diff --git a/Makefile b/Makefile index 05dcb63..ada5305 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -include .envrc +-include .envrc ## help: print this help message .PHONY: help @@ -14,17 +14,68 @@ current_time = $(shell date -Iseconds) git_description = $(shell git describe --always --dirty) linker_flags = '-s -X main.buildTime=${current_time} -X main.version=${git_description}' +production_host = 152.53.236.243 +production_user = root +production_src = /srv/party + +## build/api: build for the current OS and cross-compile for linux/amd64 .PHONY: build/api build/api: - @echo 'Building cmd/api...' - go build -ldflags=${linker_flags} -o=./bin/api ./cmd/api - GOOS=linux GOARCH=amd64 go build -ldflags=${linker_flags} -o=./bin/linux_amd64/api ./cmd/api + @echo 'Building cmd/party...' + go build -ldflags=${linker_flags} -o=./bin/party ./cmd/party + GOOS=linux GOARCH=amd64 go build -ldflags=${linker_flags} -o=./bin/linux_amd64/party ./cmd/party + +## build/package: assemble .deb — runs on the production server, not locally +.PHONY: build/package +build/package: + @echo 'Building binary...' + go build -ldflags=${linker_flags} -o=./bin/party ./cmd/party + @echo 'Assembling .deb...' + rm -rf /tmp/party-pkg + mkdir -p /tmp/party-pkg/DEBIAN + mkdir -p /tmp/party-pkg/usr/bin + mkdir -p /tmp/party-pkg/usr/share/party + mkdir -p /tmp/party-pkg/lib/systemd/system + cp ./bin/party /tmp/party-pkg/usr/bin/party + cp -r ./web /tmp/party-pkg/usr/share/party/ + cp -r ./migrations /tmp/party-pkg/usr/share/party/ + cp ./deploy/party.service /tmp/party-pkg/lib/systemd/system/ + cp ./deploy/DEBIAN/postinst /tmp/party-pkg/DEBIAN/postinst + cp ./deploy/DEBIAN/prerm /tmp/party-pkg/DEBIAN/prerm + cp ./deploy/DEBIAN/postrm /tmp/party-pkg/DEBIAN/postrm + chmod 755 /tmp/party-pkg/DEBIAN/postinst /tmp/party-pkg/DEBIAN/prerm /tmp/party-pkg/DEBIAN/postrm + printf 'Package: party\nVersion: %s\nArchitecture: amd64\nMaintainer: Vicente Ferrari Smith \nDescription: Party\n' \ + '${git_description}' > /tmp/party-pkg/DEBIAN/control + dpkg-deb --build --root-owner-group /tmp/party-pkg ./party.deb + @echo 'Package ready: ./party.deb' + +## deploy/configure: one-time production server setup +.PHONY: deploy/configure +deploy/configure: + cat deploy/setup.sh | ssh ${production_user}@${production_host} bash + +## deploy/teardown: remove everything from the production server +.PHONY: deploy/teardown +deploy/teardown: confirm + cat deploy/teardown.sh | ssh ${production_user}@${production_host} bash + +## deploy/migrate: run database migrations on production +.PHONY: deploy/migrate +deploy/migrate: confirm + ssh ${production_user}@${production_host} \ + 'set -a; . /etc/party/environment; set +a; migrate -path /usr/share/party/migrations -database $$PARTY_DB_DSN up' + +## deploy: pull latest, build .deb on server, and install it +.PHONY: deploy +deploy: confirm + ssh -t ${production_user}@${production_host} \ + 'cd ${production_src} && git pull origin main && make build/package && dpkg -i ./party.deb' ## run/api: run the cmd/api application .PHONY: run/api run/api: @echo "Running the API" - go run ./cmd/api -db-dsn=${PARTY_DB_DSN} + go run ./cmd/party -db-dsn=${PARTY_DB_DSN} .PHONY: db/psql db/psql: diff --git a/deploy/DEBIAN/postinst b/deploy/DEBIAN/postinst new file mode 100644 index 0000000..e50f7d5 --- /dev/null +++ b/deploy/DEBIAN/postinst @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +if ! id -u party >/dev/null 2>&1; then + useradd --system --no-create-home --shell /bin/false party +fi + +chown -R party:party /usr/share/party + +if [ ! -f /etc/party/environment ]; then + mkdir -p /etc/party + cat > /etc/party/environment <<'EOF' +PARTY_DB_DSN=postgres://party:secret@localhost/party?sslmode=disable +APNS_KEY_PATH= +APNS_KEY_ID= +APNS_TEAM_ID= +APNS_BUNDLE_ID= +EOF + chmod 640 /etc/party/environment + chown root:party /etc/party/environment + echo "NOTE: Edit /etc/party/environment before the service can start." +fi + +systemctl daemon-reload +systemctl enable party.service +systemctl restart party.service diff --git a/deploy/DEBIAN/postrm b/deploy/DEBIAN/postrm new file mode 100644 index 0000000..6b839c6 --- /dev/null +++ b/deploy/DEBIAN/postrm @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +case "$1" in + purge) + rm -rf /etc/party + userdel party 2>/dev/null || true + ;; +esac diff --git a/deploy/DEBIAN/prerm b/deploy/DEBIAN/prerm new file mode 100644 index 0000000..f14a9ef --- /dev/null +++ b/deploy/DEBIAN/prerm @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +systemctl stop party.service || true +systemctl disable party.service || true diff --git a/deploy/party.service b/deploy/party.service new file mode 100644 index 0000000..502758b --- /dev/null +++ b/deploy/party.service @@ -0,0 +1,15 @@ +[Unit] +Description=Party API server +After=network.target + +[Service] +Type=simple +User=party +WorkingDirectory=/usr/share/party +EnvironmentFile=/etc/party/environment +ExecStart=/usr/bin/party +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/setup.sh b/deploy/setup.sh new file mode 100644 index 0000000..1fa7870 --- /dev/null +++ b/deploy/setup.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -euo pipefail + +MIGRATE_VERSION=v4.18.1 +REPO_URL=https://github.com/vicenteferrarismith/party # TODO: set your repo URL + +apt-get update -q +apt-get install -y -q git golang-go + +# Install golang-migrate (not in Debian repos) +if ! command -v migrate &>/dev/null; then + echo "Installing migrate ${MIGRATE_VERSION}..." + wget -qO /tmp/migrate.tar.gz \ + "https://github.com/golang-migrate/migrate/releases/download/${MIGRATE_VERSION}/migrate.linux-amd64.tar.gz" + tar -xzf /tmp/migrate.tar.gz -C /usr/local/bin migrate + chmod +x /usr/local/bin/migrate + rm /tmp/migrate.tar.gz +fi + +# Clone repo +if [ ! -d /srv/party ]; then + git clone "$REPO_URL" /srv/party +fi + +echo "" +echo "Setup complete. Next steps:" +echo " 1. make deploy/migrate" +echo " 2. Edit /etc/party/environment with your DB DSN and secrets" +echo " 3. systemctl restart party" diff --git a/deploy/teardown.sh b/deploy/teardown.sh new file mode 100644 index 0000000..f9af51d --- /dev/null +++ b/deploy/teardown.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +# Purge the installed package — removes binary, web assets, /etc/party, and the party user +if dpkg -s party &>/dev/null 2>&1; then + dpkg --purge party +fi + +# Remove cloned repo +rm -rf /srv/party + +# Remove migrate +rm -f /usr/local/bin/migrate + +# Remove Go +apt-get remove -y golang-go +apt-get autoremove -y + +echo "Teardown complete." diff --git a/go.mod b/go.mod index c1d7ed0..1fb2cc2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module party.at/party -go 1.25.0 +go 1.24.0 require ( github.com/felixge/httpsnoop v1.0.4