A self-hosted Docker platform for running websites, APIs, bots, analytics, and email behind one production gateway.
Aether is the infrastructure layer for my personal and studio projects. It keeps local development and production deployment in one Compose-based system, builds service images with GitHub Actions, and rolls updates onto an ARM64 VPS without taking the entire stack down.
- Multiple websites and static applications
- A shared API and automation services
- Nginx routing and TLS termination
- Privacy-friendly analytics with Plausible
- Mail hosting through Mailcow
- Automated container builds and rolling deployments
- Certificate renewal, backups, and operational scripts
flowchart LR
visitor[Visitors and clients] --> gateway[Nginx gateway<br/>routing + TLS]
gateway --> sites[Websites<br/>Sumeet · Arcane Codex · Reliq]
gateway --> api[Vulkan API]
gateway --> analytics[Plausible Analytics]
gateway --> mail[Mailcow]
bots[Telegram bots] --> api
github[GitHub Actions] --> registry[GitHub Container Registry]
registry --> host[ARM64 VPS]
host --> gateway
host --> bots
The base Compose file defines the shared service topology. Environment-specific overlays add local bind mounts, production images, analytics, and mail services as needed.
| Service | Role | Public project |
|---|---|---|
gateway |
Nginx reverse proxy, routing, security headers, and TLS termination | — |
sumeetsaini_com |
Interactive personal website | kungfusaini/sumeetsaini_com |
vulkan |
Shared API for projects, contact forms, and personal tools | kungfusaini/vulkan |
arcanecodex |
Hugo-powered writing and reference site | kungfusaini/arcane-codex |
reliqstudios |
Reliq Studios website | kungfusaini/reliqstudios |
reliqdigital |
Reliq digital-services website | kungfusaini/reliq.digital |
reliqlabs |
Reliq Labs website | kungfusaini/reliqlabs |
bucketbot |
Telegram automation and capture bot | kungfusaini/bucketbot |
goblinbot |
Telegram interface for personal-finance data | kungfusaini/goblinbot |
plausible |
Self-hosted, privacy-friendly analytics | plausible/analytics |
mailcow |
Self-hosted email stack | mailcow/mailcow-dockerized |
Aether also hosts a small collection of private and standalone web applications that use the same gateway and deployment model.
| File | Purpose |
|---|---|
docker-compose.yml |
Shared service definitions and network topology |
docker-compose-dev.yml |
Local builds, bind mounts, ports, and development configuration |
docker-compose-prod.yml |
GHCR images, production volumes, and external networks |
docker-compose-plausible.yml |
Plausible and its data services |
docker-compose-mailcow.yml |
Mailcow integration |
Keeping these concerns in overlays makes the development stack lightweight while allowing production to opt into stateful infrastructure.
- Docker with Compose v2
- Git with submodule support
Clone the repository and its service submodules:
git clone --recurse-submodules https://github.com/kungfusaini/aether.git
cd aetherStart the normal development stack:
docker compose \
-f docker-compose.yml \
-f docker-compose-dev.yml \
up -dAdd local analytics when needed:
docker compose \
-f docker-compose.yml \
-f docker-compose-dev.yml \
-f docker-compose-plausible.yml \
up -dUseful commands:
# Follow all service logs
docker compose logs -f
# Inspect running services
docker compose ps
# Stop the stack
docker compose down| Surface | URL |
|---|---|
| Gateway | http://localhost |
| Personal website | http://localhost:8080 |
| Vulkan API | http://localhost:3000 |
| Arcane Codex | http://localhost:1313 |
| Plausible | http://stats.localhost when its overlay is enabled |
Some gateway hostnames require matching entries in /etc/hosts; see the development Nginx configuration under services/gateway/conf.d/dev/.
The main GitHub Actions workflow:
- Checks out the repository and service submodules.
- Builds ARM64 images for the maintained services.
- Pushes the resulting container images to GitHub Container Registry.
- Copies Compose and operational files to the host.
- Pulls changed images and updates services individually.
- Removes unused images after a successful rollout.
Individual projects can also trigger focused deployments. For example, the babbi.world workflow updates only its own service rather than redeploying the full platform.
Production configuration is assembled from Compose overlays:
docker compose \
-f docker-compose.yml \
-f docker-compose-prod.yml \
-f docker-compose-mailcow.yml \
-f docker-compose-plausible.yml \
up -dThis command documents the topology; a real deployment also requires host directories, external Docker networks, certificates, and secrets configured by the deployment environment.
- TLS certificate setup and renewal
- Mailcow domain onboarding
scripts/setup-backup.sh— configure backupsscripts/test-backup.sh— exercise the backup pathscripts/verify-backup.sh— verify backup outputscripts/cf-add-site.sh— assist with Cloudflare site setup
.
├── .github/workflows/ # Build and deployment automation
├── docs/ # Operational documentation
├── scripts/ # TLS, backup, DNS, and mail helpers
├── services/ # Gateway plus application submodules
├── docker-compose.yml # Shared topology
├── docker-compose-dev.yml # Development overlay
├── docker-compose-prod.yml # Production overlay
├── docker-compose-mailcow.yml
└── docker-compose-plausible.yml
- Deployment credentials and application secrets are supplied through GitHub Actions secrets and host-managed environment values.
- The gateway centralizes TLS, proxy headers, and common security policy.
- Production-only credentials are not required for the normal development stack.
- Repository examples use placeholders; secrets should never be committed to Compose files.
Aether is a working personal infrastructure repository rather than a turnkey hosting product. Its architecture and operational patterns are reusable, but production deployment assumes control of the target VPS, DNS, certificates, external networks, and service-specific secrets.