Migrate ejabberd uploads to mod_s3_upload and Garage
In addition to installing and configuring the new module, this also enables public access to the S3 API via `bucket-name.s3.kosmos.org` as well as Web access on `bucket-name.web.s3.kosmos.org` (when enabled). Also includes some drive-by improvements to Chef attribute naming and usage. Co-authored-by: Greg Karékinian <greg@karekinian.com>
This commit is contained in:
@@ -1,16 +1,7 @@
|
||||
node.default["kosmos-ejabberd"]["version"] = "23.04"
|
||||
node.default["kosmos-ejabberd"]["package_version"] = "1"
|
||||
node.default["kosmos-ejabberd"]["checksum"] = "0bc273043085f8bc333abd176e767cc0a77b7336014777c2f2d10ae27e3d8aec"
|
||||
node.default["kosmos-ejabberd"]["turn_ip_address"] = "148.251.83.201"
|
||||
node.default["kosmos-ejabberd"]["stun_turn_port"] = 3478
|
||||
node.default["kosmos-ejabberd"]["turn_min_port"] = 50000
|
||||
node.default["kosmos-ejabberd"]["turn_max_port"] = 50050
|
||||
|
||||
node.default["kosmos-ejabberd"]["uploads"] = {
|
||||
"domain" => "uploads.kosmos.chat",
|
||||
"max_upload_size_mb" => "100",
|
||||
"upload.pm" => {
|
||||
"repo" => "https://gitea.kosmos.org/kosmos/ngx_http_upload.git",
|
||||
"revision" => "0.2"
|
||||
}
|
||||
}
|
||||
node.default["ejabberd"]["version"] = "23.04"
|
||||
node.default["ejabberd"]["package_version"] = "1"
|
||||
node.default["ejabberd"]["checksum"] = "0bc273043085f8bc333abd176e767cc0a77b7336014777c2f2d10ae27e3d8aec"
|
||||
node.default["ejabberd"]["turn_ip_address"] = nil
|
||||
node.default["ejabberd"]["stun_turn_port"] = 3478
|
||||
node.default["ejabberd"]["turn_min_port"] = 50000
|
||||
node.default["ejabberd"]["turn_max_port"] = 50050
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
ejabberd_credentials = data_bag_item("credentials", "ejabberd")
|
||||
|
||||
ejabberd_version = node["kosmos-ejabberd"]["version"]
|
||||
package_checksum = node["kosmos-ejabberd"]["checksum"]
|
||||
ejabberd_version = node["ejabberd"]["version"]
|
||||
package_checksum = node["ejabberd"]["checksum"]
|
||||
package_path = "#{Chef::Config['file_cache_path']}/ejabberd_#{ejabberd_version}_amd64.deb"
|
||||
|
||||
remote_file package_path do
|
||||
source "https://github.com/processone/ejabberd/releases/download/#{ejabberd_version}/ejabberd_#{ejabberd_version}-#{node["kosmos-ejabberd"]["package_version"]}_amd64.deb"
|
||||
source "https://github.com/processone/ejabberd/releases/download/#{ejabberd_version}/ejabberd_#{ejabberd_version}-#{node["ejabberd"]["package_version"]}_amd64.deb"
|
||||
checksum package_checksum
|
||||
notifies :install, "dpkg_package[ejabberd]", :immediately
|
||||
end
|
||||
@@ -22,6 +22,21 @@ dpkg_package "ejabberd" do
|
||||
action :nothing
|
||||
end
|
||||
|
||||
execute "update contrib modules" do
|
||||
command "ejabberdctl modules_update_specs"
|
||||
end
|
||||
|
||||
%w[mod_s3_upload].each do |emod|
|
||||
execute "install #{emod}" do
|
||||
command "ejabberdctl module_install #{emod}"
|
||||
not_if { ::File.exist?("/opt/ejabberd/.ejabberd-modules/#{emod}/ebin") }
|
||||
end
|
||||
|
||||
file "/opt/ejabberd/.ejabberd-modules/#{emod}/conf/#{emod}.yml" do
|
||||
action :delete
|
||||
end
|
||||
end
|
||||
|
||||
file "/opt/ejabberd/.erlang.cookie" do
|
||||
mode "0400"
|
||||
owner "ejabberd"
|
||||
@@ -70,7 +85,7 @@ hosts = [
|
||||
ldap_enabled: true,
|
||||
ldap_password: ejabberd_credentials['kosmos_ldap_password'],
|
||||
append_host_config: <<-EOF
|
||||
modules:
|
||||
modules:
|
||||
mod_disco:
|
||||
extra_domains:
|
||||
- kosmos.chat
|
||||
@@ -92,12 +107,6 @@ modules:
|
||||
default_room_options:
|
||||
mam: true
|
||||
preload_rooms: true
|
||||
mod_muc_rtbl: {}
|
||||
mod_http_upload:
|
||||
put_url: "https://uploads.kosmos.chat/8af2c77"
|
||||
external_secret: "#{ejabberd_credentials["uploads_secret"]}"
|
||||
max_size: 104857600
|
||||
thumbnail: false # otherwise needs the identify command from ImageMagick installed
|
||||
EOF
|
||||
},
|
||||
{
|
||||
@@ -106,7 +115,7 @@ modules:
|
||||
ldap_enabled: true,
|
||||
ldap_password: ejabberd_credentials['5apps_ldap_password'],
|
||||
append_host_config: <<-EOF
|
||||
modules:
|
||||
modules:
|
||||
mod_disco:
|
||||
extra_domains:
|
||||
- muc.5apps.com
|
||||
@@ -133,12 +142,6 @@ modules:
|
||||
persistent: true
|
||||
mam: true
|
||||
preload_rooms: true
|
||||
mod_muc_rtbl: {}
|
||||
mod_http_upload:
|
||||
put_url: "https://uploads.kosmos.chat/2802cfe"
|
||||
external_secret: "#{ejabberd_credentials["uploads_secret"]}"
|
||||
max_size: 104857600
|
||||
thumbnail: false # otherwise needs the identify command from ImageMagick installed
|
||||
EOF
|
||||
}
|
||||
]
|
||||
@@ -182,12 +185,19 @@ template "/opt/ejabberd/conf/ejabberd.yml" do
|
||||
admin_users: admin_users,
|
||||
stun_auth_realm: "kosmos.org",
|
||||
stun_secret: ejabberd_credentials['stun_secret'],
|
||||
turn_ip_address: node["kosmos-ejabberd"]["turn_ip_address"],
|
||||
stun_turn_port: node["kosmos-ejabberd"]["stun_turn_port"],
|
||||
turn_min_port: node["kosmos-ejabberd"]["turn_min_port"],
|
||||
turn_max_port: node["kosmos-ejabberd"]["turn_max_port"],
|
||||
turn_ip_address: node["ejabberd"]["turn_ip_address"],
|
||||
stun_turn_port: node["ejabberd"]["stun_turn_port"],
|
||||
turn_min_port: node["ejabberd"]["turn_min_port"],
|
||||
turn_max_port: node["ejabberd"]["turn_max_port"],
|
||||
private_ip_address: node["knife_zero"]["host"],
|
||||
akkounts_ip_addresses: akkounts_ip_addresses
|
||||
akkounts_ip_addresses: akkounts_ip_addresses,
|
||||
mod_s3_upload: {
|
||||
region: "garage",
|
||||
bucket_url: "https://#{node["garage"]["xmpp_upload_bucket"]}.#{node["garage"]["s3_api_root_domain"]}",
|
||||
download_url: "https://media.kosmos.chat",
|
||||
key_id: ejabberd_credentials['s3_key_id'],
|
||||
secret_key: ejabberd_credentials['s3_secret_key']
|
||||
}
|
||||
notifies :reload, "service[ejabberd]", :delayed
|
||||
end
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ firewall_rule 'erlang_cluster' do
|
||||
end
|
||||
|
||||
firewall_rule 'ejabberd_stun_turn' do
|
||||
port node["kosmos-ejabberd"]["stun_turn_port"]
|
||||
port node["ejabberd"]["stun_turn_port"]
|
||||
protocol :udp
|
||||
command :allow
|
||||
end
|
||||
|
||||
firewall_rule 'ejabberd_turn' do
|
||||
port node["kosmos-ejabberd"]["turn_min_port"]..node["kosmos-ejabberd"]["turn_max_port"]
|
||||
port node["ejabberd"]["turn_min_port"]..node["ejabberd"]["turn_max_port"]
|
||||
protocol :udp
|
||||
command :allow
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ for domain in $RENEWED_DOMAINS; do
|
||||
cp "${RENEWED_LINEAGE}/fullchain.pem" /opt/ejabberd/conf/$domain.crt
|
||||
chown ejabberd:ejabberd /opt/ejabberd/conf/$domain.*
|
||||
chmod 600 /opt/ejabberd/conf/$domain.*
|
||||
/opt/ejabberd-#{node["kosmos-ejabberd"]["version"]}/bin/ejabberdctl reload_config
|
||||
/opt/ejabberd-#{node["ejabberd"]["version"]}/bin/ejabberdctl reload_config
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -20,20 +20,20 @@ end
|
||||
openresty_stream "ejabberd" do
|
||||
template "nginx_conf_streams.erb"
|
||||
variables ejabberd_hosts: ["10.1.1.113"],
|
||||
stun_turn_port: node["kosmos-ejabberd"]["stun_turn_port"],
|
||||
turn_min_port: node["kosmos-ejabberd"]["turn_min_port"],
|
||||
turn_max_port: node["kosmos-ejabberd"]["turn_max_port"]
|
||||
stun_turn_port: node["ejabberd"]["stun_turn_port"],
|
||||
turn_min_port: node["ejabberd"]["turn_min_port"],
|
||||
turn_max_port: node["ejabberd"]["turn_max_port"]
|
||||
action :enable
|
||||
end
|
||||
|
||||
firewall_rule 'ejabberd_stun_turn' do
|
||||
port node["kosmos-ejabberd"]["stun_turn_port"]
|
||||
port node["ejabberd"]["stun_turn_port"]
|
||||
protocol :udp
|
||||
command :allow
|
||||
end
|
||||
|
||||
firewall_rule 'ejabberd_turn' do
|
||||
port node["kosmos-ejabberd"]["turn_min_port"]..node["kosmos-ejabberd"]["turn_max_port"]
|
||||
port node["ejabberd"]["turn_min_port"]..node["ejabberd"]["turn_max_port"]
|
||||
protocol :udp
|
||||
command :allow
|
||||
end
|
||||
|
||||
@@ -2,28 +2,6 @@
|
||||
# Cookbook:: kosmos-ejabberd
|
||||
# Recipe:: pg_db
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright:: 2020, Kosmos Developers
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ include_recipe "kosmos-nginx::with_perl"
|
||||
ejabberd_credentials = data_bag_item("credentials", "ejabberd")
|
||||
uploads_secret = ejabberd_credentials["uploads_secret"]
|
||||
|
||||
upload_config = node["kosmos-ejabberd"]["uploads"]
|
||||
upload_config = node["ejabberd"]["uploads"]
|
||||
domain = upload_config["domain"]
|
||||
|
||||
git "/opt/upload.pm" do
|
||||
|
||||
@@ -77,7 +77,6 @@ listen:
|
||||
request_handlers:
|
||||
"/ws": ejabberd_http_ws
|
||||
"/bosh": mod_bosh
|
||||
"/upload": mod_http_upload
|
||||
"/admin": ejabberd_web_admin
|
||||
custom_headers:
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
@@ -261,6 +260,22 @@ modules:
|
||||
mod_stream_mgmt: {}
|
||||
mod_s2s_dialback: {}
|
||||
mod_http_api: {}
|
||||
mod_muc_rtbl: {}
|
||||
mod_s3_upload:
|
||||
region: <%= @mod_s3_upload[:region] %>
|
||||
bucket_url: <%= @mod_s3_upload[:bucket_url] %>
|
||||
download_url: <%= @mod_s3_upload[:download_url] %>
|
||||
access_key_id: <%= @mod_s3_upload[:key_id] %>
|
||||
access_key_secret: <%= @mod_s3_upload[:secret_key] %>
|
||||
max_size: 104857600
|
||||
put_ttl: 600
|
||||
set_public: true
|
||||
service_name: 'S3 Upload'
|
||||
access: local
|
||||
hosts:
|
||||
<% @hosts.each do |host| -%>
|
||||
- "upload.<%= host[:name] %>"
|
||||
<% end -%>
|
||||
|
||||
allow_contrib_modules: true
|
||||
|
||||
|
||||
@@ -21,5 +21,5 @@ host_config:
|
||||
|
||||
append_host_config:
|
||||
"<%= @host[:name] %>":
|
||||
<%= @host[:append_host_config].chomp %>
|
||||
<%= @host[:append_host_config].chomp %>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
node.default['garage']['version'] = '0.8.0'
|
||||
node.default['garage']['checksum']['amd64'] = '66dd2ea1f677281a43e10eb619523b1b269f8fde9047ce8caa70958f3b13ca74'
|
||||
node.default['garage']['version'] = '0.8.4'
|
||||
node.default['garage']['checksum']['amd64'] = '45403d494847c42efc620f66c52d27c0bb0446a490e62f5b0b87489a588a767d'
|
||||
node.default['garage']['replication_mode'] = 'none'
|
||||
node.default['garage']['s3_api_port'] = 3900
|
||||
node.default['garage']['rpc_port'] = 3901
|
||||
@@ -9,3 +9,4 @@ node.default['garage']['k2v_api_port'] = 3904
|
||||
node.default['garage']['s3_api_root_domain'] = '.s3.garage.localhost'
|
||||
node.default['garage']['s3_web_root_domain'] = '.web.garage.localhost'
|
||||
node.default['garage']['s3_web_domains'] = []
|
||||
node.default['garage']['xmpp_upload_bucket'] = nil
|
||||
|
||||
22
site-cookbooks/kosmos_garage/recipes/nginx_s3.rb
Normal file
22
site-cookbooks/kosmos_garage/recipes/nginx_s3.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Cookbook Name:: kosmos_garage
|
||||
# Recipe:: nginx_s3
|
||||
#
|
||||
|
||||
domain_name = node['garage']['s3_api_root_domain']
|
||||
server_name = "*.#{domain_name}"
|
||||
|
||||
tls_cert_for domain_name do
|
||||
domain [domain_name, server_name]
|
||||
auth "gandi_dns"
|
||||
action :create
|
||||
end
|
||||
|
||||
openresty_site domain_name do
|
||||
template "nginx_conf_s3.erb"
|
||||
variables server_name: "#{domain_name} #{server_name}",
|
||||
domain_name: domain_name,
|
||||
xmpp_upload_bucket: node['garage']['xmpp_upload_bucket'],
|
||||
ssl_cert: "/etc/letsencrypt/live/#{domain_name}/fullchain.pem",
|
||||
ssl_key: "/etc/letsencrypt/live/#{domain_name}/privkey.pem"
|
||||
end
|
||||
@@ -15,18 +15,41 @@ proxy_cache_path #{node['openresty']['cache_dir']}/garage
|
||||
EOF
|
||||
end
|
||||
|
||||
domains = node['garage']['s3_web_domains']
|
||||
#
|
||||
# Root domain for public Web access via bucket-name.root-domain.tld
|
||||
#
|
||||
|
||||
domains.each do |server_name|
|
||||
tls_cert_for server_name do
|
||||
domain_name = node['garage']['s3_web_root_domain']
|
||||
server_name = "*.#{domain_name}"
|
||||
|
||||
tls_cert_for server_name do
|
||||
auth "gandi_dns"
|
||||
action :create
|
||||
end
|
||||
|
||||
openresty_site domain_name do
|
||||
template "nginx_conf_web.erb"
|
||||
variables server_name: server_name,
|
||||
domain_name: domain_name,
|
||||
ssl_cert: "/etc/letsencrypt/live/#{domain_name}/fullchain.pem",
|
||||
ssl_key: "/etc/letsencrypt/live/#{domain_name}/privkey.pem"
|
||||
end
|
||||
|
||||
#
|
||||
# Custom domains for public Web access
|
||||
#
|
||||
|
||||
node['garage']['s3_web_domains'].each do |domain_name|
|
||||
tls_cert_for domain_name do
|
||||
auth "gandi_dns"
|
||||
action :create
|
||||
end
|
||||
|
||||
openresty_site server_name do
|
||||
openresty_site domain_name do
|
||||
template "nginx_conf_web.erb"
|
||||
variables server_name: server_name,
|
||||
ssl_cert: "/etc/letsencrypt/live/#{server_name}/fullchain.pem",
|
||||
ssl_key: "/etc/letsencrypt/live/#{server_name}/privkey.pem"
|
||||
variables server_name: domain_name,
|
||||
domain_name: domain_name,
|
||||
ssl_cert: "/etc/letsencrypt/live/#{domain_name}/fullchain.pem",
|
||||
ssl_key: "/etc/letsencrypt/live/#{domain_name}/privkey.pem"
|
||||
end
|
||||
end
|
||||
|
||||
49
site-cookbooks/kosmos_garage/templates/nginx_conf_s3.erb
Normal file
49
site-cookbooks/kosmos_garage/templates/nginx_conf_s3.erb
Normal file
@@ -0,0 +1,49 @@
|
||||
upstream garage_s3 {
|
||||
server 127.0.0.1:3900;
|
||||
}
|
||||
|
||||
server {
|
||||
listen <%= "#{node[:openresty][:listen_ip]}:" if node[:openresty][:listen_ip] %>443 ssl http2;
|
||||
listen [::]:443 http2 ssl;
|
||||
|
||||
ssl_certificate <%= @ssl_cert %>;
|
||||
ssl_certificate_key <%= @ssl_key %>;
|
||||
|
||||
server_name <%= @server_name %>;
|
||||
|
||||
access_log <%= node[:openresty][:log_dir] %>/<%= @domain_name %>.access.log json;
|
||||
error_log <%= node[:openresty][:log_dir] %>/<%= @domain_name %>.error.log warn;
|
||||
|
||||
error_page 401 403 404 500 /__empty-page.html;
|
||||
|
||||
location = /__empty-page.html {
|
||||
internal;
|
||||
return 200 "";
|
||||
}
|
||||
|
||||
location / {
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Content-Length 0;
|
||||
add_header Content-Type text/plain;
|
||||
return 200;
|
||||
}
|
||||
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_request_buffering off;
|
||||
proxy_max_temp_file_size 0;
|
||||
|
||||
proxy_pass http://garage_s3;
|
||||
|
||||
<% if @xmpp_upload_bucket %>
|
||||
# Some XMPP clients (e.g. Beagle, Siskin, Snikket, Monal) require a 201 CREATED
|
||||
# for PUT requests to be considered successful
|
||||
header_filter_by_lua_block {
|
||||
if ngx.var.http_host == "<%= @xmpp_upload_bucket %>.<%= @domain_name %>" and
|
||||
ngx.req.get_method() == "PUT" and ngx.status == ngx.HTTP_OK then
|
||||
ngx.status = ngx.HTTP_CREATED
|
||||
end
|
||||
}
|
||||
<% end %>
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
server {
|
||||
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
|
||||
listen <%= "#{node[:openresty][:listen_ip]}:" if node[:openresty][:listen_ip] %>443 ssl http2;
|
||||
listen [::]:443 http2 ssl;
|
||||
|
||||
server_name <%= @server_name %>;
|
||||
|
||||
access_log off;
|
||||
|
||||
ssl_certificate <%= @ssl_cert %>;
|
||||
ssl_certificate_key <%= @ssl_key %>;
|
||||
|
||||
access_log <%= node[:openresty][:log_dir] %>/<%= @domain_name %>.access.log json;
|
||||
error_log <%= node[:openresty][:log_dir] %>/<%= @domain_name %>.error.log warn;
|
||||
|
||||
error_page 401 403 404 500 /__empty-page.html;
|
||||
|
||||
location = /__empty-page.html {
|
||||
|
||||
Reference in New Issue
Block a user