All articles

Tasuki Keifu: GitHub Deployment and Data Synchronization Plan

Personal projectsRead in Chinese

GitHub Deployment and Data Synchronization Plan

This plan was written on 2026-09-11. It records the deployment state at that time and proposes subsequent work; its checklist is not a claim that every item was completed. Related documents are the V0.1 technical plan and V0.1 PRD.

1. Starting Point

tasuki-keifu had an initial deployment on Ubuntu-3:

  • Domain: https://tasuki-keifu.gelatoni.uk
  • Application directory: /opt/apps/tasuki-keifu
  • Application port: 127.0.0.1:3020
  • Reverse proxy: Nginx
  • Runtime: Docker Compose
  • Database: a PostgreSQL container dedicated to the project

The initial procedure copied local code to the server, built an image there, ran migrations, and restarted the containers. That was adequate for early validation, but the proposed regular release path was a GitHub Actions workflow similar to personal-site.

2. Reference Deployment Pattern

At the time, personal-site used a private GitHub repository as the code source. A push to main triggered Actions to install dependencies, check types, build the application and Docker image, save the image as a tar.gz artifact, upload the archive and Compose file over SSH/SCP, load the image on Ubuntu-3, and restart the service with Docker Compose.

This pattern kept a GitHub token and a Git checkout off the server, made CI failures easier to locate, and gave both sites a consistent release entry point. tasuki-keifu also needed database migrations. Business-data ingestion was deliberately outside the deployment workflow.

3. Proposed Repository and Release Rules

The proposal was to create gelatoni-xh/tasuki-keifu as a private repository initially, and revisit public access once data provenance, copyright boundaries, page quality, and operations were more mature. The first version needed only main: pushes would deploy production, and workflow_dispatch would allow a manual run. A develop branch, preview environment, and release tags were possible later, once data entry and administration made them useful.

The workflow could reuse the server connection secret names UBUNTU3_HOST, UBUNTU3_USER, and UBUNTU3_SSH_KEY. It should not store the production database password, DATABASE_URL, or .env.production in GitHub Actions. Production environment variables belonged on the server at /opt/apps/tasuki-keifu/.env.production. Actions would transport release artifacts and deployment files, not import, synchronize, or repair business data.

The repository would contain a Dockerfile, docker-compose.prod.yml, deployment notes and an Nginx configuration under deploy/, and .github/workflows/deploy.yml. The Compose file should support an image uploaded by Actions while retaining a local build option for emergencies. The Nginx configuration should be documented without being overwritten on each deployment.

4. Proposed GitHub Actions Flow

push main
  build
    checkout
    set up pnpm and Node.js
    pnpm install --frozen-lockfile
    pnpm prisma:generate
    pnpm lint
    pnpm build
    docker build -t tasuki-keifu-app:latest .
    docker save tasuki-keifu-app:latest | gzip

  deploy
    upload image archive and Compose file
    docker load
    docker compose run --rm app pnpm prisma migrate deploy
    docker compose up -d app
    docker image prune -f
    health check

The deployment must run prisma migrate deploy, but must not run pnpm db:seed. Seeding is for local development or an explicit initialization step. Once production contains business data, seeding cannot be a routine release action. Imports, synchronization, and data corrections need a separate workflow.

5. Production Database Boundary

The production PostgreSQL database was the source of truth. At the time it ran in a container with database tasuki_keifu, user tasuki_keifu_user, and volume tasuki-keifu_tasuki-keifu-postgres-data.

The operating rules were:

  • Allow migrations in deployment; do not automatically seed or import data.
  • Back up before significant imports.
  • Prefer restoring a backup for a data rollback, rather than assuming a reverse migration can reconstruct data.

Application deployment changes code and schema. It must not overwrite the curated production dataset.

6. Data Completion and Synchronization

6.1 Near Term: Production as the Write Target

For V0.1 to V0.2, the dataset was small, one person was the main maintainer, and the data-entry model was still being explored. The goal was to put facts gathered through offline breadth-first research into production without coupling that work to application releases.

The proposed sequence was:

  1. Explore sources, structure the facts, and judge source credibility outside the release pipeline.
  2. Trigger a manual or scripted production backup before writing.
  3. Write through a controlled script, administrative interface, or explicit SQL.
  4. Record source and audit information for the write.
  5. Keep deployment limited to prisma migrate deploy, without seeding or import scripts.

During this early stage, a controlled offline session could connect to production to complete data; production backups could be restored locally for page development and model checks; and local model changes could reach production through migrations. The plan discouraged replacing the production database with a local copy, automatic production seeding, committing database dumps to Git, storing production dumps in Actions, or putting scraping and cleaning into deployment.

6.2 Dataset Checkpoints

When a batch of records had been checked sufficiently, the maintainer could create a checkpoint: back up production, record the covered data and sources plus known gaps, optionally restore the backup locally as a development baseline, and continue making incremental changes against production. This checkpoint was a data-workflow snapshot, not a release or a required code tag.

6.3 Medium Term: Production as Source, Local as Development Copy

As the real dataset grew, production would remain the source of truth and the local database would become a development copy. Production changes should pass through an administrative interface, import script, or controlled SQL. Local development could use a sanitized or complete production backup, but local edits should not be synchronized directly back to production. Corrections should be auditable through administration, imports, or migrations.

That stage called for an admin interface, import jobs, audit logs, pre-import backups, and import-result reports. These were proposed additions, not claimed as existing features.

6.4 Long-Term Direction

Public pages / admin interface
  PostgreSQL primary business database

Import scripts / collection jobs
  staging tables
    human review
      business tables

Analysis / relationship graphs / statistics
  warehouse or materialized views

The long-term direction retained raw source data, put cleaned records into business tables, and could serve relationship and statistical views from materialized views or an analytical store. Public pages would still use a trusted production business database. V0.1 did not implement this layer.

7. Backup and Recovery

The deployment already had /opt/apps/tasuki-keifu/backup-db.sh, a backups directory, and /etc/cron.d/tasuki-keifu-backup. The short-term plan called for a daily pg_dump, manual backups before significant entry or migrations, and restoring a backup locally when real data was needed for development.

Proposed improvements were an explicit retention period, such as 14 days; object-storage uploads; periodic restore drills; and encryption of backup files. Their presence in the plan does not imply they had been implemented.

For application rollback, retain the preceding image archive or tag, reload that image, and run docker compose up -d app if the new version breaks pages. Prisma migrations would not receive automatic reverse migrations. For risky schema changes, first validate the migration locally, back up production, run the migration, and check core pages. Data recovery would use a backup restore.

8. Manual Fallback and Checklist

The original manual route could remain available for Actions failures, server troubleshooting, and very early validation:

local code -> sync to server -> docker compose build -> migrate deploy -> compose up

Once Actions worked, the intended normal route was git push main -> GitHub Actions -> Ubuntu-3.

The plan's priorities were:

  • P0: Create the private repository, initialize and push main, add deploy.yml, support uploaded images in the production Compose file, verify reusable connection secrets, and complete one Actions deployment.
  • P1: Add a post-deploy health check, document local restoration from a production backup, provide a manual production-backup command, and make the local-only seed rule explicit.
  • P2: Design staging imports and import reports, add object-storage backup, and record a restore drill.
Tasuki Keifu: GitHub Deployment and Data Synchronization Plan | Xuhuan / Gelatoni