diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 854b1ab..f34c2fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,7 @@ This repository is the standalone productized Workdock platform. Use this file as the quick-start guide for future coders. It complements: - `DEPLOYMENT.md` +- `TUBCO_SETUP.md` - `backend/workflows/templates/workflows/project_wiki.html` - `backend/workflows/templates/workflows/developer_handbook.html` @@ -34,6 +35,8 @@ Rule: Do not let a customer deployment track `develop` directly. +Use `TUBCO_SETUP.md` for the customer-specific bootstrap, reset, config-sync, and deploy sequence. + ## Dual Remote Workflow This repository now has two different Git remotes with different purposes: - `origin`: the normal GitHub product remote diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index dcf714d..bf6af44 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -254,6 +254,46 @@ This is destructive. It wipes: It does not remove the server-local env file. That file must already exist. +## TUBCO customer setup +For the TUBCO customer line, use the frozen customer branch instead of the normal product branches. + +Branch rule: +- `release/tubco-v1` is the deployment branch +- do not deploy TUBCO from `develop` +- do not deploy TUBCO from `main` + +Recommended first-time flow: +1. check out `release/tubco-v1` +2. create `.env.prod` on the customer server +3. run a destructive reset/bootstrap from the Mac +4. import the intended TUBCO config baseline +5. verify `https://portal.tub.co/healthz/` + +Important TUBCO values in `.env.prod`: +```env +APP_DOMAIN=portal.tub.co +APP_BASE_URL=https://portal.tub.co +DJANGO_DEBUG=0 +DJANGO_SECURE_COOKIES=1 +DJANGO_SECURE_SSL_REDIRECT=1 +``` + +Customer reset from scratch: +```bash +git checkout release/tubco-v1 +RESET_CONFIRM=RESET \ +EXPECTED_BRANCH=release/tubco-v1 \ +DEPLOY_HOST=root@ \ +DEPLOY_PATH=/opt/workdock \ +REMOTE_ENV_FILE=.env.prod \ +HEALTH_URL=https://portal.tub.co/healthz/ \ +RUN_DJANGO_CHECK=1 \ +./scripts/reset_stack_from_mac.sh +``` + +The full customer runbook lives in: +- [TUBCO_SETUP.md](/Users/bostame/Documents/workdock-platform/TUBCO_SETUP.md) + ## Manual production deployment For production, use a dedicated helper instead of the test script. @@ -366,6 +406,9 @@ ssh -4 root@192.168.2.55 ' - PDF letterhead - use dry-run first. Treat config sync as an explicit operator action, not something hidden inside deploy. +For the customer-specific version of this workflow, including `portal.tub.co` examples, use: +- [TUBCO_SETUP.md](/Users/bostame/Documents/workdock-platform/TUBCO_SETUP.md) + ## GitHub Actions workflows ### Test deployment workflow File: diff --git a/TUBCO_SETUP.md b/TUBCO_SETUP.md new file mode 100644 index 0000000..ce7501f --- /dev/null +++ b/TUBCO_SETUP.md @@ -0,0 +1,190 @@ +# TUBCO Customer Setup Runbook + +Use this runbook when you want to set up or rebuild the TUBCO customer deployment from scratch. + +This is the customer-specific path. Normal product work still happens on: +- `develop` +- `main` + +TUBCO delivery happens from: +- `release/tubco-v1` + +## 1. Use the right branch +```bash +git checkout release/tubco-v1 +git pull --ff-only origin release/tubco-v1 +``` + +If you plan to push an approved customer fix to the TUBCO remote: +```bash +./scripts/git_remote_target.sh status +./scripts/git_remote_target.sh push-tubco release/tubco-v1 +``` + +## 2. Prepare the target server once +Target assumptions: +- repo path: `/opt/workdock` +- env file: `.env.prod` +- public URL: `https://portal.tub.co` + +Create the server env file from the example: +```bash +ssh root@ +cd /opt/workdock +cp .env.prod.example .env.prod +``` + +Required values to review in `.env.prod`: +- `APP_DOMAIN=portal.tub.co` +- `APP_BASE_URL=https://portal.tub.co` +- `DJANGO_ALLOWED_HOSTS=portal.tub.co,...` +- `DJANGO_CSRF_TRUSTED_ORIGINS=https://portal.tub.co` +- `DJANGO_DEBUG=0` +- `DJANGO_SECURE_COOKIES=1` +- `DJANGO_SECURE_SSL_REDIRECT=1` +- `DJANGO_SECRET_KEY=` +- `POSTGRES_PASSWORD=` + +## 3. Optional: export the intended local TUBCO config baseline +Run from the local repo: +```bash +docker compose exec -T web python manage.py export_portal_app_config --output /tmp/portal-app-config.json +docker compose exec -T web python manage.py export_portal_deployment_config --output /tmp/portal-deployment-config.json +docker compose cp web:/tmp/portal-app-config.json /tmp/portal-app-config.json +docker compose cp web:/tmp/portal-deployment-config.json /tmp/portal-deployment-config.json +``` + +This gives you the local baseline for: +- app registry visibility/order +- branding text and colors +- company metadata + +## 4. Reset the customer stack from scratch +This is destructive and wipes: +- database state +- generated media/documents +- staticfiles volume +- backup volume + +Run: +```bash +git checkout release/tubco-v1 +RESET_CONFIRM=RESET \ +EXPECTED_BRANCH=release/tubco-v1 \ +DEPLOY_HOST=root@ \ +DEPLOY_PATH=/opt/workdock \ +REMOTE_ENV_FILE=.env.prod \ +HEALTH_URL=https://portal.tub.co/healthz/ \ +RUN_DJANGO_CHECK=1 \ +./scripts/reset_stack_from_mac.sh +``` + +Use this when you want a fresh customer environment with only default bootstrap data. + +## 5. Import the TUBCO config baseline +Copy the exported JSON to the target host: +```bash +scp -4 /tmp/portal-app-config.json /tmp/portal-deployment-config.json root@:/opt/workdock/ +``` + +Copy the files into the running web container: +```bash +ssh -4 root@ ' +docker cp /opt/workdock/portal-app-config.json workdock-web-1:/tmp/portal-app-config.json && +docker cp /opt/workdock/portal-deployment-config.json workdock-web-1:/tmp/portal-deployment-config.json +' +``` + +Dry-run the import first: +```bash +ssh -4 root@ ' +docker exec workdock-web-1 python manage.py import_portal_app_config /tmp/portal-app-config.json --dry-run && +docker exec workdock-web-1 python manage.py import_portal_deployment_config /tmp/portal-deployment-config.json --dry-run +' +``` + +If the dry run looks correct, apply it: +```bash +ssh -4 root@ ' +docker exec workdock-web-1 python manage.py import_portal_app_config /tmp/portal-app-config.json && +docker exec workdock-web-1 python manage.py import_portal_deployment_config /tmp/portal-deployment-config.json +' +``` + +Note: +- uploaded branding assets are not included in this JSON sync +- logo, favicon, and PDF letterhead still need explicit upload on the customer system + +## 6. Normal customer deployment after the first setup +After the first reset/bootstrap, regular TUBCO updates should usually be deploys, not resets. + +If you do not want a destructive reset, use the normal deploy path: +```bash +git checkout release/tubco-v1 +rsync -az --delete \ + --filter 'P .env.test' \ + --filter 'P .env.prod' \ + --exclude '.git' \ + --exclude '.github' \ + --exclude '.venv' \ + --exclude '__pycache__' \ + --exclude 'node_modules' \ + --exclude 'backend/media' \ + --exclude 'backend/staticfiles' \ + -e 'ssh -4' \ + /Users/bostame/Documents/workdock-platform/ \ + root@:/opt/workdock/ + +ssh -4 root@ ' +cd /opt/workdock && +RUN_DJANGO_CHECK=1 DEPLOY_HEALTH_URL="https://portal.tub.co/healthz/" ./scripts/deploy_stack.sh .env.prod docker-compose.prod.yml +' +``` + +## 7. Verify the deployment +Health: +```bash +curl -I https://portal.tub.co/healthz/ +``` + +Container state: +```bash +ssh -4 root@ ' +cd /opt/workdock && +docker compose --env-file .env.prod -f docker-compose.prod.yml ps +' +``` + +Django checks inside the running app: +```bash +ssh -4 root@ ' +docker exec workdock-web-1 python manage.py check +' +``` + +## 8. Customer policy +For TUBCO: +- deploy from `release/tubco-v1` +- do not give them future product features by default +- only backport approved: + - bug fixes + - security updates + - UI improvements + +Do not deploy TUBCO from: +- `develop` +- `main` + +## 9. Access and roles +Current intended customer rule: +- highest customer-facing application role: `Super Admin` +- `Platform Owner` remains product-level + +TUBCO-specific behavior already in the customer branch: +- `Super Admin` can access: + - Branding + - Company Config +- `Super Admin` cannot access: + - App Registry + - Trial Management + - Django Admin link diff --git a/backend/workflows/templates/workflows/developer_handbook.html b/backend/workflows/templates/workflows/developer_handbook.html index 336bb75..6ab00b6 100644 --- a/backend/workflows/templates/workflows/developer_handbook.html +++ b/backend/workflows/templates/workflows/developer_handbook.html @@ -38,6 +38,7 @@ Hosts & Domains CI/CD Deployment + TUBCO Setup Commands Troubleshooting Security @@ -661,6 +662,84 @@ lxc.mount.entry: /dev/null sys/module/apparmor/parameters/enabled none bind 0 0<
  • Take a snapshot commit before major next-phase work
  • +

    18b) TUBCO Customer Setup

    +
    +

    What this branch is for

    +
      +
    • release/tubco-v1 is the frozen TUBCO customer branch.
    • +
    • It should receive only approved bug fixes, security updates, and UI improvements.
    • +
    • Do not deploy TUBCO from develop or main.
    • +
    +
    +
    +

    First-time customer setup

    +
      +
    1. Check out release/tubco-v1.
    2. +
    3. Create .env.prod on the target server.
    4. +
    5. Run the destructive reset/bootstrap helper from the Mac.
    6. +
    7. Import the intended TUBCO config baseline.
    8. +
    9. Verify https://portal.tub.co/healthz/.
    10. +
    +
    git checkout release/tubco-v1
    +RESET_CONFIRM=RESET \
    +EXPECTED_BRANCH=release/tubco-v1 \
    +DEPLOY_HOST=root@<customer-host> \
    +DEPLOY_PATH=/opt/workdock \
    +REMOTE_ENV_FILE=.env.prod \
    +HEALTH_URL=https://portal.tub.co/healthz/ \
    +RUN_DJANGO_CHECK=1 \
    +./scripts/reset_stack_from_mac.sh
    +
    +
    +

    Required production env values

    +
    APP_DOMAIN=portal.tub.co
    +APP_BASE_URL=https://portal.tub.co
    +DJANGO_DEBUG=0
    +DJANGO_SECURE_COOKIES=1
    +DJANGO_SECURE_SSL_REDIRECT=1
    +

    The customer server also needs strong values for DJANGO_SECRET_KEY and POSTGRES_PASSWORD.

    +
    +
    +

    Config baseline import

    +

    Export the intended local baseline:

    +
    docker compose exec -T web python manage.py export_portal_app_config --output /tmp/portal-app-config.json
    +docker compose exec -T web python manage.py export_portal_deployment_config --output /tmp/portal-deployment-config.json
    +docker compose cp web:/tmp/portal-app-config.json /tmp/portal-app-config.json
    +docker compose cp web:/tmp/portal-deployment-config.json /tmp/portal-deployment-config.json
    +

    Copy the payloads to the customer server and then into the running web container:

    +
    scp -4 /tmp/portal-app-config.json /tmp/portal-deployment-config.json root@<customer-host>:/opt/workdock/
    +ssh -4 root@<customer-host> '
    +docker cp /opt/workdock/portal-app-config.json workdock-web-1:/tmp/portal-app-config.json &&
    +docker cp /opt/workdock/portal-deployment-config.json workdock-web-1:/tmp/portal-deployment-config.json
    +'
    +

    Dry-run first, then apply:

    +
    ssh -4 root@<customer-host> '
    +docker exec workdock-web-1 python manage.py import_portal_app_config /tmp/portal-app-config.json --dry-run &&
    +docker exec workdock-web-1 python manage.py import_portal_deployment_config /tmp/portal-deployment-config.json --dry-run
    +'
    +
    +ssh -4 root@<customer-host> '
    +docker exec workdock-web-1 python manage.py import_portal_app_config /tmp/portal-app-config.json &&
    +docker exec workdock-web-1 python manage.py import_portal_deployment_config /tmp/portal-deployment-config.json
    +'
    +

    Uploaded assets such as logo, favicon, and PDF letterhead are still separate media and need explicit upload.

    +
    +
    +

    Normal TUBCO updates

    +

    When you intentionally want to update the customer branch remote:

    +
    ./scripts/git_remote_target.sh status
    +./scripts/git_remote_target.sh push-tubco release/tubco-v1
    +

    Use a TUBCO personal access token stored in the macOS keychain, not a reusable account password.

    +
    +
    +

    Customer role boundary

    +
      +
    • TUBCO should work primarily with Super Admin and below.
    • +
    • In the customer branch, Super Admin can access Branding and Company Config.
    • +
    • App Registry, Trial Management, and the Django admin link remain platform-level.
    • +
    +
    +

    19) Command Reference

    Local development

    @@ -700,6 +779,21 @@ RUN_DJANGO_CHECK=1 \ ./scripts/reset_stack_from_mac.sh

    Use the second form for a customer setup from scratch. This is destructive and removes database/media/static/backups before bootstrapping again.

    +
    +

    TUBCO setup

    +
    git checkout release/tubco-v1
    +RESET_CONFIRM=RESET \
    +EXPECTED_BRANCH=release/tubco-v1 \
    +DEPLOY_HOST=root@<customer-host> \
    +DEPLOY_PATH=/opt/workdock \
    +REMOTE_ENV_FILE=.env.prod \
    +HEALTH_URL=https://portal.tub.co/healthz/ \
    +RUN_DJANGO_CHECK=1 \
    +./scripts/reset_stack_from_mac.sh
    +

    Rebuild a fresh TUBCO environment from the customer branch.

    +
    ./scripts/git_remote_target.sh push-tubco release/tubco-v1
    +

    Push an explicitly approved customer update to the TUBCO remote.

    +

    Production deployment

    ./scripts/deploy_prod_from_mac.sh