This repository contains the infrastructure configuration for deploying Toite applications. It includes Docker Compose setup, deployment scripts, and documentation for running the complete application stack on a VPS.
The infrastructure follows a CI/CD pipeline where:
- CI/CD Pipelines - GitHub Actions in the
backendandinternal-frontendrepositories build and push Docker images to Docker Hub when changes are merged to main - Docker Hub - Acts as the central registry storing all application images
- Domain - DNS A record points to the VPS (e.g.,
demo.toite.ee) - VPS - A single server runs all services via Docker Compose:
- Traefik - Reverse proxy handling routing and TLS certificates
- PostgreSQL, Redis, MongoDB - Data stores
- MinIO - S3-compatible object storage
- Backend Application - API server
- Internal Frontend - Admin/internal web application
Services start in a specific order based on their dependencies:
- postgres-init - Generates SSL certificates for PostgreSQL, then exits
- PostgreSQL, MongoDB, Redis - Data stores start in parallel (PostgreSQL waits for certs)
- migrations - Applies database migrations to PostgreSQL, then exits
- Backend - Starts after all data stores are healthy and migrations complete
- Internal Frontend - Starts after backend is running
Follow the VPS Setup Guide to provision and secure your server. This guide covers:
- Creating a hardened Ubuntu server with security best practices
- Setting up SSH key-based authentication
- Installing rootless Docker
- Configuring firewall and automatic security updates
Before deploying via CI/CD, you need to configure GitHub environments with the required secrets and variables.
- Go to your repository Settings > Environments
- Create an environment (e.g.,
production,dev, ordemo) - Add the following configuration:
Secrets (per environment):
| Secret | Description |
|---|---|
VPS_HOST |
VPS IP address or hostname |
VPS_PORT |
SSH port number (e.g., 22 or custom) |
VPS_SSH_PRIVATE_KEY |
SSH private key for the deploy user |
LETSENCRYPT_EMAIL |
Email for Let's Encrypt certificate notifications |
Variables (per environment):
| Variable | Description |
|---|---|
DOMAIN |
Domain name for the deployment (e.g., demo.toite.ee) |
The deployment is triggered manually via the Deploy Infrastructure workflow:
- Go to Actions > Deploy Infrastructure
- Click Run workflow
- Select the target environment from the dropdown
- Click Run workflow to start deployment
What the deployment does:
- Validates all required secrets and variables are configured
- Connects to the VPS via SSH as the
deployuser - Checks that
~/appdoesn't already exist (fails if it does) - Verifies Docker is installed and running
- Uploads files via rsync (excludes
.git,.github,docs,.env) - Generates
.envfile with random passwords and secrets - Sets
DOMAINandLETSENCRYPT_EMAILfrom GitHub configuration - Pulls all Docker images
- Starts all services with
docker compose up -d
After successful deployment, you can view the status in the Deployments section of the repository.
Note: This workflow is for initial deployment only. If
~/appalready exists on the VPS, you must remove it manually before redeploying.
After initial deployment, use the Pull & Restart Infrastructure workflow to update application containers with new images:
- Go to Actions > Pull & Restart Infrastructure
- Click Run workflow
- Select the target environment from the dropdown
- Click Run workflow to start the update
What the update does:
- Connects to the VPS via SSH
- Pulls latest images for:
backend,migrations,internal-frontend - Recreates those containers with
--force-recreate - Cleans up unused Docker images
Note: This workflow only updates application services. Infrastructure services (Traefik, PostgreSQL, MongoDB, Redis, MinIO) are not affected. The
.envfile and data volumes are preserved.
Use the Seed Database workflow to reset databases and populate them with seed data. This is useful for testing or resetting non-production environments.
Warning: This is a destructive operation that deletes all data in PostgreSQL, MongoDB, and Redis!
- Go to Actions > Seed Database
- Click Run workflow
- Select the target environment (
devordemo) - Type
SEEDin the confirmation field - Click Run workflow to start seeding
What the seeding does:
- Pulls the latest
toite/seeder:latestimage - Stops all services and removes database volumes (PostgreSQL, MongoDB, Redis)
- Starts PostgreSQL and waits for it to be healthy
- Runs the seeder container to populate the database
- Starts all services
Note: This workflow is not available for production. Let's Encrypt certificates and MinIO data are preserved.
If you prefer to deploy manually without GitHub Actions:
# 1. Copy files to VPS (from local machine)
rsync -avz --exclude='.git' --exclude='.github' --exclude='docs' --exclude='.env' \
./ deploy@YOUR_VPS_HOST:~/app/
# 2. SSH into VPS
ssh deploy@YOUR_VPS_HOST
# 3. Generate environment file
cd ~/app
chmod +x setup-env.sh
./setup-env.sh
# 4. Edit .env with your domain and email
nano .env
# Set DOMAIN=your-domain.com
# Set LETSENCRYPT_EMAIL=your-email@example.com
# 5. Pull Docker images
docker compose pull
# 6. Start all services
docker compose up -d
# 7. Verify services are running
docker compose ps
