40 Commits

Author SHA1 Message Date
f0314e0b99 Update vendored cookbooks 2026-04-11 15:34:44 +04:00
ac4fb0c9ca Fix Java/Homebrew cookbook resource failing with recent Chef
Required by our Mastodon cookbook
2026-04-11 15:23:30 +04:00
d5e3d62522 Add new postgres cluster, remove old one 2026-04-11 15:22:34 +04:00
061880536b Fix akkounts systemd unit stop command
Typo (not using pumactl), but we don't need to specify it to do the
right thing anyway. systemd can just send sigterm on its own.
2026-04-11 14:56:15 +04:00
9de37cde96 Update doc 2026-04-11 14:55:32 +04:00
64d5d34d85 Update postgres roles
Reset to normal/final
2026-04-11 14:55:02 +04:00
db9177c9c6 Improve RAM usage allowance
Queries can spawn more processed and then use more RAM than
`shared_buffers`
2026-04-11 14:53:28 +04:00
c92f9157a5 Fix method undefined in heredoc 2026-04-11 14:52:53 +04:00
a89db454d0 Improve postgres management scripts 2026-04-11 14:51:51 +04:00
fddcd4899e Ignore default db for migration/management 2026-04-10 12:57:51 +04:00
8e11df4544 Update PG migration runbook 2026-04-10 12:49:28 +04:00
0020677ab2 Drone: Make database details configurable 2026-04-10 08:37:06 +04:00
09412f69e8 Move doc 2026-04-10 08:36:54 +04:00
bc3f291bd2 WIP Prepare postgres for migration by replication 2026-04-10 08:25:55 +04:00
6583cd7010 Upgrade WAL config for PG14 2026-04-08 15:41:13 +04:00
290af8177a Refactor postgres server recipes/resource 2026-04-08 15:41:10 +04:00
2cb5540a7b Add new postgres replica (v12) 2026-04-07 16:56:01 +04:00
002ad2ca62 Update Gandi API key
Co-authored-by: Greg Karékinian <greg@karekinian.com>
2026-04-07 16:53:43 +04:00
7710231fc4 Add CORS headers for Garage web access
Fixes Discourse plugin JS usage
2026-04-07 16:53:09 +04:00
Greg Karekinian
d68deb96e9 Update openresty submodule 2026-04-07 11:40:35 +02:00
01cdd000cb Update nodes 2026-03-27 14:30:46 +04:00
ea8e2de70a Merge pull request 'Use Ubuntu 22.04 for new VMs' (#521) from jammy_jellyfish into master
Reviewed-on: #521
2026-03-27 10:28:22 +00:00
8ad3674c4d Install libvirt CLI on KVM hosts 2026-03-27 14:27:28 +04:00
Râu Cao
25192ad3ce Use Ubuntu 22.04 for new VMs
Also, remove the custom config image generation and replace it with
`--cloud-init` options.
2026-03-26 20:35:30 +04:00
55b6e24f1e Merge pull request 'Configure Gitea commit signing with SSH key' (#623) from feature/237-gitea_ssh_signing into master
Reviewed-on: #623
Reviewed-by: Greg <greg@kosmos.org>
2026-03-19 13:27:55 +00:00
a23c7d536a Merge pull request 'Improve BTC price tracking script' (#624) from feature/btc_price_tracker into master
Reviewed-on: #624
2026-03-07 06:21:51 +00:00
d492cd18cc Improve BTC price tracking script
1. Robust API helper: Add make_request with retry logic for both
   GET (price data) and PUT (upload) requests
2. Arithmetic precision: Switch to awk for floating-point average
   calculation
3. Correct error handling: Updated get_price_data to return status
   codes and the main script to exit on failure
4. Safer JSON: Use jq to construct valid JSON payloads
5. Safety Flags: Add set -e/-o to fail fast on any command errors
2026-03-06 23:20:12 +04:00
161b78be97 Configure Gitea commit signing with SSH key 2026-02-13 17:29:23 +04:00
6e83384da5 Use more attributes for Gitea config 2026-02-13 16:07:24 +04:00
be8278fbdc Upgrade act_runner 2026-02-13 16:06:08 +04:00
ff3f05452f Merge pull request 'Update Gitea to 1.25.4' (#622) from chore/upgrade_gitea into master
Reviewed-on: #622
Reviewed-by: Râu Cao <raucao@kosmos.org>
2026-02-13 10:18:36 +00:00
Greg Karekinian
1fb66092fc Update Gitea to 1.25.4
Back to using the binary from upstream releases
2026-02-13 11:15:07 +01:00
Greg Karekinian
81691f7e21 Run systemctl daemon-reload on gitea service changes 2026-02-13 11:05:08 +01:00
e9dff82628 Merge pull request 'Add IPv6 support for all OpenResty sites' (#618) from feature/614-ipv6 into master
Reviewed-on: #618
2026-02-12 13:09:25 +00:00
0933e9caa0 Add IPv6 to all OpenResty sites
Co-authored-by: Greg Karékinian <greg@karekinian.com>
2026-02-12 17:05:14 +04:00
9f862a89cc Merge pull request 'Enable Gitea SSH via IPv6' (#613) from chore/612-enable_ipv6_ssh into master
Reviewed-on: #613
Reviewed-by: Greg <greg@kosmos.org>
2026-01-11 13:19:33 +00:00
039dbdf091 Enable Gitea SSH via IPv6
closes #612
2026-01-09 13:43:06 +07:00
e3559119be Update node info 2025-11-25 10:56:35 +00:00
16f95170ef Remove old node 2025-11-25 10:55:04 +00:00
36f5903271 Merge pull request 'Fix URL matcher for substr (vs strfry)' (#608) from bugfix/substr_url_matching into master
Reviewed-on: #608
2025-11-17 11:03:48 +00:00
92 changed files with 1262 additions and 267 deletions

View File

@@ -24,6 +24,7 @@ cookbook 'composer', '~> 2.7.0'
cookbook 'fail2ban', '~> 7.0.4' cookbook 'fail2ban', '~> 7.0.4'
cookbook 'git', '~> 10.0.0' cookbook 'git', '~> 10.0.0'
cookbook 'golang', '~> 5.3.1' cookbook 'golang', '~> 5.3.1'
cookbook 'homebrew', '>= 6.0.0'
cookbook 'hostname', '= 0.4.2' cookbook 'hostname', '= 0.4.2'
cookbook 'hostsfile', '~> 3.0.1' cookbook 'hostsfile', '~> 3.0.1'
cookbook 'java', '~> 4.3.0' cookbook 'java', '~> 4.3.0'

View File

@@ -8,6 +8,7 @@ DEPENDENCIES
firewall (~> 6.2.16) firewall (~> 6.2.16)
git (~> 10.0.0) git (~> 10.0.0)
golang (~> 5.3.1) golang (~> 5.3.1)
homebrew (>= 6.0.0)
hostname (= 0.4.2) hostname (= 0.4.2)
hostsfile (~> 3.0.1) hostsfile (~> 3.0.1)
ipfs ipfs
@@ -62,7 +63,7 @@ GRAPH
git (10.0.0) git (10.0.0)
golang (5.3.1) golang (5.3.1)
ark (>= 6.0) ark (>= 6.0)
homebrew (5.4.1) homebrew (6.0.2)
hostname (0.4.2) hostname (0.4.2)
hostsfile (>= 0.0.0) hostsfile (>= 0.0.0)
hostsfile (3.0.1) hostsfile (3.0.1)

4
clients/garage-14.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "garage-14",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAypINv1zTZ7+pyT0iRhik\n0W70ASYADo7qK7QyE9/3nu2sUrP1IjoNFsv/ceKwicH7Fw2Ei1o+yKZlKn7zJzY7\n93YRZndF04VH2bmqy0uOWK0Bdat7gCld5bvS6FmRflg7g64LFb33/64QIVsVGHGL\nYF2TO//x79t9JKcQDa4h5MOWzJNTFuEcUGa0gJjMYpWGVHEJSgRuIgyhXmyIJJgY\nguj6ymTm5+3VS7NzoNy2fbTt1LRpHb5UWrCR15oiLZiDSMLMx0CcGOCmrhvODi4k\n0umw+2NPd1G50s9z7KVbTqybuQ65se2amRnkVcNfaBIU5qk9bVqcmhZlEozmBZCd\ndwIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/garage-15.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "garage-15",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy14sTt5gxVZi9C3KIEBu\nDyUgbb6jc3/GR22fNPTqV6uDHhxzhE2UsYwY/7yuA1RasdwHEOBWZaoC0Om5/Zmi\n8gn6//v1ILyLNaAcw+SQcxZkCN8Sk/0atRS9HYk1agE8Mvh72Fe2z3l+92VMefy7\nJwJUNNBTbnV2WVCchChoWnfhI7bkSLSHp0M2MO2pI+lkpSdmfkJSa5z9zihgxKO8\nXfvhryDCZNvfRVHhwc+ffpap0gLF0H9riGKE4FwLy4YqbuW1Tgm6bObb9bpOIw6Q\nVfH3kC/KMK5FlnxGmYtDkhRJ/wjGInRBk9WK/QOmjyd2FVxipEQmA4RdjlznRC9I\nrwIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/leo.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "leo",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFfQsJnREjbXTtpT6BVt\naBaUzRmCQi8Du0TzeUG0ENrY0p5Exqleye2rC6bJlB3PER1xr5zdtuXLgbcVumIb\nzroU5JPtFbQk7r/pj0atT+UEYzl16iuEpprQ/bug+f0nE514USr6YG4G+tlZ/jBI\nSHsCQF1P8ufXFLW0ewC7rdvBkgA+DwK14naRxS4jO5MSl4wmNTjs/jymTg508mQq\nf5tG52t8qFdgn9pRdBXmyTpPtwK7I4rZ+1Qn+1E5m4oQUZsxh8Ba1bGbKotVO7Ua\nYL1yCGx7zRRUvLLIdSMvlRXTJBUSQtQ8P4QUDWTY1Na2w3t9sulKg2Lwsw8tktvC\nCwIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/postgres-10.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "postgres-10",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2oBb5omC7ZionWhudgFm\n2NGcRXsI0c7+g1+0duaxj5dziaRTltqzpRJTfiJD6R36FcvEqwGc+qQgYSMzc1Xd\nY4OTvJFIDiFAmROm/DZYgFtTDldVNJZO2bbU3COYf/Z2Poq56gC4zLLd/zf6shgb\n2Mty8PlQ82JJAY9EMI3aAifdnZ1k/g4weFC4LFg9lUcNNXOwlAjp//LJ3ku3aY1r\nwW74msSeWEjE44YZdWyMYgM7Fy1hz5giHFQtRdOLemRCWQ8h26wn/cmWld7lsLg+\nlYqxokxWXGv8r5zR8kDTBkd0dxY7ZMbo7oESY4Uhuf4UReMe2ZGHto1E7w3llSj+\n7wIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/postgres-11.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "postgres-11",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1foYpuubS2ovlg3uHO12\nQ/ROZ8MpG+LkCAM46uVfPaoWwfY0vdfMsBOanHDgm9DGUCEBJZ6LPrvCvGXbpPy6\n9GSswK75zVWODblNjvvV4ueGFq4bBFwRuZNjyMlqgyzeU+srZL0ivelu5XEuGuoD\nPYCBKWYqGMz85/eMC7/tinTJtKPyOtXe/G8meji+r7gh3j+ypj/EWeKfcRDa4aGe\n/DmMCurIjjPAXFLMAA6fIqPWVfcPw4APNPE60Z92yPGsTbPu7bL54M5f7udmmu7H\nOgk1HjMAmXCuLDzTkfaxqHP+57yELg/YpXR1E93VmBeQuIBsyOFEk6AmUmA1Ib6e\nnQIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/postgres-12.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "postgres-12",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1mYGrYB8keUKmXA8dhWc\ncCLzp50xR0ajSw+bWYydyRqD5wuEVKjiJu4+G9QmTVXkVgJ+AYI0Y9/WZYpDqVH6\nvLUo6BSNQaWx20q93qIdOGLy8YG3Qyznezk4l8T9u9vWZDyDpKw6gCxzikMkrXxb\n0cqOYtyud8+PtSEEMogSjOKhRURVHlVrlVH3SQO7Whke9rkiFcbXzubsK9yjkUtF\nxZafSoGorOlDsPvFTfYnkepVB+GHcgiribRYSrO+73GypC2kqMhCpWrb6a0VWsP/\nh53+q3JL3vBvdvjcv51Wpf4n6JdnXnQGn2/MdXEzw+NXgjU4/IdYtbORSbaI8F5t\nowIDAQAB\n-----END PUBLIC KEY-----\n"
}

View File

@@ -1,4 +0,0 @@
{
"name": "postgres-7",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArraIm6mXi0qgK4oWDs2I\nOIx+g/LPnfRd5aBXhoHcekGiJKttQTi5dRdN4+T6qVEC2h4Cc9qN47h2TZPLDh/M\neIZvu0AyicpectzXf6DtDZh0hFCnv47RDi9927op9tjMXk0SV1tLel7MN0dawATw\ny0vQkkr/5a3ZdiP4dFv+bdfVrj+Tuh85BYPVyX2mxq9F7Efxrt6rzVBiqr6uJLUY\nStpeB3CCalC4zQApKX2xrdtr2k8aJbqC6C//LiKbb7VKn+ZuZJ32L/+9HDEzQoFC\no0ZZPMhfnjcU+iSHYZuPMTJTNbwgRuOgpn9O8kZ239qYc59z7HEXwwWiYPDevbiM\nCQIDAQAB\n-----END PUBLIC KEY-----\n"
}

4
clients/postgres-9.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "postgres-9",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2dcE9HH0r5TBb/FGj2+e\nOw8ssoxeB61JmR4/psdZ6oPR08gxyqOY0ODziCmyIdXwFhjIcC44HjxCbcB8TU8G\nWGqlmfqWWIJW0x/2xOycHobAWDn5fC5ttTXkR3HC1TutX/2mH26mtfz9UjNdPaTo\nVZFMcxeaBCFSNlYC7hPUQ5f/qBdhhpLxP9uyzU+YFPqtwLP7g8EAUQObM4L+m6Q8\nqE7xgYpnhgaNrPsmvaVuoNylMGwyK0j1whOkcik8UgLprD70ISNSNxxcLehbvA3G\nPQPQRRuFF36fu2gECWGopbrFKwQGNfgJguQoXM1RQZQMQqWHPS933k5i6bi5pnhp\nzwIDAQAB\n-----END PUBLIC KEY-----\n"
}

View File

@@ -3,3 +3,5 @@ config:
line-length: false # MD013 line-length: false # MD013
no-duplicate-heading: false # MD024 no-duplicate-heading: false # MD024
reference-links-images: false # MD052 reference-links-images: false # MD052
ignores:
- .github/copilot-instructions.md

View File

@@ -2,6 +2,48 @@
This file is used to list changes made in each version of the homebrew cookbook. This file is used to list changes made in each version of the homebrew cookbook.
## 6.0.2 - *2025-09-04*
Standardise files with files in sous-chefs/repo-management
Standardise files with files in sous-chefs/repo-management
## 6.0.1 - *2025-03-24*
## 6.0.0 - *2025-03-17*
- Updated library call for new homebrew class name found in chef-client 18.6.2+ releases
## 5.4.9 - *2024-11-18*
Standardise files with files in sous-chefs/repo-management
Standardise files with files in sous-chefs/repo-management
Standardise files with files in sous-chefs/repo-management
Standardise files with files in sous-chefs/repo-management
Standardise files with files in sous-chefs/repo-management
## 5.4.8 - *2024-05-07*
## 5.4.7 - *2024-05-06*
- Explicitly include `Which` module from `Chef` which fixes runs on 18.x clients.
## 5.4.6 - *2024-05-06*
## 5.4.5 - *2023-11-01*
Standardise files with files in sous-chefs/repo-management
## 5.4.4 - *2023-09-28*
## 5.4.3 - *2023-09-04*
## 5.4.2 - *2023-07-10*
## 5.4.1 - *2023-06-01* ## 5.4.1 - *2023-06-01*
## 5.4.0 - *2023-04-24* ## 5.4.0 - *2023-04-24*

View File

@@ -20,8 +20,9 @@
# #
class HomebrewUserWrapper class HomebrewUserWrapper
require 'chef/mixin/homebrew_user' require 'chef/mixin/homebrew'
include Chef::Mixin::HomebrewUser include Chef::Mixin::Homebrew
include Chef::Mixin::Which
end end
module Homebrew module Homebrew
@@ -59,41 +60,17 @@ module Homebrew
def owner def owner
@owner ||= begin @owner ||= begin
# once we only support 14.0 we can switch this to find_homebrew_username HomebrewUserWrapper.new.find_homebrew_username
require 'etc' rescue
::Etc.getpwuid(HomebrewUserWrapper.new.find_homebrew_uid).name Chef::Exceptions::CannotDetermineHomebrewPath
rescue Chef::Exceptions::CannotDetermineHomebrewOwner
calculate_owner
end.tap do |owner| end.tap do |owner|
Chef::Log.debug("Homebrew owner is #{owner}") Chef::Log.debug("Homebrew owner is #{owner}")
end end
end end
private
def calculate_owner
owner = homebrew_owner_attr || sudo_user || current_user
if owner == 'root'
raise Chef::Exceptions::User,
"Homebrew owner is 'root' which is not supported. " \
"To set an explicit owner, please set node['homebrew']['owner']."
end
owner
end
def homebrew_owner_attr
Chef.node['homebrew']['owner']
end
def sudo_user
ENV['SUDO_USER']
end
def current_user
ENV['USER']
end
end unless defined?(Homebrew) end unless defined?(Homebrew)
class HomebrewWrapper class HomebrewWrapper
include Homebrew include Homebrew
end end
Chef::Mixin::Homebrew.include(Homebrew)

View File

@@ -17,13 +17,13 @@
"recipes": { "recipes": {
}, },
"version": "5.4.1", "version": "6.0.2",
"source_url": "https://github.com/sous-chefs/homebrew", "source_url": "https://github.com/sous-chefs/homebrew",
"issues_url": "https://github.com/sous-chefs/homebrew/issues", "issues_url": "https://github.com/sous-chefs/homebrew/issues",
"privacy": false, "privacy": false,
"chef_versions": [ "chef_versions": [
[ [
">= 15.3" ">= 18.6.2"
] ]
], ],
"ohai_versions": [ "ohai_versions": [

View File

@@ -3,9 +3,9 @@ maintainer 'Sous Chefs'
maintainer_email 'help@sous-chefs.org' maintainer_email 'help@sous-chefs.org'
license 'Apache-2.0' license 'Apache-2.0'
description 'Install Homebrew and includes resources for working with taps and casks' description 'Install Homebrew and includes resources for working with taps and casks'
version '5.4.1' version '6.0.2'
supports 'mac_os_x' supports 'mac_os_x'
source_url 'https://github.com/sous-chefs/homebrew' source_url 'https://github.com/sous-chefs/homebrew'
issues_url 'https://github.com/sous-chefs/homebrew/issues' issues_url 'https://github.com/sous-chefs/homebrew/issues'
chef_version '>= 15.3' chef_version '>= 18.6.2'

View File

@@ -1,9 +1,10 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"], "extends": ["config:base"],
"packageRules": [{ "packageRules": [
{
"groupName": "Actions", "groupName": "Actions",
"matchUpdateTypes": ["patch", "pin", "digest"], "matchUpdateTypes": ["minor", "patch", "pin"],
"automerge": true, "automerge": true,
"addLabels": ["Release: Patch", "Skip: Announcements"] "addLabels": ["Release: Patch", "Skip: Announcements"]
}, },

View File

@@ -19,6 +19,7 @@
# limitations under the License. # limitations under the License.
# #
unified_mode true
chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides)
property :cask_name, String, regex: %r{^[\w/-]+$}, name_property: true property :cask_name, String, regex: %r{^[\w/-]+$}, name_property: true

View File

@@ -19,6 +19,7 @@
# limitations under the License. # limitations under the License.
# #
unified_mode true
chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides) chef_version_for_provides '< 14.0' if respond_to?(:chef_version_for_provides)
property :tap_name, String, name_property: true, regex: %r{^[\w-]+(?:\/[\w-]+)+$} property :tap_name, String, name_property: true, regex: %r{^[\w-]+(?:\/[\w-]+)+$}

View File

@@ -1,23 +1,16 @@
{ {
"id": "gandi_api", "id": "gandi_api",
"key": {
"encrypted_data": "lU7/xYTmP5Sb6SsK5TNNIyegWozzBtUzpg7oDdl6gcz9FEMmG2ft0Ljh5Q==\n",
"iv": "EZPQD3C+wsP/mBhF\n",
"auth_tag": "vF9E8Pj4Z8quJJdOMg/QTw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"access_token": { "access_token": {
"encrypted_data": "1Uw69JkNrmb8LU/qssuod1SlqxxrWR7TJQZeeivRrNzrMIVTEW/1uwJIYL6b\nM4GeeYl9lIRlMMmLBkc=\n", "encrypted_data": "+skwxHnpAj/3d3e2u7s7B9EydbETj8b0flWahvb5gt/o4JYFWHrhIyX/0IVa\n4wgmu08eDgU51i0knGA=\n",
"iv": "cc1GJKu6Cf4DkIgX\n", "iv": "ONKrFCt8Oj3GKIQ5\n",
"auth_tag": "ERem4S7ozG695kjvWIMghw==\n", "auth_tag": "j9Hrk8ZZFMQub4NUO+2e4g==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
}, },
"domains": { "domains": {
"encrypted_data": "scZ5blsSjs54DlitR7KZ3enLbyceOR5q0wjHw1golQ==\n", "encrypted_data": "lGfoPHdXEYYdJmoIA9M119wjVl1v4UzIv5gHADwx0A==\n",
"iv": "oDcHm7shAzW97b4t\n", "iv": "q6XKbxhW7X9ONxNt\n",
"auth_tag": "62Zais9yf68SwmZRsmZ3hw==\n", "auth_tag": "ns9WJH8Oe75siWu+sOZkRg==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
} }

287
doc/postgres/migration.md Normal file
View File

@@ -0,0 +1,287 @@
# Migrating PostgreSQL cluster to a new major version
## Summary
1. Dump from a replica
2. Restore to fresh VM running new major version
3. Add logical replication for delta sync from current/old primary
4. Switch primary to new server
5. Remove logical replication on new server
## Runbook
* Primary host: `PRIMARY_HOST`
* Replica host: `REPLICA_HOST`
* New PG14 host: `NEW_HOST`
* PostgreSQL superuser: `postgres`
* Running locally on each machine via `sudo -u postgres`
Adjust hostnames/IPs/etc. where needed.
---
### 🟢 0. PRIMARY — Pre-checks
```bash
sudo -u postgres psql -c "SHOW wal_level;"
sudo -u postgres psql -c "SHOW max_replication_slots;"
```
If needed, edit config:
```bash
sudo -u postgres vi $PGDATA/postgresql.conf
```
Ensure:
```conf
wal_level = logical
max_replication_slots = 10
```
Restart if changed:
```bash
sudo systemctl restart postgresql
```
---
### 🔵🟡 3. Create keypair for syncing dump later
🔵 On NEW_HOST:
```bash
sudo mkdir -p /home/postgres/.ssh && \
sudo chown -R postgres:postgres /home/postgres && \
sudo chmod 700 /home/postgres/.ssh && \
sudo -u postgres bash -c 'ssh-keygen -t ecdsa -b 256 -f /home/postgres/.ssh/id_ecdsa -N "" -C "postgres@$(hostname)"' && \
sudo cat /home/postgres/.ssh/id_ecdsa.pub
```
Copy the public key from the above output
🟡 On replica:
```bash
sudo mkdir -p /home/postgres/.ssh && \
sudo chown -R postgres:postgres /home/postgres && \
sudo chmod 700 /home/postgres/.ssh && \
echo [public_key] | sudo tee /home/postgres/.ssh/authorized_keys > /dev/null && \
sudo chmod 700 /home/postgres/.ssh
```
---
### 🟢 1. PRIMARY — Create publication and replication slots
```bash
sudo -u postgres pg_create_replication_publications
```
or
```bash
sudo -u postgres pg_create_replication_publication [db_name]
```
Listing publications and slots:
```bash
sudo -u postgres pg_list_replication_publications
sudo -u postgres pg_list_replication_slots
```
---
### 🟡 3. REPLICA — Pause replication
```bash
sudo -u postgres psql -c "SELECT pg_wal_replay_pause();"
```
Verify:
```bash
sudo -u postgres psql -c "SELECT pg_is_wal_replay_paused();"
```
---
### 🟡 4. REPLICA — Run dump
```bash
sudo -u postgres pg_dump_all_databases
```
or
```bash
sudo -u postgres bash -c "pg_dumpall --globals-only > /tmp/globals.sql"
sudo -u postgres pg_dump_database [db_name]
```
---
### 🟡 5. REPLICA — Resume replication
```bash
sudo -u postgres psql -c "SELECT pg_wal_replay_resume();"
```
---
### 🔵 6. COPY dumps to NEW HOST
From NEW_HOST:
```bash
export REPLICA_HOST=[private_ip] && \
cd /tmp && \
sudo -u postgres scp "postgres@$REPLICA_HOST:/tmp/globals.sql" . && \
sudo -u postgres scp "postgres@$REPLICA_HOST:/tmp/dump_*.tar.zst" .
```
---
### 🔵 7. NEW HOST (PostgreSQL 14) — Restore
#### 7.1 Restore globals
```bash
sudo -u postgres psql -f /tmp/globals.sql
```
---
#### 7.2 Create databases
```bash
sudo -u postgres psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1')" | \
xargs -I{} sudo -u postgres createdb {}
```
or
```bash
sudo -u postgres createdb [db_name]
```
---
#### 7.3 Restore each database
```bash
sudo -u postgres pg_restore_all_databases
```
or
```bash
sudo -u postgres pg_restore_database [db_name]
```
---
### 🔵 8. NEW HOST — Create subscriptions
```bash
sudo -u postgres pg_create_replication_subscriptions
```
or
```bash
sudo -u postgres pg_create_replication_subscription [db_name]
```
---
### 🔵 9. NEW HOST — Monitor replication
```bash
sudo -u postgres pg_list_replication_subscriptions
```
---
### 🔴 11. CUTOVER
#### 11.1 Stop writes on old primary
Put app(s) in maintenance mode, stop the app/daemons.
---
#### 11.2 Wait for replication to catch up
TODO: not the best way to check, since WAL LSNs keep increasing
```bash
sudo -u postgres psql -d [db_name] -c "SELECT * FROM pg_stat_subscription;"
```
---
#### 11.3 Fix sequences
Run per DB:
```bash
sudo -u postgres pg_fix_sequences_in_all_databases
```
or
```bash
sudo -u postgres pg_fix_sequences [db_name]
```
---
#### 11.4 Point app to NEW_HOST
1. Update `pg.kosmos.local` in `/etc/hosts` on app server(s). For example:
```bash
export NEW_PG_PRIMARY=[private_ip]
knife ssh roles:ejabberd -a knife_zero.host "sudo sed -r \"s/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s(pg.kosmos.local)/$NEW_PG_PRIMARY\t\1/\" -i /etc/hosts"
```
Or override node attribute(s) if necessary and/or approporiate.
2. Start the app/daemons, and deactivate maintenance mode.
---
### 🧹 12. CLEANUP NEW_HOST
```bash
sudo -u postgres pg_drop_replication_subscriptions
```
---
### 🧹 13. CLEANUP PRIMARY
TODO: Looks like slots are dropped automatically, when subscriptions are dropped
```bash
sudo -u postgres pg_drop_replication_publications
```
---
### 🧹 13. CLEANUP Chef
Once all apps/databases are migrated, update the role in the node
config of the new primary to 'postgres_primary' and converge it.
Also delete the old primary node config from the Chef repo.
---
### ✅ DONE
---

View File

@@ -9,7 +9,7 @@
"automatic": { "automatic": {
"fqdn": "akkounts-1", "fqdn": "akkounts-1",
"os": "linux", "os": "linux",
"os_version": "5.4.0-216-generic", "os_version": "5.4.0-223-generic",
"hostname": "akkounts-1", "hostname": "akkounts-1",
"ipaddress": "192.168.122.160", "ipaddress": "192.168.122.160",
"roles": [ "roles": [

View File

@@ -12,6 +12,7 @@
}, },
"openresty": { "openresty": {
"listen_ip": "148.251.237.111", "listen_ip": "148.251.237.111",
"listen_ipv6": "2a01:4f8:202:804a::2",
"log_formats": { "log_formats": {
"json": "{\"ip\":\"$remote_addr\",\"time\":\"$time_local\",\"host\":\"$host\",\"method\":\"$request_method\",\"uri\":\"$uri\",\"status\":$status,\"size\":$body_bytes_sent,\"referer\":\"$http_referer\",\"upstream_addr\":\"$upstream_addr\",\"upstream_response_time\":\"$upstream_response_time\",\"ua\":\"$http_user_agent\"}" "json": "{\"ip\":\"$remote_addr\",\"time\":\"$time_local\",\"host\":\"$host\",\"method\":\"$request_method\",\"uri\":\"$uri\",\"status\":$status,\"size\":$body_bytes_sent,\"referer\":\"$http_referer\",\"upstream_addr\":\"$upstream_addr\",\"upstream_response_time\":\"$upstream_response_time\",\"ua\":\"$http_user_agent\"}"
} }
@@ -81,6 +82,7 @@
"timezone_iii::debian", "timezone_iii::debian",
"ntp::default", "ntp::default",
"ntp::apparmor", "ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails", "kosmos-base::systemd_emails",
"apt::unattended-upgrades", "apt::unattended-upgrades",
"kosmos-base::firewall", "kosmos-base::firewall",

View File

@@ -75,6 +75,7 @@
"timezone_iii::debian", "timezone_iii::debian",
"ntp::default", "ntp::default",
"ntp::apparmor", "ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails", "kosmos-base::systemd_emails",
"apt::unattended-upgrades", "apt::unattended-upgrades",
"kosmos-base::firewall", "kosmos-base::firewall",

65
nodes/garage-14.json Normal file
View File

@@ -0,0 +1,65 @@
{
"name": "garage-14",
"chef_environment": "production",
"normal": {
"knife_zero": {
"host": "10.1.1.151"
}
},
"automatic": {
"fqdn": "garage-14",
"os": "linux",
"os_version": "5.15.0-1095-kvm",
"hostname": "garage-14",
"ipaddress": "192.168.122.36",
"roles": [
"base",
"kvm_guest",
"garage_node"
],
"recipes": [
"kosmos-base",
"kosmos-base::default",
"kosmos_kvm::guest",
"kosmos_garage",
"kosmos_garage::default",
"kosmos_garage::firewall_rpc",
"kosmos_garage::firewall_apis",
"apt::default",
"timezone_iii::default",
"timezone_iii::debian",
"ntp::default",
"ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails",
"apt::unattended-upgrades",
"kosmos-base::firewall",
"kosmos-postfix::default",
"postfix::default",
"postfix::_common",
"postfix::_attributes",
"postfix::sasl_auth",
"hostname::default",
"firewall::default"
],
"platform": "ubuntu",
"platform_version": "22.04",
"cloud": null,
"chef_packages": {
"chef": {
"version": "18.10.17",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.10.17/lib",
"chef_effortless": null
},
"ohai": {
"version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
}
}
},
"run_list": [
"role[base]",
"role[kvm_guest]",
"role[garage_node]"
]
}

View File

@@ -1,34 +1,36 @@
{ {
"name": "postgres-8", "name": "garage-15",
"chef_environment": "production", "chef_environment": "production",
"normal": { "normal": {
"knife_zero": { "knife_zero": {
"host": "10.1.1.99" "host": "10.1.1.82"
} }
}, },
"automatic": { "automatic": {
"fqdn": "postgres-8", "fqdn": "garage-15",
"os": "linux", "os": "linux",
"os_version": "5.15.0-1059-kvm", "os_version": "5.15.0-1095-kvm",
"hostname": "postgres-8", "hostname": "garage-15",
"ipaddress": "192.168.122.100", "ipaddress": "192.168.122.57",
"roles": [ "roles": [
"base", "base",
"kvm_guest", "kvm_guest",
"postgresql_replica" "garage_node"
], ],
"recipes": [ "recipes": [
"kosmos-base", "kosmos-base",
"kosmos-base::default", "kosmos-base::default",
"kosmos_kvm::guest", "kosmos_kvm::guest",
"kosmos_postgresql::hostsfile", "kosmos_garage",
"kosmos_postgresql::replica", "kosmos_garage::default",
"kosmos_postgresql::firewall", "kosmos_garage::firewall_rpc",
"kosmos_garage::firewall_apis",
"apt::default", "apt::default",
"timezone_iii::default", "timezone_iii::default",
"timezone_iii::debian", "timezone_iii::debian",
"ntp::default", "ntp::default",
"ntp::apparmor", "ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails", "kosmos-base::systemd_emails",
"apt::unattended-upgrades", "apt::unattended-upgrades",
"kosmos-base::firewall", "kosmos-base::firewall",
@@ -37,26 +39,27 @@
"postfix::_common", "postfix::_common",
"postfix::_attributes", "postfix::_attributes",
"postfix::sasl_auth", "postfix::sasl_auth",
"hostname::default" "hostname::default",
"firewall::default"
], ],
"platform": "ubuntu", "platform": "ubuntu",
"platform_version": "22.04", "platform_version": "22.04",
"cloud": null, "cloud": null,
"chef_packages": { "chef_packages": {
"chef": { "chef": {
"version": "18.5.0", "version": "18.10.17",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.5.0/lib", "chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.10.17/lib",
"chef_effortless": null "chef_effortless": null
}, },
"ohai": { "ohai": {
"version": "18.1.11", "version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.1.11/lib/ohai" "ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
} }
} }
}, },
"run_list": [ "run_list": [
"role[base]", "role[base]",
"role[kvm_guest]", "role[kvm_guest]",
"role[postgresql_replica]" "role[garage_node]"
] ]
} }

View File

@@ -50,13 +50,6 @@
"postfix::sasl_auth", "postfix::sasl_auth",
"hostname::default", "hostname::default",
"firewall::default", "firewall::default",
"kosmos_gitea::compile_from_source",
"git::default",
"git::package",
"kosmos-nodejs::default",
"nodejs::nodejs_from_package",
"nodejs::repo",
"golang::default",
"backup::default", "backup::default",
"logrotate::default" "logrotate::default"
], ],

56
nodes/leo.json Normal file
View File

@@ -0,0 +1,56 @@
{
"name": "leo",
"normal": {
"knife_zero": {
"host": "leo.kosmos.org"
}
},
"automatic": {
"fqdn": "leo",
"os": "linux",
"os_version": "5.15.0-164-generic",
"hostname": "leo",
"ipaddress": "5.9.81.116",
"roles": [
"base"
],
"recipes": [
"kosmos-base",
"kosmos-base::default",
"kosmos_kvm::host",
"apt::default",
"timezone_iii::default",
"timezone_iii::debian",
"ntp::default",
"ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails",
"apt::unattended-upgrades",
"kosmos-base::firewall",
"kosmos-postfix::default",
"postfix::default",
"postfix::_common",
"postfix::_attributes",
"postfix::sasl_auth",
"hostname::default"
],
"platform": "ubuntu",
"platform_version": "22.04",
"cloud": null,
"chef_packages": {
"chef": {
"version": "18.10.17",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.10.17/lib",
"chef_effortless": null
},
"ohai": {
"version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
}
}
},
"run_list": [
"role[base]",
"recipe[kosmos_kvm::host]"
]
}

View File

@@ -1,16 +1,17 @@
{ {
"name": "postgres-6", "name": "postgres-11",
"chef_environment": "production",
"normal": { "normal": {
"knife_zero": { "knife_zero": {
"host": "10.1.1.196" "host": "10.1.1.91"
} }
}, },
"automatic": { "automatic": {
"fqdn": "postgres-6", "fqdn": "postgres-11",
"os": "linux", "os": "linux",
"os_version": "5.4.0-173-generic", "os_version": "5.15.0-1095-kvm",
"hostname": "postgres-6", "hostname": "postgres-11",
"ipaddress": "192.168.122.60", "ipaddress": "192.168.122.142",
"roles": [ "roles": [
"base", "base",
"kvm_guest", "kvm_guest",
@@ -21,18 +22,20 @@
"kosmos-base::default", "kosmos-base::default",
"kosmos_kvm::guest", "kosmos_kvm::guest",
"kosmos_postgresql::primary", "kosmos_postgresql::primary",
"kosmos_postgresql::firewall",
"kosmos-akkounts::pg_db", "kosmos-akkounts::pg_db",
"kosmos-bitcoin::lndhub-go_pg_db", "kosmos-bitcoin::lndhub-go_pg_db",
"kosmos-bitcoin::nbxplorer_pg_db", "kosmos-bitcoin::nbxplorer_pg_db",
"kosmos_drone::pg_db", "kosmos_drone::pg_db",
"kosmos_gitea::pg_db", "kosmos_gitea::pg_db",
"kosmos-mastodon::pg_db", "kosmos-mastodon::pg_db",
"kosmos_postgresql::firewall",
"kosmos_postgresql::management_scripts",
"apt::default", "apt::default",
"timezone_iii::default", "timezone_iii::default",
"timezone_iii::debian", "timezone_iii::debian",
"ntp::default", "ntp::default",
"ntp::apparmor", "ntp::apparmor",
"kosmos-base::journald_conf",
"kosmos-base::systemd_emails", "kosmos-base::systemd_emails",
"apt::unattended-upgrades", "apt::unattended-upgrades",
"kosmos-base::firewall", "kosmos-base::firewall",
@@ -44,17 +47,17 @@
"hostname::default" "hostname::default"
], ],
"platform": "ubuntu", "platform": "ubuntu",
"platform_version": "20.04", "platform_version": "22.04",
"cloud": null, "cloud": null,
"chef_packages": { "chef_packages": {
"chef": { "chef": {
"version": "18.4.2", "version": "18.10.17",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.4.2/lib", "chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.10.17/lib",
"chef_effortless": null "chef_effortless": null
}, },
"ohai": { "ohai": {
"version": "18.1.11", "version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.1.11/lib/ohai" "ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
} }
} }
}, },

View File

@@ -1,5 +1,5 @@
{ {
"name": "postgres-7", "name": "postgres-12",
"chef_environment": "production", "chef_environment": "production",
"normal": { "normal": {
"knife_zero": { "knife_zero": {
@@ -7,11 +7,11 @@
} }
}, },
"automatic": { "automatic": {
"fqdn": "postgres-7", "fqdn": "postgres-12",
"os": "linux", "os": "linux",
"os_version": "5.4.0-1123-kvm", "os_version": "5.15.0-1096-kvm",
"hostname": "postgres-7", "hostname": "postgres-12",
"ipaddress": "192.168.122.89", "ipaddress": "192.168.122.139",
"roles": [ "roles": [
"base", "base",
"kvm_guest", "kvm_guest",
@@ -24,6 +24,7 @@
"kosmos_postgresql::hostsfile", "kosmos_postgresql::hostsfile",
"kosmos_postgresql::replica", "kosmos_postgresql::replica",
"kosmos_postgresql::firewall", "kosmos_postgresql::firewall",
"kosmos_postgresql::management_scripts",
"apt::default", "apt::default",
"timezone_iii::default", "timezone_iii::default",
"timezone_iii::debian", "timezone_iii::debian",
@@ -41,17 +42,17 @@
"hostname::default" "hostname::default"
], ],
"platform": "ubuntu", "platform": "ubuntu",
"platform_version": "20.04", "platform_version": "22.04",
"cloud": null, "cloud": null,
"chef_packages": { "chef_packages": {
"chef": { "chef": {
"version": "18.5.0", "version": "18.10.17",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.5.0/lib", "chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.10.17/lib",
"chef_effortless": null "chef_effortless": null
}, },
"ohai": { "ohai": {
"version": "18.1.11", "version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.1.11/lib/ohai" "ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
} }
} }
}, },

View File

@@ -8,8 +8,8 @@ run_list %w(
override_attributes( override_attributes(
"gitea" => { "gitea" => {
"repo" => "https://github.com/67P/gitea.git", # "repo" => "https://github.com/67P/gitea.git",
"revision" => "ldap_sync", # "revision" => "ldap_sync",
"log" => { "level" => "Info" } "log" => { "level" => "Info" }
}, },
) )

View File

@@ -1,12 +1,13 @@
name "postgresql_primary" name "postgresql_primary"
run_list %w( run_list [
kosmos_postgresql::primary "kosmos_postgresql::primary",
kosmos_postgresql::firewall "kosmos-akkounts::pg_db",
kosmos-akkounts::pg_db "kosmos-bitcoin::lndhub-go_pg_db",
kosmos-bitcoin::lndhub-go_pg_db "kosmos-bitcoin::nbxplorer_pg_db",
kosmos-bitcoin::nbxplorer_pg_db "kosmos_drone::pg_db",
kosmos_drone::pg_db "kosmos_gitea::pg_db",
kosmos_gitea::pg_db "kosmos-mastodon::pg_db",
kosmos-mastodon::pg_db "kosmos_postgresql::firewall",
) "kosmos_postgresql::management_scripts"
]

View File

@@ -1,7 +1,8 @@
name "postgresql_replica" name "postgresql_replica"
run_list %w( run_list [
kosmos_postgresql::hostsfile "kosmos_postgresql::hostsfile",
kosmos_postgresql::replica "kosmos_postgresql::replica",
kosmos_postgresql::firewall "kosmos_postgresql::firewall",
) "kosmos_postgresql::management_scripts"
]

View File

@@ -0,0 +1,8 @@
name "postgresql_replica_logical"
run_list [
"kosmos_postgresql::hostsfile",
"kosmos_postgresql::replica_logical",
"kosmos_postgresql::firewall",
"kosmos_postgresql::management_scripts"
]

View File

@@ -8,8 +8,8 @@ upstream _<%= @upstream_name %> {
<% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%> <% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%>
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
listen 443 ssl http2; listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
listen [::]:443 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;

View File

@@ -230,7 +230,6 @@ systemd_unit "akkounts.service" do
WorkingDirectory: deploy_path, WorkingDirectory: deploy_path,
Environment: "RAILS_ENV=#{rails_env} SOLID_QUEUE_IN_PUMA=true", Environment: "RAILS_ENV=#{rails_env} SOLID_QUEUE_IN_PUMA=true",
ExecStart: "#{bundle_path} exec puma -C config/puma.rb --pidfile #{deploy_path}/tmp/puma.pid", ExecStart: "#{bundle_path} exec puma -C config/puma.rb --pidfile #{deploy_path}/tmp/puma.pid",
ExecStop: "#{bundle_path} exec puma -C config/puma.rb --pidfile #{deploy_path}/tmp/puma.pid stop",
ExecReload: "#{bundle_path} exec pumactl -F config/puma.rb --pidfile #{deploy_path}/tmp/puma.pid phased-restart", ExecReload: "#{bundle_path} exec pumactl -F config/puma.rb --pidfile #{deploy_path}/tmp/puma.pid phased-restart",
PIDFile: "#{deploy_path}/tmp/puma.pid", PIDFile: "#{deploy_path}/tmp/puma.pid",
TimeoutSec: "10", TimeoutSec: "10",

View File

@@ -11,7 +11,7 @@ proxy_cache_path <%= node[:openresty][:cache_dir] %>/akkounts levels=1:2
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @domain %>; server_name <%= @domain %>;
if ($host != $server_name) { if ($host != $server_name) {

View File

@@ -7,7 +7,7 @@ upstream _akkounts_api {
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @domain %>; server_name <%= @domain %>;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;

View File

@@ -1,49 +1,86 @@
#!/bin/bash #!/bin/bash
set -e
set -o pipefail
# Calculate yesterday's date in YYYY-MM-DD format # Calculate yesterday's date in YYYY-MM-DD format
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d) YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
echo "Starting price tracking for $YESTERDAY" >&2 echo "Starting price tracking for $YESTERDAY" >&2
# Helper function to perform HTTP requests with retries
# Usage: make_request <retries> <method> <url> [data] [header1] [header2] ...
make_request() {
local retries=$1
local method=$2
local url=$3
local data=$4
shift 4
local headers=("$@")
local count=0
local wait_time=3
local response
while [ "$count" -lt "$retries" ]; do
local curl_opts=(-s -S -f -X "$method")
if [ -n "$data" ]; then
curl_opts+=(-d "$data")
fi
for h in "${headers[@]}"; do
curl_opts+=(-H "$h")
done
if response=$(curl "${curl_opts[@]}" "$url"); then
echo "$response"
return 0
fi
echo "Request to $url failed (Attempt $((count+1))/$retries). Retrying in ${wait_time}s..." >&2
sleep "$wait_time"
count=$((count + 1))
done
echo "ERROR: Request to $url failed after $retries attempts" >&2
return 1
}
# Fetch and process rates for a fiat currency # Fetch and process rates for a fiat currency
get_price_data() { get_price_data() {
local currency=$1 local currency=$1
local data avg open24 last local data avg open24 last
data=$(curl -s "https://www.bitstamp.net/api/v2/ticker/btc${currency,,}/") if data=$(make_request 3 "GET" "https://www.bitstamp.net/api/v2/ticker/btc${currency,,}/" ""); then
if [ $? -eq 0 ] && [ ! -z "$data" ]; then
echo "Successfully retrieved ${currency} price data" >&2 echo "Successfully retrieved ${currency} price data" >&2
open24=$(echo "$data" | jq -r '.open_24') open24=$(echo "$data" | jq -r '.open_24')
last=$(echo "$data" | jq -r '.last') last=$(echo "$data" | jq -r '.last')
avg=$(( (${open24%.*} + ${last%.*}) / 2 )) avg=$(echo "$open24 $last" | awk '{printf "%.0f", ($1 + $2) / 2}')
echo $avg echo $avg
else else
echo "ERROR: Failed to retrieve ${currency} price data" >&2 echo "ERROR: Failed to retrieve ${currency} price data" >&2
exit 1 return 1
fi fi
} }
# Get price data for each currency # Get price data for each currency
usd_avg=$(get_price_data "USD") usd_avg=$(get_price_data "USD") || exit 1
eur_avg=$(get_price_data "EUR") eur_avg=$(get_price_data "EUR") || exit 1
gbp_avg=$(get_price_data "GBP") gbp_avg=$(get_price_data "GBP") || exit 1
# Create JSON # Create JSON
json="{\"EUR\":$eur_avg,\"USD\":$usd_avg,\"GBP\":$gbp_avg}" json=$(jq -n \
--argjson eur "$eur_avg" \
--argjson usd "$usd_avg" \
--argjson gbp "$gbp_avg" \
'{"EUR": $eur, "USD": $usd, "GBP": $gbp}')
echo "Rates: $json" >&2 echo "Rates: $json" >&2
# PUT in remote storage # PUT in remote storage
response=$(curl -X PUT \ if make_request 3 "PUT" "<%= @rs_base_url %>/$YESTERDAY" "$json" \
-H "Authorization: Bearer $RS_AUTH" \ "Authorization: Bearer $RS_AUTH" \
-H "Content-Type: application/json" \ "Content-Type: application/json" > /dev/null; then
-d "$json" \
-w "%{http_code}" \
-s \
-o /dev/null \
"<%= @rs_base_url %>/$YESTERDAY")
if [ "$response" -eq 200 ] || [ "$response" -eq 201 ]; then
echo "Successfully uploaded price data" >&2 echo "Successfully uploaded price data" >&2
else else
echo "ERROR: Failed to upload price data. HTTP status: $response" >&2 echo "ERROR: Failed to upload price data" >&2
exit 1 exit 1
fi fi

View File

@@ -49,7 +49,7 @@ server {
client_max_body_size 100M; client_max_body_size 100M;
server_name <%= @server_name %>; server_name <%= @server_name %>;
listen 443 ssl http2; listen 443 ssl http2;
listen [::]:443 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
access_log <%= node[:nginx][:log_dir] %>/btcpayserver.access.log json; access_log <%= node[:nginx][:log_dir] %>/btcpayserver.access.log json;
error_log <%= node[:nginx][:log_dir] %>/btcpayserver.error.log warn; error_log <%= node[:nginx][:log_dir] %>/btcpayserver.error.log warn;

View File

@@ -7,7 +7,7 @@ upstream _lndhub {
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
add_header Strict-Transport-Security "max-age=15768000"; add_header Strict-Transport-Security "max-age=15768000";

View File

@@ -49,7 +49,7 @@ server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
<% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%> <% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%>
listen 443 ssl http2; listen 443 ssl http2;
listen [::]:443 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
<% else -%> <% else -%>
listen 80; listen 80;
<% end -%> <% end -%>

View File

@@ -3,7 +3,7 @@
server { server {
listen 443 ssl http2; listen 443 ssl http2;
listen [::]:443 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;

View File

@@ -7,7 +7,7 @@ upstream _express_<%= @server_name.gsub(".", "_") %> {
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
add_header Strict-Transport-Security "max-age=15768000"; add_header Strict-Transport-Security "max-age=15768000";

View File

@@ -12,7 +12,7 @@ upstream _ipfs_api {
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
access_log /var/log/nginx/<%= @server_name %>.access.log; access_log /var/log/nginx/<%= @server_name %>.access.log;
error_log /var/log/nginx/<%= @server_name %>.error.log; error_log /var/log/nginx/<%= @server_name %>.error.log;

View File

@@ -21,7 +21,7 @@ proxy_cache_path /var/cache/nginx/mastodon levels=1:2
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
include <%= @shared_config_path %>; include <%= @shared_config_path %>;

View File

@@ -3,7 +3,7 @@
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @domain %>; server_name <%= @domain %>;
root /var/www/<%= @domain %>/site; root /var/www/<%= @domain %>/site;

View File

@@ -9,7 +9,7 @@ upstream _discourse {
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;

View File

@@ -1,2 +1,6 @@
node.default["kosmos_drone"]["domain"] = "drone.kosmos.org" node.default["kosmos_drone"]["domain"] = "drone.kosmos.org"
node.default["kosmos_drone"]["upstream_port"] = 80 node.default["kosmos_drone"]["upstream_port"] = 80
node.default["kosmos_drone"]["pg_host"] = "pg.kosmos.local"
node.default["kosmos_drone"]["pg_port"] = 5432
node.default["kosmos_drone"]["pg_db"] = "drone"
node.default["kosmos_drone"]["pg_user"] = "drone"

View File

@@ -9,11 +9,11 @@ credentials = data_bag_item("credentials", "drone")
drone_credentials = data_bag_item('credentials', 'drone') drone_credentials = data_bag_item('credentials', 'drone')
postgres_config = { postgres_config = {
username: "drone", host: node["kosmos_drone"]["pg_host"],
password: drone_credentials["postgresql_password"], port: node["kosmos_drone"]["pg_port"],
host: "pg.kosmos.local", database: node["kosmos_drone"]["pg_db"],
port: 5432, username: node["kosmos_drone"]["pg_user"],
database: "drone" password: drone_credentials["postgresql_password"]
} }
directory deploy_path do directory deploy_path do

View File

@@ -8,7 +8,7 @@ upstream _drone {
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;

View File

@@ -4,7 +4,7 @@ upstream garage_s3 {
server { 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; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;

View File

@@ -1,6 +1,6 @@
server { 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; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
@@ -18,6 +18,7 @@ server {
} }
location / { location / {
add_header 'Access-Control-Allow-Origin' '*' always;
proxy_intercept_errors on; proxy_intercept_errors on;
proxy_cache garage_cache; proxy_cache garage_cache;
proxy_pass http://garage_web; proxy_pass http://garage_web;

View File

@@ -1,11 +1,12 @@
node.default["gitea"]["version"] = "1.23.8" node.default["gitea"]["version"] = "1.25.4"
node.default["gitea"]["checksum"] = "827037e7ca940866918abc62a7488736923396c467fcb4acd0dd9829bb6a6f4c" node.default["gitea"]["checksum"] = "a3031853e67c53714728ef705642c9046a11fb0ea356aff592e23efe6114607d"
node.default["gitea"]["repo"] = nil node.default["gitea"]["repo"] = nil
node.default["gitea"]["revision"] = nil node.default["gitea"]["revision"] = nil
node.default["gitea"]["working_directory"] = "/var/lib/gitea" node.default["gitea"]["working_directory"] = "/var/lib/gitea"
node.default["gitea"]["port"] = 3000 node.default["gitea"]["port"] = 3000
node.default["gitea"]["postgresql_host"] = "localhost:5432" node.default["gitea"]["postgresql_host"] = "localhost:5432"
node.default["gitea"]["domain"] = "gitea.kosmos.org" node.default["gitea"]["domain"] = "gitea.kosmos.org"
node.default["gitea"]["email"] = "gitea@kosmos.org"
node.default["gitea"]["config"] = { node.default["gitea"]["config"] = {
"log": { "log": {
@@ -22,5 +23,5 @@ node.default["gitea"]["config"] = {
} }
} }
node.default["gitea"]["act_runner"]["version"] = "0.2.6" node.default["gitea"]["act_runner"]["version"] = "0.2.13"
node.default["gitea"]["act_runner"]["checksum"] = "234c2bdb871e7b0bfb84697f353395bfc7819faf9f0c0443845868b64a041057" node.default["gitea"]["act_runner"]["checksum"] = "3acac8b506ac8cadc88a55155b5d6378f0fab0b8f62d1e0c0450f4ccd69733e2"

View File

@@ -19,6 +19,17 @@ jwt_secret = gitea_data_bag_item["jwt_secret"]
internal_token = gitea_data_bag_item["internal_token"] internal_token = gitea_data_bag_item["internal_token"]
secret_key = gitea_data_bag_item["secret_key"] secret_key = gitea_data_bag_item["secret_key"]
apt_repository "git-core-ppa" do
uri "http://ppa.launchpad.net/git-core/ppa/ubuntu"
components ["main"]
key "E1DF1F24"
action :add
only_if do
node['platform'] == 'ubuntu' &&
Gem::Version.new(node['platform_version']) < Gem::Version.new('22.04')
end
end
package "git" package "git"
user "git" do user "git" do
@@ -26,6 +37,13 @@ user "git" do
home "/home/git" home "/home/git"
end end
directory "/home/git/.ssh" do
owner "git"
group "git"
mode "0700"
recursive true
end
directory working_directory do directory working_directory do
owner "git" owner "git"
group "git" group "git"
@@ -78,6 +96,8 @@ if node.chef_environment == "production"
end end
config_variables = { config_variables = {
domain: node["gitea"]["domain"],
email: node["gitea"]["email"],
working_directory: working_directory, working_directory: working_directory,
git_home_directory: git_home_directory, git_home_directory: git_home_directory,
repository_root_directory: repository_root_directory, repository_root_directory: repository_root_directory,
@@ -98,6 +118,16 @@ config_variables = {
s3_bucket: gitea_data_bag_item["s3_bucket"] s3_bucket: gitea_data_bag_item["s3_bucket"]
} }
bash "Generate git ed25519 keypair" do
user "git"
group "git"
cwd git_home_directory
code <<-EOH
ssh-keygen -t ed25519 -f #{git_home_directory}/.ssh/id_ed25519
EOH
creates "#{git_home_directory}/.ssh/id_ed25519"
end
template "#{config_directory}/app.ini" do template "#{config_directory}/app.ini" do
source "app.ini.erb" source "app.ini.erb"
owner "git" owner "git"
@@ -129,7 +159,7 @@ template "/etc/systemd/system/gitea.service" do
git_home_directory: git_home_directory, git_home_directory: git_home_directory,
config_directory: config_directory, config_directory: config_directory,
gitea_binary_path: gitea_binary_path gitea_binary_path: gitea_binary_path
notifies :run, "execute[systemctl daemon-reload]", :delayed notifies :run, "execute[systemctl daemon-reload]", :immediately
end end
service "gitea" do service "gitea" do

View File

@@ -2,12 +2,12 @@ APP_NAME = Gitea
RUN_MODE = prod RUN_MODE = prod
[server] [server]
SSH_DOMAIN = gitea.kosmos.org SSH_DOMAIN = <%= @domain %>
HTTP_PORT = 3000 HTTP_PORT = 3000
DISABLE_SSH = false DISABLE_SSH = false
SSH_PORT = 22 SSH_PORT = 22
PROTOCOL = http PROTOCOL = http
DOMAIN = gitea.kosmos.org DOMAIN = <%= @domain %>
# Gitea is running behind an nginx reverse load balancer, use an HTTPS root URL # Gitea is running behind an nginx reverse load balancer, use an HTTPS root URL
ROOT_URL = https://%(DOMAIN)s ROOT_URL = https://%(DOMAIN)s
# REDIRECT_OTHER_PORT = true # REDIRECT_OTHER_PORT = true
@@ -30,6 +30,16 @@ MAX_OPEN_CONNS = 20
ROOT = <%= @repository_root_directory %> ROOT = <%= @repository_root_directory %>
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true
[repository.signing]
SIGNING_KEY = <%= @git_home_directory %>/.ssh/id_ed25519.pub
SIGNING_NAME = Gitea
SIGNING_EMAIL = git@<%= @domain %>
SIGNING_FORMAT = ssh
INITIAL_COMMIT = always
CRUD_ACTIONS = always
WIKI = always
MERGES = always
# [indexer] # [indexer]
# ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve # ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
@@ -46,7 +56,7 @@ SMTP_ADDR = <%= @smtp_addr %>
SMTP_PORT = <%= @smtp_port %> SMTP_PORT = <%= @smtp_port %>
USER = <%= @smtp_user %> USER = <%= @smtp_user %>
PASSWD = <%= @smtp_password %> PASSWD = <%= @smtp_password %>
FROM = gitea@kosmos.org FROM = <%= @email %>
[security] [security]
INTERNAL_TOKEN = <%= @internal_token %> INTERNAL_TOKEN = <%= @internal_token %>

View File

@@ -4,5 +4,6 @@ upstream _gitea_ssh {
server { server {
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>22; listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>22;
listen [::]:22;
proxy_pass _gitea_ssh; proxy_pass _gitea_ssh;
} }

View File

@@ -6,7 +6,7 @@ upstream _gitea_web {
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;

View File

@@ -1,9 +1,9 @@
release = "20240514" release = "20260320"
img_filename = "ubuntu-22.04-server-cloudimg-amd64-disk-kvm" img_filename = "ubuntu-22.04-server-cloudimg-amd64-disk-kvm"
node.default["kosmos_kvm"]["host"]["qemu_base_image"] = { node.default["kosmos_kvm"]["host"]["qemu_base_image"] = {
"url" => "https://cloud-images.ubuntu.com/releases/jammy/release-#{release}/#{img_filename}.img", "url" => "https://cloud-images.ubuntu.com/releases/jammy/release-#{release}/#{img_filename}.img",
"checksum" => "2e7698b3ebd7caead06b08bd3ece241e6ce294a6db01f92ea12bcb56d6972c3f", "checksum" => "f7173eb7137b4f0ebeaea8fffe68ecdab1e3c787bde1fd8dfdf27103554332b3",
"path" => "/var/lib/libvirt/images/base/#{img_filename}-#{release}.qcow2" "path" => "/var/lib/libvirt/images/base/#{img_filename}-#{release}.qcow2"
} }

View File

@@ -3,7 +3,7 @@
# Recipe:: host # Recipe:: host
# #
package %w(virtinst libvirt-daemon-system) package %w(virtinst libvirt-daemon-system libvirt-clients)
directory "/var/lib/libvirt/images/base" do directory "/var/lib/libvirt/images/base" do
recursive true recursive true

View File

@@ -17,7 +17,7 @@ DISKSIZE=${4:-10} # 10GB default
# Directory where image files will be stored # Directory where image files will be stored
IMAGE_DIR=/var/lib/libvirt/images IMAGE_DIR=/var/lib/libvirt/images
IMAGE_PATH=$IMAGE_DIR/${VMNAME}.qcow2 IMAGE_PATH=$IMAGE_DIR/${VMNAME}.qcow2
CIDATA_PATH=${IMAGE_DIR}/cidata-${VMNAME}.iso CIDATA_PATH=${IMAGE_DIR}/${VMNAME}-cloudinit
BASE_FILE=<%= @base_image_path %> BASE_FILE=<%= @base_image_path %>
# Create the VM image if it does not already exist # Create the VM image if it does not already exist
@@ -38,9 +38,8 @@ qemu-img info "$IMAGE_PATH"
# Check if the cloud-init metadata file exists # Check if the cloud-init metadata file exists
# if not, generate it # if not, generate it
if [ ! -r $CIDATA_PATH ]; then if [ ! -r $CIDATA_PATH ]; then
pushd $(dirname $CIDATA_PATH) mkdir -p $CIDATA_PATH
mkdir -p $VMNAME pushd $CIDATA_PATH
cd $VMNAME
cat > user-data <<-EOS cat > user-data <<-EOS
#cloud-config #cloud-config
@@ -62,25 +61,19 @@ instance-id: $VMNAME
local-hostname: $VMNAME local-hostname: $VMNAME
EOS EOS
genisoimage -output "$CIDATA_PATH" -volid cidata -joliet -rock user-data meta-data
chown libvirt-qemu:kvm "$CIDATA_PATH"
chmod 600 "$CIDATA_PATH"
popd popd
fi fi
# setting --os-variant to ubuntu20.04 and ubuntu18.04 breaks SSH and networking
virt-install \ virt-install \
--name "$VMNAME" \ --name "$VMNAME" \
--ram "$RAM" \ --ram "$RAM" \
--vcpus "$CPUS" \ --vcpus "$CPUS" \
--cpu host \ --cpu host \
--arch x86_64 \ --arch x86_64 \
--os-type linux \ --osinfo detect=on,name=ubuntujammy \
--os-variant ubuntu16.04 \
--hvm \ --hvm \
--virt-type kvm \ --virt-type kvm \
--disk "$IMAGE_PATH" \ --disk "$IMAGE_PATH" \
--cdrom "$CIDATA_PATH" \
--boot hd \ --boot hd \
--network=bridge=virbr0,model=virtio \ --network=bridge=virbr0,model=virtio \
--graphics none \ --graphics none \
@@ -88,4 +81,5 @@ virt-install \
--console pty \ --console pty \
--channel unix,mode=bind,path=/var/lib/libvirt/qemu/$VMNAME.guest_agent.0,target_type=virtio,name=org.qemu.guest_agent.0 \ --channel unix,mode=bind,path=/var/lib/libvirt/qemu/$VMNAME.guest_agent.0,target_type=virtio,name=org.qemu.guest_agent.0 \
--autostart \ --autostart \
--import --import \
--cloud-init root-password-generate=off,disable=on,meta-data=$CIDATA_PATH/meta-data,user-data=$CIDATA_PATH/user-data

View File

@@ -12,7 +12,7 @@ upstream _<%= @app_name %> {
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
access_log <%= node[:nginx][:log_dir] %>/<%= @app_name %>.access.log; # TODO json_liquor_cabinet; access_log <%= node[:nginx][:log_dir] %>/<%= @app_name %>.access.log; # TODO json_liquor_cabinet;

View File

@@ -0,0 +1 @@
node.default["openresty"]["listen_ipv6"] = "::"

View File

@@ -1,3 +1,8 @@
node.default['kosmos_postgresql']['postgresql_version'] = "14"
# This is set to false by default, and set to true in the server resource # This is set to false by default, and set to true in the server resource
# for replicas. # for replicas.
node.default['kosmos_postgresql']['ready_to_set_up_replica'] = false node.default['kosmos_postgresql']['ready_to_set_up_replica'] = false
# Address space from which clients are allowed to connect
node.default['kosmos_postgresql']['access_addr'] = "10.1.1.0/24"

View File

@@ -0,0 +1,31 @@
#!/bin/bash
set -euo pipefail
DB_NAME="${1:?Usage: $0 <database_name>}"
echo "== Processing DB: $DB_NAME =="
# Create publication (idempotent)
psql -d "$DB_NAME" -v ON_ERROR_STOP=1 <<'SQL'
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_publication WHERE pubname = 'migrate_pub'
) THEN
CREATE PUBLICATION migrate_pub FOR ALL TABLES;
END IF;
END
$$;
SQL
# Create logical replication slot (idempotent-ish)
SLOT="migrate_slot_${DB_NAME}"
if ! psql -d "$DB_NAME" -Atqc "SELECT 1 FROM pg_replication_slots WHERE slot_name = '$SLOT'" | grep -q 1; then
echo " Creating slot: $SLOT"
psql -d "$DB_NAME" -c "SELECT pg_create_logical_replication_slot('$SLOT', 'pgoutput');"
else
echo " Slot already exists: $SLOT"
fi
echo "== Done =="

View File

@@ -0,0 +1,34 @@
#!/bin/bash
set -e
echo "== Creating publication in each database =="
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "Processing DB: $db"
# Create publication (idempotent)
psql -d "$db" -v ON_ERROR_STOP=1 <<SQL
DO \$\$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_publication WHERE pubname = 'migrate_pub'
) THEN
CREATE PUBLICATION migrate_pub FOR ALL TABLES;
END IF;
END
\$\$;
SQL
# Create logical replication slot (idempotent-ish)
SLOT="migrate_slot_${db}"
if ! psql -d "$db" -Atqc "SELECT 1 FROM pg_replication_slots WHERE slot_name = '$SLOT'" | grep -q 1; then
echo " Creating slot: $SLOT"
psql -d "$db" -c "SELECT pg_create_logical_replication_slot('$SLOT', 'pgoutput');"
else
echo " Slot already exists: $SLOT"
fi
done
echo "== Done =="

View File

@@ -0,0 +1,34 @@
#!/bin/bash
set -e
echo "== Dropping subscriptions slots and publications =="
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "Processing DB: $db"
SLOT="migrate_slot_${db}"
# Drop slot if exists
if psql -d "$db" -Atqc "SELECT 1 FROM pg_replication_slots WHERE slot_name = '$SLOT'" | grep -q 1; then
echo " Dropping slot: $SLOT"
psql -d "$db" -c "SELECT pg_drop_replication_slot('$SLOT');"
else
echo " Slot not found: $SLOT"
fi
# Drop publication if exists
psql -d "$db" -v ON_ERROR_STOP=1 <<SQL
DO \$\$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_publication WHERE pubname = 'migrate_pub'
) THEN
DROP PUBLICATION migrate_pub;
END IF;
END
\$\$;
SQL
done
echo "== Done =="

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -e
echo "== Dropping subscriptions =="
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "Processing DB: $db"
SUB="migrate_sub_${db}"
# Check if subscription exists
EXISTS=$(psql -d "$db" -Atqc "SELECT 1 FROM pg_subscription WHERE subname = '$SUB'")
if [ "$EXISTS" = "1" ]; then
echo " Found subscription: $SUB"
# Disable first (good practice)
psql -d "$db" -c "ALTER SUBSCRIPTION $SUB DISABLE;"
# Drop it (must be top-level)
psql -d "$db" -c "DROP SUBSCRIPTION $SUB;"
else
echo " No subscription: $SUB"
fi
done
echo "== Done =="

View File

@@ -0,0 +1,9 @@
#!/bin/bash
cd /tmp && \
(pg_dumpall --globals-only > globals.sql) && \
psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN (''template1'',''postgres'')" | \
xargs -I{} -P4 sh -c "
pg_dump -Fd -j 4 -d \"{}\" -f dump_{} &&
tar -cf - dump_{} | zstd -19 -T0 > dump_{}.tar.zst &&
rm -rf dump_{}
"

View File

@@ -0,0 +1,10 @@
#!/bin/bash
set -euo pipefail
DB_NAME="${1:?Usage: $0 <database_name>}"
cd /tmp
pg_dump -Fd -j 4 -d "$DB_NAME" -f "dump_${DB_NAME}"
tar -cf - "dump_${DB_NAME}" | zstd -19 -T0 > "dump_${DB_NAME}.tar.zst"
rm -rf "dump_${DB_NAME}"

View File

@@ -0,0 +1,35 @@
#!/bin/bash
set -e
DB="$1"
if [ -z "$DB" ]; then
echo "Usage: $0 <database>"
exit 1
fi
echo "== Fixing sequences in database: $DB =="
SQL=$(psql -d "$DB" -Atqc "
SELECT
'SELECT setval(' ||
quote_literal(pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname)) ||
', COALESCE(MAX(' || quote_ident(a.attname) || '), 0) + 1, false) FROM ' ||
quote_ident(n.nspname)||'.'||quote_ident(c.relname) || ';'
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE c.relkind = 'r'
AND a.attnum > 0
AND NOT a.attisdropped
AND pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname) IS NOT NULL;
")
if [ -z "$SQL" ]; then
echo "No sequences found in $DB"
exit 0
fi
echo "$SQL" | psql -d "$DB"
echo "== Done =="

View File

@@ -0,0 +1,38 @@
#!/bin/bash
set -e
echo "== Fixing sequences across all databases =="
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "---- DB: $db ----"
# Generate fix statements
SQL=$(psql -d "$db" -Atqc "
SELECT
'SELECT setval(' ||
quote_literal(pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname)) ||
', COALESCE(MAX(' || quote_ident(a.attname) || '), 0) + 1, false) FROM ' ||
quote_ident(n.nspname)||'.'||quote_ident(c.relname) || ';'
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE c.relkind = 'r'
AND a.attnum > 0
AND NOT a.attisdropped
AND pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname) IS NOT NULL;
")
if [ -z "$SQL" ]; then
echo "No sequences found in $db"
continue
fi
echo "Fixing sequences in $db..."
# Execute generated statements
echo "$SQL" | psql -d "$db"
done
echo "== Done fixing sequences =="

View File

@@ -0,0 +1,5 @@
#!/bin/bash
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "DB: $db"
psql -d "$db" -Atqc "SELECT pubname FROM pg_publication;"
done

View File

@@ -0,0 +1,5 @@
#!/bin/bash
psql -c "
SELECT slot_name,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn))
FROM pg_replication_slots;"

View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -euo pipefail
psql -Atqc "
SELECT datname
FROM pg_database
WHERE datallowconn
AND datname NOT IN ('template1','postgres')
" | while read -r db; do
result=$(psql -X -At -d "$db" -c "SELECT * FROM pg_stat_subscription;" 2>/dev/null || true)
if [[ -n "$result" ]]; then
echo "==== DB: $db ===="
echo "$result"
fi
done

View File

@@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
cd /tmp
for f in dump_*.tar.zst; do
db=$(echo $f | sed "s/dump_\(.*\)\.tar\.zst/\1/")
echo "Restoring $db"
zstd -d "$f" -c | tar -xf -
pg_restore -j 4 -d "$db" dump_$db
rm -rf "dump_$db"
done

View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -euo pipefail
DB_NAME="${1:?Usage: $0 <database_name>}"
cd /tmp
FILE="dump_${DB_NAME}.tar.zst"
DIR="dump_${DB_NAME}"
echo "Restoring $DB_NAME"
zstd -d "$FILE" -c | tar -xf -
pg_restore -j 4 -d "$DB_NAME" "$DIR"
rm -rf "$DIR"

View File

@@ -36,10 +36,8 @@ class Chef
end end
end end
def postgresql_service_name def postgresql_version
postgresql_version = "12" node['kosmos_postgresql']['postgresql_version']
"postgresql@#{postgresql_version}-main"
end end
end end
end end

View File

@@ -0,0 +1,121 @@
#
# Cookbook:: kosmos_postgresql
# Recipe:: management_scripts
#
credentials = data_bag_item('credentials', 'postgresql')
cookbook_file "/usr/local/bin/pg_dump_all_databases" do
source "dump_all_databases.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_dump_database" do
source "dump_database.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_restore_all_databases" do
source "restore_all_databases.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_restore_database" do
source "restore_database.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_create_replication_publications" do
source "create_publications.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_create_replication_publication" do
source "create_publication.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_drop_replication_publications" do
source "drop_publications.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_list_replication_publications" do
source "list_publications.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_list_replication_slots" do
source "list_replication_slots.sh"
user "postgres"
group "postgres"
mode "0744"
end
template "/usr/local/bin/pg_create_replication_subscriptions" do
source "create_subscriptions.sh.erb"
user "postgres"
group "postgres"
mode "0740"
variables pg_host: "pg.kosmos.local",
pg_port: 5432,
pg_user: "replication",
pg_pass: credentials["replication_password"]
sensitive true
end
template "/usr/local/bin/pg_create_replication_subscription" do
source "create_subscription.sh.erb"
user "postgres"
group "postgres"
mode "0740"
variables pg_host: "pg.kosmos.local",
pg_port: 5432,
pg_user: "replication",
pg_pass: credentials["replication_password"]
sensitive true
end
cookbook_file "/usr/local/bin/pg_drop_replication_subscriptions" do
source "drop_subscriptions.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_list_replication_subscriptions" do
source "list_subscriptions.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_fix_sequences_in_all_databases" do
source "fix_sequences.sh"
user "postgres"
group "postgres"
mode "0744"
end
cookbook_file "/usr/local/bin/pg_fix_sequences" do
source "fix_sequences.sh"
user "postgres"
group "postgres"
mode "0744"
end

View File

@@ -3,31 +3,6 @@
# Recipe:: primary # Recipe:: primary
# #
postgresql_version = "12"
postgresql_service = "postgresql@#{postgresql_version}-main"
service postgresql_service do
supports restart: true, status: true, reload: true
end
postgresql_custom_server postgresql_version do postgresql_custom_server postgresql_version do
role "primary" role "primary"
end end
postgresql_access "zerotier members" do
access_type "host"
access_db "all"
access_user "all"
access_addr "10.1.1.0/24"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
postgresql_access "zerotier members replication" do
access_type "host"
access_db "replication"
access_user "replication"
access_addr "10.1.1.0/24"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end

View File

@@ -3,54 +3,34 @@
# Recipe:: replica # Recipe:: replica
# #
postgresql_version = "12"
postgresql_service = "postgresql@#{postgresql_version}-main"
postgresql_custom_server postgresql_version do postgresql_custom_server postgresql_version do
role "replica" role "replica"
end end
service postgresql_service do
supports restart: true, status: true, reload: true
end
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
primary = postgresql_primary primary = postgresql_primary
unless primary.nil? if primary.nil?
# TODO Chef::Log.warn("No PostgreSQL primary node found. Skipping replication setup.")
return
end
postgresql_service_name = "postgresql@#{postgresql_version}-main"
postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main" postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main"
# FIXME get zerotier IP # TODO Replace pg.kosmos.local with private IP once available
# via proper node attribute
# https://gitea.kosmos.org/kosmos/chef/issues/263
execute "set up replication" do execute "set up replication" do
command <<-EOF command <<-EOF
systemctl stop #{postgresql_service} systemctl stop #{postgresql_service_name}
mv #{postgresql_data_dir} #{postgresql_data_dir}.old mv #{postgresql_data_dir} #{postgresql_data_dir}.old
pg_basebackup -h pg.kosmos.local -U replication -D #{postgresql_data_dir} -R pg_basebackup -h pg.kosmos.local -U replication -D #{postgresql_data_dir} -R
chown -R postgres:postgres #{postgresql_data_dir} chown -R postgres:postgres #{postgresql_data_dir}
systemctl start #{postgresql_service} systemctl start #{postgresql_service_name}
EOF EOF
environment 'PGPASSWORD' => postgresql_data_bag_item['replication_password'] environment 'PGPASSWORD' => postgresql_data_bag_item['replication_password']
sensitive true sensitive true
not_if { ::File.exist? "#{postgresql_data_dir}/standby.signal" } not_if { ::File.exist? "#{postgresql_data_dir}/standby.signal" }
end end
postgresql_access "zerotier members" do
access_type "host"
access_db "all"
access_user "all"
access_addr "10.1.1.0/24"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
postgresql_access "zerotier members replication" do
access_type "host"
access_db "replication"
access_user "replication"
access_addr "10.1.1.0/24"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
end

View File

@@ -0,0 +1,15 @@
#
# Cookbook:: kosmos_postgresql
# Recipe:: replica_logical
#
postgresql_custom_server postgresql_version do
role "replica_logical"
end
# primary = postgresql_primary
#
# if primary.nil?
# Chef::Log.warn("No PostgreSQL primary node found. Skipping replication setup.")
# return
# end

View File

@@ -44,25 +44,28 @@ action :create do
shared_buffers = if node['memory']['total'].to_i / 1024 < 1024 # < 1GB RAM shared_buffers = if node['memory']['total'].to_i / 1024 < 1024 # < 1GB RAM
"128MB" "128MB"
else # >= 1GB RAM, use 50% of total RAM else # >= 1GB RAM, use 25% of total RAM
"#{node['memory']['total'].to_i / 1024 / 2}MB" "#{node['memory']['total'].to_i / 1024 / 4}MB"
end end
additional_config = { additional_config = {
max_connections: 200, # default max_connections: 200, # default
shared_buffers: shared_buffers, shared_buffers: shared_buffers,
work_mem: "4MB",
unix_socket_directories: "/var/run/postgresql", unix_socket_directories: "/var/run/postgresql",
dynamic_shared_memory_type: "posix", dynamic_shared_memory_type: "posix",
timezone: "UTC", # default is GMT timezone: "UTC", # default is GMT
listen_addresses: "0.0.0.0", listen_addresses: "0.0.0.0",
promote_trigger_file: "#{postgresql_data_dir}/failover.trigger", promote_trigger_file: "#{postgresql_data_dir}/failover.trigger",
wal_keep_segments: 256 wal_level: "logical",
wal_keep_size: 4096, # 256 segments, 16MB each
max_replication_slots: 16
} }
postgresql_server_conf "main" do postgresql_server_conf "main" do
version postgresql_version version postgresql_version
additional_config additional_config additional_config additional_config
notifies :reload, "service[#{postgresql_service}]", :delayed notifies :restart, "service[#{postgresql_service}]", :delayed
end end
postgresql_user "replication" do postgresql_user "replication" do
@@ -70,6 +73,24 @@ action :create do
replication true replication true
password postgresql_credentials['replication_password'] password postgresql_credentials['replication_password']
end end
postgresql_access "all members" do
access_type "host"
access_db "all"
access_user "all"
access_addr node['kosmos_postgresql']['access_addr']
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
postgresql_access "replication members" do
access_type "host"
access_db "replication"
access_user "replication"
access_addr node['kosmos_postgresql']['access_addr']
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
end end
action_class do action_class do

View File

@@ -0,0 +1,31 @@
#!/bin/bash
set -euo pipefail
DB_NAME="${1:?Usage: $0 <database_name>}"
echo "== Processing DB: $DB_NAME =="
SLOT="migrate_slot_${DB_NAME}"
SUB="migrate_sub_${DB_NAME}"
psql -d "$DB_NAME" -v ON_ERROR_STOP=1 <<SQL
DO \$\$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_subscription WHERE subname = '$SUB'
) THEN
CREATE SUBSCRIPTION $SUB
CONNECTION 'host=<%= @pg_host %> port=<%= @pg_port %> dbname=$DB_NAME user=<%= @pg_user %> password=<%= @pg_pass %>'
PUBLICATION migrate_pub
WITH (
slot_name = '$SLOT',
create_slot = false,
copy_data = false,
enabled = true
);
END IF;
END
\$\$;
SQL
echo "== Done =="

View File

@@ -0,0 +1,34 @@
#!/bin/bash
set -e
echo "== Creating subscriptions for all databases =="
for db in $(psql -Atqc "SELECT datname FROM pg_database WHERE datallowconn AND datname NOT IN ('template1','postgres')"); do
echo "Processing DB: $db"
SLOT="migrate_slot_${db}"
SUB="migrate_sub_${db}"
psql -d "$db" -v ON_ERROR_STOP=1 <<SQL
DO \$\$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_subscription WHERE subname = '$SUB'
) THEN
CREATE SUBSCRIPTION $SUB
CONNECTION 'host=<%= @pg_host %> port=<%= @pg_port %> dbname=$db user=<%= @pg_user %> password=<%= @pg_pass %>'
PUBLICATION migrate_pub
WITH (
slot_name = '$SLOT',
create_slot = false,
copy_data = false,
enabled = true
);
END IF;
END
\$\$;
SQL
done
echo "== Done =="

View File

@@ -6,7 +6,7 @@ upstream _<%= @upstream_name %> {
server { 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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @domain %>; server_name <%= @domain %>;

View File

@@ -13,7 +13,7 @@ upstream _substr {
server { server {
server_name <%= @domain %>; server_name <%= @domain %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
access_log "/var/log/nginx/<%= @domain %>.access.log"; access_log "/var/log/nginx/<%= @domain %>.access.log";
error_log "/var/log/nginx/<%= @domain %>.error.log"; error_log "/var/log/nginx/<%= @domain %>.error.log";

View File

@@ -3,7 +3,7 @@
server { server {
server_name <%= @domain %>; server_name <%= @domain %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
access_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.access.log; access_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.access.log;
error_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.error.log warn; error_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.error.log warn;

View File

@@ -3,7 +3,7 @@
server { server {
server_name <%= @domain %>; server_name <%= @domain %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
root /var/www/<%= @domain %>/public; root /var/www/<%= @domain %>/public;

View File

@@ -3,6 +3,7 @@
server { server {
server_name _; server_name _;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>80 default_server; listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>80 default_server;
listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:80 default_server;
location / { location / {
return 301 https://<%= @domain %>; return 301 https://<%= @domain %>;
@@ -12,7 +13,7 @@ server {
server { server {
server_name <%= @domain %>; server_name <%= @domain %>;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2 default_server; listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2 default_server;
if ($host != $server_name) { if ($host != $server_name) {
return 307 $scheme://$server_name; return 307 $scheme://$server_name;

View File

@@ -5,8 +5,8 @@ upstream _<%= @app_name %> {
<% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%> <% if File.exist?(@ssl_cert) && File.exist?(@ssl_key) -%>
server { server {
listen 443 ssl http2; listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
listen [::]:443 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
server_name <%= @server_name %>; server_name <%= @server_name %>;
access_log <%= node[:nginx][:log_dir] %>/<%= @app_name %>.access.log json; access_log <%= node[:nginx][:log_dir] %>/<%= @app_name %>.access.log json;

View File

@@ -8,7 +8,7 @@ upstream _rs_discourse {
server { server {
server_name <%= @server_name %>; server_name <%= @server_name %>;
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 ssl http2; listen <%= "[#{node['openresty']['listen_ipv6']}]" %>:443 ssl http2;
ssl_certificate <%= @ssl_cert %>; ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>; ssl_certificate_key <%= @ssl_key %>;