diff --git a/clients/sockethub-1.json b/clients/sockethub-1.json new file mode 100644 index 0000000..6d3b935 --- /dev/null +++ b/clients/sockethub-1.json @@ -0,0 +1,4 @@ +{ + "name": "sockethub-1", + "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0DbJHhPvJTaKfPHoOa+i\nr49DPFVvAgUVsbVUsgRvnAW/ngoRwhSHTaHBIfmuvNI/6yoSTy2xZzIgsDGZDeEe\n/gSlmUjbh4Udex9pZ3fotdPjTpqDQMk8KpmCjF9SWstfYwYhcx2oLiImdeSLvn6l\nyMrpx/rieDHn8rEs/cvqkrCCPLtOxLByC92iy5wkz64PouU0/VUud0G7o02pTXd4\n0WULNpehRGl3paNmqCQmShUxeRMkJYOYspHyc13qwQHD35hOBk7A6QDDRHMRbcoI\nLE36q5Mkyh2YGbDhSemoyh+lwqYOHfYJy9gWrIvPEbg6us0yXK1xq1kifPKB9zQj\n4QIDAQAB\n-----END PUBLIC KEY-----\n" +} \ No newline at end of file diff --git a/nodes b/nodes index 9fd2015..a0396e9 160000 --- a/nodes +++ b/nodes @@ -1 +1 @@ -Subproject commit 9fd20154f7d503a9e7dac6799c8dfc1423e2d6b1 +Subproject commit a0396e959b4b65ea720c977cf345b412d7242e76 diff --git a/roles/openresty_proxy.rb b/roles/openresty_proxy.rb index 42a3ff2..b6b8eaf 100644 --- a/roles/openresty_proxy.rb +++ b/roles/openresty_proxy.rb @@ -40,6 +40,7 @@ production_run_list = %w( kosmos-ipfs::nginx_public_gateway kosmos-mastodon::nginx remotestorage_discourse::nginx + sockethub::nginx role[tor_proxy] ) diff --git a/roles/sockethub.rb b/roles/sockethub.rb index 27d7584..6b7fcd4 100644 --- a/roles/sockethub.rb +++ b/roles/sockethub.rb @@ -1,10 +1,11 @@ name "sockethub" -default_attributes 'sockethub' => { - 'version' => '5.0.0-alpha.1' +default_attributes 'kosmos_redis' => { + 'requirepass' => false } run_list %w( + kosmos_redis::default sockethub::default - sockethub::proxy + sockethub::firewall ) diff --git a/site-cookbooks/kosmos_redis/attributes/default.rb b/site-cookbooks/kosmos_redis/attributes/default.rb index adab69b..b2ea82f 100644 --- a/site-cookbooks/kosmos_redis/attributes/default.rb +++ b/site-cookbooks/kosmos_redis/attributes/default.rb @@ -3,3 +3,4 @@ default["kosmos_redis"]["add_redisio_repository"] = true default["kosmos_redis"]["package_name"] = "redis" default["kosmos_redis"]["port"] = 6379 +default["kosmos_redis"]["requirepass"] = true diff --git a/site-cookbooks/kosmos_redis/recipes/default.rb b/site-cookbooks/kosmos_redis/recipes/default.rb index 33401ee..14046df 100644 --- a/site-cookbooks/kosmos_redis/recipes/default.rb +++ b/site-cookbooks/kosmos_redis/recipes/default.rb @@ -7,7 +7,7 @@ include_recipe "kosmos_redis::repo" if node["kosmos_redis"]["add_redisio_repository"] -credentials = data_bag_item("credentials", "redis") +credentials = data_bag_item("credentials", "redis") if node["kosmos_redis"]["requirepass"] redisio_install "default" do package_install true @@ -17,6 +17,6 @@ end redisio_server node["kosmos_redis"]["port"].to_s do package_install true package_name node["kosmos_redis"]["package_name"] - requirepass credentials["password"] + requirepass credentials["password"] if node["kosmos_redis"]["requirepass"] breadcrumb false end diff --git a/site-cookbooks/sockethub/CHANGELOG.md b/site-cookbooks/sockethub/CHANGELOG.md index fdd6020..e5bc8c5 100644 --- a/site-cookbooks/sockethub/CHANGELOG.md +++ b/site-cookbooks/sockethub/CHANGELOG.md @@ -1,6 +1,14 @@ -sockethub CHANGELOG -=================== +CHANGELOG +========= + +0.3.0 +----- +- Update to sockethub 5.0.0-alpha.25 +- Serve via openresty proxy (tls_cert_for + openresty_site) instead of + a directly managed nginx on the VM +- Generate sockethub.config.json (trustProxy, reconnectIpSource) +- Restrict the service port to the internal 10.1.1.0/24 network 0.1.0 ----- -- [Greg Karékinian] - Initial release of sockethub +- Initial release of sockethub cookbook diff --git a/site-cookbooks/sockethub/README.md b/site-cookbooks/sockethub/README.md index 5158dcd..9b1c85b 100644 --- a/site-cookbooks/sockethub/README.md +++ b/site-cookbooks/sockethub/README.md @@ -7,27 +7,10 @@ Attributes ---------- #### sockethub::default - - - - - - - - - - - - - - - - - - - -
KeyTypeDescriptionDefault
['sockethub']['port']IntegerThe local port to run sockethub on10551
['sockethub']['external_port']IntegerThe external port to run sockethub on. This will also open the port on the firewall10550
-Right now the nginx vhost is hardcoded: sockethub.kosmos.org - -Sockethub will be available under https://sockethub.kosmos.org:10550 +| Key | Type | Description | Default | +| --- | --- | --- | --- | +| `['sockethub']['version']` | String | The npm version of sockethub to install | `5.0.0-alpha.25` | +| `['sockethub']['port']` | Integer | The local port to run sockethub on | `10550` | +| `['sockethub']['domain']` | String | The public domain served by the openresty proxy | `sockethub.kosmos.org` | +| `['sockethub']['log_level']` | String | Console log level (error, warn, info, debug) | `info` | diff --git a/site-cookbooks/sockethub/attributes/default.rb b/site-cookbooks/sockethub/attributes/default.rb index 18a135b..1d367c0 100644 --- a/site-cookbooks/sockethub/attributes/default.rb +++ b/site-cookbooks/sockethub/attributes/default.rb @@ -1,5 +1,4 @@ -node.default['sockethub']['port'] = '10551' -node.default['sockethub']['external_port'] = '10550' -node.default['sockethub']['version'] = '4.1.0' -node.default['sockethub']['nginx']['server_name'] = 'sockethub.kosmos.org' -node.default['sockethub']['debug_logs'] = 'sockethub*' +node.default['sockethub']['version'] = '5.0.0-alpha.25' +node.default['sockethub']['port'] = '10550' +node.default['sockethub']['domain'] = 'sockethub.kosmos.org' +node.default['sockethub']['log_level'] = 'info' \ No newline at end of file diff --git a/site-cookbooks/sockethub/metadata.rb b/site-cookbooks/sockethub/metadata.rb index def42c4..43de904 100644 --- a/site-cookbooks/sockethub/metadata.rb +++ b/site-cookbooks/sockethub/metadata.rb @@ -4,9 +4,9 @@ maintainer_email 'mail@kosmos.org' license 'MIT' description 'Installs/Configures sockethub' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '0.2.0' +version '0.3.0' depends 'firewall' -depends 'redisio' +depends 'kosmos-base' depends 'kosmos-nodejs' -depends 'kosmos-nginx' +depends 'kosmos_openresty' \ No newline at end of file diff --git a/site-cookbooks/sockethub/recipes/default.rb b/site-cookbooks/sockethub/recipes/default.rb index 353baee..b22f626 100644 --- a/site-cookbooks/sockethub/recipes/default.rb +++ b/site-cookbooks/sockethub/recipes/default.rb @@ -3,10 +3,7 @@ # Recipe:: default # -include_recipe 'redisio::default' -include_recipe 'redisio::enable' - -node.override["kosmos_nodejs"]["version"] = "24.18.0" +node.override["kosmos_nodejs"]["version"] = "24.21.0" include_recipe 'kosmos-nodejs' user = "sockethub" @@ -27,6 +24,24 @@ end npm_package "sockethub" do version node['sockethub']['version'] + auto_update false +end + +directory "/etc/sockethub" do + owner user + group group + mode 0750 +end + +template "/etc/sockethub/sockethub.config.json" do + source "sockethub.config.json.erb" + owner user + group group + mode 0640 + variables port: node['sockethub']['port'], + domain: node['sockethub']['domain'], + log_level: node['sockethub']['log_level'] + notifies :restart, 'systemd_unit[sockethub_nodejs.service]', :delayed end execute "systemctl daemon-reload" do @@ -34,17 +49,6 @@ execute "systemctl daemon-reload" do action :nothing end -environment_variables = { - 'PORT' => node['sockethub']['port'], - # Use the second database (index starts at 0) - 'REDIS_URL' => "redis://localhost:6379/1" -} -unless node['sockethub']['debug_logs'].nil? - environment_variables['DEBUG'] = node['sockethub']['debug_logs'] -end - -environment = environment_variables.map{|k, v| "'#{k}=#{v}'"}.join(' ') - systemd_unit "sockethub_nodejs.service" do content <<-EOF [Unit] @@ -56,7 +60,7 @@ After=redis@6379.service ExecStart=#{entry} User=#{user} Group=#{group} -Environment=#{environment} +Environment=SOCKETHUB_CONFIG=/etc/sockethub/sockethub.config.json Restart=always [Install] diff --git a/site-cookbooks/sockethub/recipes/firewall.rb b/site-cookbooks/sockethub/recipes/firewall.rb index 08f58b0..381188e 100644 --- a/site-cookbooks/sockethub/recipes/firewall.rb +++ b/site-cookbooks/sockethub/recipes/firewall.rb @@ -7,7 +7,8 @@ unless node.chef_environment == "development" include_recipe "kosmos-base::firewall" firewall_rule 'sockethub' do - port node['sockethub']['external_port'].to_i + port node['sockethub']['port'].to_i + source '10.1.1.0/24' protocol :tcp command :allow end diff --git a/site-cookbooks/sockethub/recipes/nginx.rb b/site-cookbooks/sockethub/recipes/nginx.rb new file mode 100644 index 0000000..46d9833 --- /dev/null +++ b/site-cookbooks/sockethub/recipes/nginx.rb @@ -0,0 +1,27 @@ +# +# Cookbook Name:: sockethub +# Recipe:: nginx +# + +domain = node['sockethub']['domain'] + +sockethub_node = search(:node, 'role:sockethub').first + +if sockethub_node.nil? + Chef::Log.warn("No node found with 'sockethub' role. Not configuring openresty site.") + return +end + +tls_cert_for domain do + auth 'gandi_dns' + action :create +end + +openresty_site domain do + template 'nginx_conf_sockethub.erb' + variables domain: domain, + upstream_host: sockethub_node['knife_zero']['host'], + upstream_port: node['sockethub']['port'], + ssl_cert: "/etc/letsencrypt/live/#{domain}/fullchain.pem", + ssl_key: "/etc/letsencrypt/live/#{domain}/privkey.pem" +end diff --git a/site-cookbooks/sockethub/recipes/proxy.rb b/site-cookbooks/sockethub/recipes/proxy.rb deleted file mode 100644 index 17744f7..0000000 --- a/site-cookbooks/sockethub/recipes/proxy.rb +++ /dev/null @@ -1,58 +0,0 @@ -# -# Cookbook Name:: sockethub -# Recipe:: proxy -# - -include_recipe 'sockethub::firewall' -include_recipe 'kosmos-nginx' -include_recipe "kosmos-base::letsencrypt" - -server_name = node['sockethub']['nginx']['server_name'] - -nginx_post_hook = <<-EOF -#!/usr/bin/env bash - -set -e - -systemctl reload nginx -EOF - -file "/etc/letsencrypt/renewal-hooks/post/nginx" do - content nginx_post_hook - mode 0755 - owner "root" - group "root" -end - -gandi_api_credentials = data_bag_item('credentials', 'gandi_api') - -template "/root/gandi_dns_certbot_hook.sh" do - variables gandi_api_key: gandi_api_credentials["key"] - mode 0770 -end - -# Generate a Let's Encrypt cert (only if no cert has been generated before). -# The systemd timer will take care of renewing -execute "letsencrypt cert for sockethub" do - command "certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos --manual-auth-hook \"/root/gandi_dns_certbot_hook.sh auth\" --manual-cleanup-hook \"/root/gandi_dns_certbot_hook.sh cleanup\" --deploy-hook \"/etc/letsencrypt/renewal-hooks/post/nginx\" --email ops@kosmos.org -d #{server_name} -n" - not_if do - File.exist?("/etc/letsencrypt/live/#{server_name}/fullchain.pem") - end -end - -template "#{node['nginx']['dir']}/sites-available/#{server_name}" do - source 'nginx_conf_sockethub.erb' - owner 'www-data' - mode 0640 - variables sockethub_port: node['sockethub']['port'], - sockethub_external_port: node['sockethub']['external_port'], - server_name: server_name, - ssl_cert: "/etc/letsencrypt/live/#{server_name}/fullchain.pem", - ssl_key: "/etc/letsencrypt/live/#{server_name}/privkey.pem" - notifies :reload, 'service[nginx]', :delayed -end - -nginx_site server_name do - action :enable -end - diff --git a/site-cookbooks/sockethub/templates/default/nginx_conf_sockethub.erb b/site-cookbooks/sockethub/templates/default/nginx_conf_sockethub.erb index a25bd84..2f4604d 100644 --- a/site-cookbooks/sockethub/templates/default/nginx_conf_sockethub.erb +++ b/site-cookbooks/sockethub/templates/default/nginx_conf_sockethub.erb @@ -1,6 +1,5 @@ -# Generated by Chef upstream _sockethub { - server localhost:<%= @sockethub_port %>; + server <%= @upstream_host %>:<%= @upstream_port %>; } map $http_upgrade $connection_upgrade { @@ -9,34 +8,25 @@ map $http_upgrade $connection_upgrade { } server { - <% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%> - listen <%= @sockethub_external_port %> ssl http2; - add_header Strict-Transport-Security "max-age=15768000"; - <% else -%> - listen <%= @sockethub_external_port %>; - <% end -%> + server_name <%= @domain %>; + listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2; + listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2; - server_name <%= @server_name %>; + access_log "/var/log/nginx/<%= @domain %>.access.log" json; + error_log "/var/log/nginx/<%= @domain %>.error.log"; - access_log <%= node[:nginx][:log_dir] %>/sockethub.access.log json; - error_log <%= node[:nginx][:log_dir] %>/sockethub.error.log warn; - - # We might need real ETags, disable those for now - gzip off; + ssl_certificate <%= @ssl_cert %>; + ssl_certificate_key <%= @ssl_key %>; location / { - # Increase number of buffers. Default is 8 - proxy_buffers 1024 8k; - + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://_sockethub; proxy_http_version 1.1; - # Enable WebSockets proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - } - - <% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%> - ssl_certificate <%= @ssl_cert %>; - ssl_certificate_key <%= @ssl_key %>; - <% end -%> -} + proxy_read_timeout 300s; + } +} \ No newline at end of file diff --git a/site-cookbooks/sockethub/templates/default/sockethub.config.json.erb b/site-cookbooks/sockethub/templates/default/sockethub.config.json.erb new file mode 100644 index 0000000..be60db8 --- /dev/null +++ b/site-cookbooks/sockethub/templates/default/sockethub.config.json.erb @@ -0,0 +1,26 @@ +{ + "examples": false, + "logging": { + "level": "<%= @log_level %>", + "file": "" + }, + "public": { + "protocol": "https", + "host": "<%= @domain %>", + "port": 443, + "path": "/" + }, + "redis": { + "url": "redis://127.0.0.1:6379/0" + }, + "sockethub": { + "port": <%= @port.to_i %>, + "host": "0.0.0.0", + "path": "/sockethub", + "trustProxy": 1 + }, + "credentialCheck": { + "reconnectIpSource": "proxy", + "proxyHeader": "x-forwarded-for" + } +} diff --git a/site-cookbooks/sockethub/templates/gandi_dns_certbot_hook.sh.erb b/site-cookbooks/sockethub/templates/gandi_dns_certbot_hook.sh.erb deleted file mode 100755 index d0ed9dc..0000000 --- a/site-cookbooks/sockethub/templates/gandi_dns_certbot_hook.sh.erb +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash -# - -set -euf -o pipefail - -# ************** USAGE ************** -# -# Example usage (with this hook file saved in /root/): -# -# sudo su - -# certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos -d "5apps.com" -d muc.5apps.com -d "xmpp.5apps.com" \ -# --manual-auth-hook "/root/letsencrypt_hook.sh auth" --manual-cleanup-hook "/root/letsencrypt_hook.sh cleanup" -# -# This hook requires configuration, continue reading. -# -# ************** CONFIGURATION ************** -# -# GANDI_API_KEY: Your Gandi Live API key -# -# PROVIDER_UPDATE_DELAY: -# How many seconds to wait after updating your DNS records. This may be required, -# depending on how slow your DNS host is to begin serving new DNS records after updating -# them via the API. 30 seconds is a safe default, but some providers can be very slow -# (e.g. Linode). -# -# Defaults to 30 seconds. -# -GANDI_API_KEY="<%= @gandi_api_key %>" -PROVIDER_UPDATE_DELAY=30 - -regex='.*\.(.*\..*)' -if [[ $CERTBOT_DOMAIN =~ $regex ]] -then - DOMAIN="${BASH_REMATCH[1]}" -else - DOMAIN="${CERTBOT_DOMAIN}" -fi - -# To be invoked via Certbot's --manual-auth-hook -function auth { - curl -s -D- -H "Content-Type: application/json" \ - -H "X-Api-Key: ${GANDI_API_KEY}" \ - -d "{\"rrset_name\": \"_acme-challenge.${CERTBOT_DOMAIN}.\", - \"rrset_type\": \"TXT\", - \"rrset_ttl\": 3600, - \"rrset_values\": [\"${CERTBOT_VALIDATION}\"]}" \ - "https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records" - - - sleep ${PROVIDER_UPDATE_DELAY} -} - -# To be invoked via Certbot's --manual-cleanup-hook -function cleanup { - curl -s -X DELETE -H "Content-Type: application/json" \ - -H "X-Api-Key: ${GANDI_API_KEY}" \ - https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records/_acme-challenge.${CERTBOT_DOMAIN}./TXT -} - -HANDLER=$1; shift; -if [ -n "$(type -t $HANDLER)" ] && [ "$(type -t $HANDLER)" = function ]; then - $HANDLER "$@" -fi