diff --git a/.gitmodules b/.gitmodules index 7167701..3f36f91 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "site-cookbooks/openresty"] path = site-cookbooks/openresty url = https://github.com/67P/chef-openresty.git +[submodule "site-cookbooks/strfry"] + path = site-cookbooks/strfry + url = git@gitea.kosmos.org:kosmos/strfry-cookbook.git +[submodule "site-cookbooks/deno"] + path = site-cookbooks/deno + url = git@gitea.kosmos.org:kosmos/deno-cookbook.git diff --git a/clients/strfry-1.json b/clients/strfry-1.json new file mode 100644 index 0000000..3ca35c9 --- /dev/null +++ b/clients/strfry-1.json @@ -0,0 +1,4 @@ +{ + "name": "strfry-1", + "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzDV/RMGMXVDbvoA6PNh8\nQzhtHwYDCFcUSkbrwP6tzh6GpVunGEOdOdhj2V63T2tF1H+lujxQXh5pK7C0D6VZ\niO04ftJlo7/svyxUcwWr+znyN5sFdQRh3cBZiGSBYolizwoqgtPFlbNhmWAzV0Du\n9t8mhz70IK3B+UdwWyHtoK0NNsJGnQ9YzAvcjyDmEO/3sCjAhNnxVpmXftpcSmd9\nMonzFtIDBbRRll4AHZYRbmXCzx63+VmelvdnufnbY82liol0zzBwJaBD1wyNlG0y\ni96p3Kx03bLNlIaYVGbjZeJi+6oo2VDWJ4OloLLAYoHDSipeHT9qWfUdnE6ge4Lm\nywIDAQAB\n-----END PUBLIC KEY-----\n" +} \ No newline at end of file diff --git a/data_bags/credentials/dirsrv.json b/data_bags/credentials/dirsrv.json index cf4ce41..8ab60bd 100644 --- a/data_bags/credentials/dirsrv.json +++ b/data_bags/credentials/dirsrv.json @@ -1,9 +1,30 @@ { "id": "dirsrv", + "admin_dn": { + "encrypted_data": "zRtz6Scb9WtUXGyjc0xyvsre0YvqupuaFz+RPApj7DEQTmYyZPVb\n", + "iv": "xfIXMhEBHBWqa4Dz\n", + "auth_tag": "BcA32u1njcnCZ+yrBGSceQ==\n", + "version": 3, + "cipher": "aes-256-gcm" + }, "admin_password": { - "encrypted_data": "i71l5E129mXCcDAyME8sNMUkYUlQMgt7Eh6noyFcLNgbaMo=\n", - "iv": "KNW2B8tpX7ywZwbg\n", - "auth_tag": "GawQ+FSlA5v5YVyryeUxng==\n", + "encrypted_data": "7JpXl3JZDqKWDfYt/wuNbkbob+oRuONhkuAlpqUCCEIn+tY=\n", + "iv": "Lcwc4NDzrfcBaIKQ\n", + "auth_tag": "rrePS3Bhdnwbr2d/o8vMhg==\n", + "version": 3, + "cipher": "aes-256-gcm" + }, + "service_dn": { + "encrypted_data": "sqRFiZreLeTPQljSfhAuV3DmsPxSC8tzWjCdu+WSSbO67sBQA+xhmGtzBhBD\nDZPGJw+jtAxzuVvPdAjxgAVgxXO6C6WEo87L1tdJewE=\n", + "iv": "GUEGtyRJXrPhWcUs\n", + "auth_tag": "2USsrx//3V7RCyumGCbMkg==\n", + "version": 3, + "cipher": "aes-256-gcm" + }, + "service_password": { + "encrypted_data": "f2wi8B8SEt6p5G0TF3dZ72j0vMFlvwcP1suxYnshBA==\n", + "iv": "rOnUoxbnkaJtodM+\n", + "auth_tag": "dVLCtBVMjxLfW2D8XjJBdQ==\n", "version": 3, "cipher": "aes-256-gcm" } diff --git a/environments/production.json b/environments/production.json index 4f84064..84cf15d 100644 --- a/environments/production.json +++ b/environments/production.json @@ -14,7 +14,8 @@ "public_key": "024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946" }, "nostr": { - "public_key": "b3e1b7c1660b7db0ecb93ec55c09e67961171a5c4e9e2602f1b47477ea61c50a" + "public_key": "b3e1b7c1660b7db0ecb93ec55c09e67961171a5c4e9e2602f1b47477ea61c50a", + "relay_url": "wss://nostr.kosmos.org" } }, "discourse": { @@ -101,6 +102,20 @@ }, "sentry": { "allowed_ips": "10.1.1.0/24" + }, + "strfry": { + "domain": "nostr.kosmos.org", + "real_ip_header": "x-real-ip", + "policy_path": "/opt/strfry/strfry-policy.ts", + "whitelist_pubkeys": [ + "b3e1b7c1660b7db0ecb93ec55c09e67961171a5c4e9e2602f1b47477ea61c50a" + ], + "info": { + "name": "Kosmos Relay", + "description": "Members-only nostr relay for kosmos.org users", + "pubkey": "1f79058c77a224e5be226c8f024cacdad4d741855d75ed9f11473ba8eb86e1cb", + "contact": "ops@kosmos.org" + } } } } diff --git a/nodes/draco.kosmos.org.json b/nodes/draco.kosmos.org.json index f07f268..f95e990 100644 --- a/nodes/draco.kosmos.org.json +++ b/nodes/draco.kosmos.org.json @@ -54,6 +54,7 @@ "kosmos_liquor-cabinet::nginx", "kosmos_rsk::nginx_testnet", "kosmos_rsk::nginx_mainnet", + "kosmos_strfry::nginx", "kosmos_website", "kosmos_website::default", "kosmos-akkounts::nginx", diff --git a/nodes/fornax.kosmos.org.json b/nodes/fornax.kosmos.org.json index bc81069..d5903f9 100644 --- a/nodes/fornax.kosmos.org.json +++ b/nodes/fornax.kosmos.org.json @@ -48,6 +48,7 @@ "kosmos_liquor-cabinet::nginx", "kosmos_rsk::nginx_testnet", "kosmos_rsk::nginx_mainnet", + "kosmos_strfry::nginx", "kosmos_website", "kosmos_website::default", "kosmos-akkounts::nginx", diff --git a/nodes/strfry-1.json b/nodes/strfry-1.json new file mode 100644 index 0000000..114bbb9 --- /dev/null +++ b/nodes/strfry-1.json @@ -0,0 +1,66 @@ +{ + "name": "strfry-1", + "chef_environment": "production", + "normal": { + "knife_zero": { + "host": "10.1.1.164" + } + }, + "automatic": { + "fqdn": "strfry-1", + "os": "linux", + "os_version": "5.15.0-1060-kvm", + "hostname": "strfry-1", + "ipaddress": "192.168.122.54", + "roles": [ + "base", + "kvm_guest", + "strfry", + "ldap_client" + ], + "recipes": [ + "kosmos-base", + "kosmos-base::default", + "kosmos_kvm::guest", + "kosmos-dirsrv::hostsfile", + "strfry", + "strfry::default", + "kosmos_strfry::policies", + "kosmos_strfry::firewall", + "apt::default", + "timezone_iii::default", + "timezone_iii::debian", + "ntp::default", + "ntp::apparmor", + "kosmos-base::systemd_emails", + "apt::unattended-upgrades", + "kosmos-base::firewall", + "kosmos-postfix::default", + "postfix::default", + "postfix::_common", + "postfix::_attributes", + "postfix::sasl_auth", + "hostname::default", + "deno::default" + ], + "platform": "ubuntu", + "platform_version": "22.04", + "cloud": null, + "chef_packages": { + "chef": { + "version": "18.4.12", + "chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.4.12/lib", + "chef_effortless": null + }, + "ohai": { + "version": "18.1.11", + "ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.1.11/lib/ohai" + } + } + }, + "run_list": [ + "role[base]", + "role[kvm_guest]", + "role[strfry]" + ] +} diff --git a/roles/openresty_proxy.rb b/roles/openresty_proxy.rb index 38e8bbb..c238c1b 100644 --- a/roles/openresty_proxy.rb +++ b/roles/openresty_proxy.rb @@ -28,6 +28,7 @@ production_run_list = %w( kosmos_liquor-cabinet::nginx kosmos_rsk::nginx_testnet kosmos_rsk::nginx_mainnet + kosmos_strfry::nginx kosmos_website::default kosmos-akkounts::nginx kosmos-akkounts::nginx_api diff --git a/roles/strfry.rb b/roles/strfry.rb new file mode 100644 index 0000000..256dac9 --- /dev/null +++ b/roles/strfry.rb @@ -0,0 +1,8 @@ +name "strfry" + +run_list %w( + role[ldap_client] + strfry::default + kosmos_strfry::policies + kosmos_strfry::firewall +) diff --git a/site-cookbooks/deno b/site-cookbooks/deno new file mode 160000 index 0000000..617f795 --- /dev/null +++ b/site-cookbooks/deno @@ -0,0 +1 @@ +Subproject commit 617f7959abda045326c8f06f1c1bcedbaa7c7285 diff --git a/site-cookbooks/kosmos-akkounts/attributes/default.rb b/site-cookbooks/kosmos-akkounts/attributes/default.rb index 8c8ad69..421f50f 100644 --- a/site-cookbooks/kosmos-akkounts/attributes/default.rb +++ b/site-cookbooks/kosmos-akkounts/attributes/default.rb @@ -22,6 +22,7 @@ node.default['akkounts']['lndhub']['public_key'] = nil node.default['akkounts']['lndhub']['postgres_db'] = 'lndhub' node.default['akkounts']['nostr']['public_key'] = nil +node.default['akkounts']['nostr']['relay_url'] = nil node.default['akkounts']['s3_enabled'] = true node.default['akkounts']['s3_endpoint'] = "https://s3.kosmos.org" diff --git a/site-cookbooks/kosmos-akkounts/recipes/default.rb b/site-cookbooks/kosmos-akkounts/recipes/default.rb index 2dd0a2b..8ffa7ab 100644 --- a/site-cookbooks/kosmos-akkounts/recipes/default.rb +++ b/site-cookbooks/kosmos-akkounts/recipes/default.rb @@ -163,6 +163,7 @@ env[:mediawiki_public_url] = node['mediawiki']['url'] env[:nostr_private_key] = credentials['nostr_private_key'] env[:nostr_public_key] = node['akkounts']['nostr']['public_key'] +env[:nostr_relay_url] = node['akkounts']['nostr']['relay_url'] # # remoteStorage / Liquor Cabinet diff --git a/site-cookbooks/kosmos_kvm/attributes/default.rb b/site-cookbooks/kosmos_kvm/attributes/default.rb index 4783c7e..25863d2 100644 --- a/site-cookbooks/kosmos_kvm/attributes/default.rb +++ b/site-cookbooks/kosmos_kvm/attributes/default.rb @@ -1,9 +1,10 @@ -ubuntu_server_cloud_image_release = "20230506" +release = "20240514" +img_filename = "ubuntu-22.04-server-cloudimg-amd64-disk-kvm" node.default["kosmos_kvm"]["host"]["qemu_base_image"] = { - "url" => "https://cloud-images.ubuntu.com/releases/focal/release-#{ubuntu_server_cloud_image_release}/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img", - "checksum" => "27d2b91fd2b715729d739e2a3155dce70d1aaae4f05c177f338b9d4b60be638c", - "path" => "/var/lib/libvirt/images/base/ubuntu-20.04-server-cloudimg-amd64-disk-kvm-#{ubuntu_server_cloud_image_release}.qcow2" + "url" => "https://cloud-images.ubuntu.com/releases/jammy/release-#{release}/#{img_filename}.img", + "checksum" => "2e7698b3ebd7caead06b08bd3ece241e6ce294a6db01f92ea12bcb56d6972c3f", + "path" => "/var/lib/libvirt/images/base/#{img_filename}-#{release}.qcow2" } # A systemd.timer OnCalendar config value diff --git a/site-cookbooks/kosmos_strfry/LICENSE b/site-cookbooks/kosmos_strfry/LICENSE new file mode 100644 index 0000000..b5a9703 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2024 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. diff --git a/site-cookbooks/kosmos_strfry/README.md b/site-cookbooks/kosmos_strfry/README.md new file mode 100644 index 0000000..04638b2 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/README.md @@ -0,0 +1,4 @@ +kosmos_strfry +============= + +Installs/configures a strfry relay and its reverse proxy config diff --git a/site-cookbooks/kosmos_strfry/attributes/default.rb b/site-cookbooks/kosmos_strfry/attributes/default.rb new file mode 100644 index 0000000..10b0eba --- /dev/null +++ b/site-cookbooks/kosmos_strfry/attributes/default.rb @@ -0,0 +1,2 @@ +node.default["strfry"]["ldap_search_dn"] = "ou=kosmos.org,cn=users,dc=kosmos,dc=org" +node.default["strfry"]["extras_dir"] = "/opt/strfry" diff --git a/site-cookbooks/kosmos_strfry/metadata.rb b/site-cookbooks/kosmos_strfry/metadata.rb new file mode 100644 index 0000000..c1be761 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/metadata.rb @@ -0,0 +1,10 @@ +name 'kosmos_strfry' +maintainer 'Kosmos' +maintainer_email 'mail@kosmos.org' +license 'MIT' +description 'strfry wrapper cookbook' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '0.1.0' + +depends 'kosmos_openresty' +depends 'deno' diff --git a/site-cookbooks/kosmos_strfry/recipes/firewall.rb b/site-cookbooks/kosmos_strfry/recipes/firewall.rb new file mode 100644 index 0000000..ea26f83 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/recipes/firewall.rb @@ -0,0 +1,13 @@ +# +# Cookbook Name:: kosmos_strfry +# Recipe:: firewall +# + +include_recipe "kosmos-base::firewall" + +firewall_rule "strfry" do + port node["strfry"]["port"] + source "10.1.1.0/24" + protocol :tcp + command :allow +end diff --git a/site-cookbooks/kosmos_strfry/recipes/nginx.rb b/site-cookbooks/kosmos_strfry/recipes/nginx.rb new file mode 100644 index 0000000..58cc724 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/recipes/nginx.rb @@ -0,0 +1,29 @@ +# +# Cookbook Name:: kosmos_strfry +# Recipe:: nginx +# + +domain = node["strfry"]["domain"] + +upstream_hosts = [] +search(:node, 'role:strfry').each do |node| + upstream_hosts << node['knife_zero']['host'] +end +if upstream_hosts.empty? + Chef::Log.warn("No node found with 'strfry' role. Not configuring nginx site.") + return +end + +tls_cert_for domain do + auth "gandi_dns" + action :create +end + +openresty_site domain do + template "nginx_conf_strfry.erb" + variables domain: domain, + upstream_port: node['strfry']['port'], + upstream_hosts: upstream_hosts, + ssl_cert: "/etc/letsencrypt/live/#{domain}/fullchain.pem", + ssl_key: "/etc/letsencrypt/live/#{domain}/privkey.pem" +end diff --git a/site-cookbooks/kosmos_strfry/recipes/policies.rb b/site-cookbooks/kosmos_strfry/recipes/policies.rb new file mode 100644 index 0000000..235a154 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/recipes/policies.rb @@ -0,0 +1,83 @@ +# +# Cookbook Name:: kosmos_strfry +# Recipe:: policies +# + +include_recipe "deno" + +# +# config +# + +ldap_credentials = Chef::EncryptedDataBagItem.load('credentials', 'dirsrv') + +extras_dir = node["strfry"]["extras_dir"] + +directory extras_dir do + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0755" +end + +env = { + ldap_url: 'ldap://ldap.kosmos.local:389', # requires "ldap_client" role + ldap_bind_dn: ldap_credentials["service_dn"], + ldap_password: ldap_credentials["service_password"], + ldap_search_dn: node["strfry"]["ldap_search_dn"], + whitelist_pubkeys: node["strfry"]["whitelist_pubkeys"].join(",") +} + +template "#{extras_dir}/.env" do + source 'env.erb' + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode 0600 + sensitive true + variables config: env + notifies :restart, "service[strfry]", :delayed +end + +# +# strfry deno scripts +# + +base_url = "https://gitea.kosmos.org/kosmos/akkounts/raw/branch/live/extras/strfry" + +remote_file "#{extras_dir}/deno.json" do + source "#{base_url}/deno.json" + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0644" + notifies :restart, "service[strfry]", :delayed +end + +remote_file "#{extras_dir}/deno.lock" do + source "#{base_url}/deno.lock" + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0644" + notifies :restart, "service[strfry]", :delayed +end + +remote_file "#{extras_dir}/strfry-policy.ts" do + source "#{base_url}/strfry-policy.ts" + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0755" + notifies :restart, "service[strfry]", :delayed +end + +remote_file "#{extras_dir}/ldap-policy.ts" do + source "#{base_url}/ldap-policy.ts" + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0644" + notifies :restart, "service[strfry]", :delayed +end + +remote_file "#{extras_dir}/strfry-sync.ts" do + source "#{base_url}/strfry-sync.ts" + owner node["strfry"]["user"] + group node["strfry"]["group"] + mode "0644" +end diff --git a/site-cookbooks/kosmos_strfry/templates/env.erb b/site-cookbooks/kosmos_strfry/templates/env.erb new file mode 100644 index 0000000..4b1faa5 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/templates/env.erb @@ -0,0 +1,11 @@ +<% @config.each do |key, value| %> +<% if value.is_a?(Hash) %> +<% value.each do |k, v| %> +<%= "#{key.upcase}_#{k.upcase}" %>=<%= v.to_s %> +<% end %> +<% else %> +<% if value %> +<%= key.upcase %>=<%= value.to_s %> +<% end %> +<% end %> +<% end %> diff --git a/site-cookbooks/kosmos_strfry/templates/nginx_conf_strfry.erb b/site-cookbooks/kosmos_strfry/templates/nginx_conf_strfry.erb new file mode 100644 index 0000000..2f8cee7 --- /dev/null +++ b/site-cookbooks/kosmos_strfry/templates/nginx_conf_strfry.erb @@ -0,0 +1,25 @@ +upstream _strfry { +<% @upstream_hosts.each do |host| %> + server <%= host %>:<%= @upstream_port || "7777" %>; +<% end %> +} + +server { + listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2; + server_name <%= @domain %>; + + access_log "/var/log/nginx/<%= @domain %>.access.log"; + error_log "/var/log/nginx/<%= @domain %>.error.log"; + + ssl_certificate <%= @ssl_cert %>; + ssl_certificate_key <%= @ssl_key %>; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_pass http://_strfry; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} diff --git a/site-cookbooks/strfry b/site-cookbooks/strfry new file mode 160000 index 0000000..a475637 --- /dev/null +++ b/site-cookbooks/strfry @@ -0,0 +1 @@ +Subproject commit a4756377b480c9bcceba4867969a0c15880913dc