Production-ready, self-hosted cloud infrastructure on Oracle Cloud Infrastructure's Always Free tier. Zero cost, fully automated, security hardened.
A complete self-hosted cloud platform running on Oracle Cloud's Always Free tier, featuring Nextcloud as the core with integrated media services, full monitoring stack, and automated backups. Built with Infrastructure as Code principles and production-grade security.
Key highlights:
- Zero cost - Runs entirely on OCI Always Free tier
- Infrastructure as Code - One-command deployment with Terraform
- Multi-service platform - Nextcloud + Komga + Jellyfin + Monitoring
- Security hardened - Multi-layer firewall, Fail2ban, HTTPS, Tailscale VPN
- Automated backups - Borg daily backups with off-site sync
- CI/CD pipeline - GitHub Actions with security scanning
INTERNET
|
+---------------------------+
| OCI Security Lists (FW) |
| Ports: 22, 80, 443 |
+---------------------------+
|
+---------------------------+
| Ubuntu 24.04 LTS (ARM64) |
| UFW + Fail2ban (SSH + |
| Nextcloud login) |
| 4 vCPU, 24GB RAM |
+---------------------------+
| |
PUBLIC | | PRIVATE (Tailscale VPN)
| |
+---------------+ +--------------------+
| |
v v
+--------------------+ +----------------------------+
| Caddy Reverse | | Tailscale Serve (HTTPS) |
| Proxy (SSL/TLS) | | |
| Let's Encrypt | | - AIO Admin :8443 |
+--------------------+ | - Komga :25600 |
| | - Jellyfin :8096 |
v | - Grafana :3000 |
+--------------------+ +----------------------------+
| Nextcloud AIO | |
| - PostgreSQL | +----------------------------+
| - Redis | | Monitoring Stack |
| - Collabora | | - Prometheus (30d) |
| - BorgBackup | | - Grafana (dashboards) |
+--------------------+ | - Node Exporter |
| - cAdvisor |
+----------------------------+
+------------------------------------------------------------+
| Persistent Block Volume (100GB, prevent_destroy) |
| /mnt/nextcloud-data/ |
| +-- nextcloud-data/ (user files, database, config) |
| +-- borg-backups/ (encrypted daily backups) |
+------------------------------------------------------------+
Design pattern: "Pets vs Cattle"
- Cattle (Compute): Instance is ephemeral and fully recreatable via
terraform destroy+terraform apply - Pet (Storage): Persistent block volume is protected (
prevent_destroy = true) and holds all critical data - Disaster Recovery: Infrastructure can be rebuilt from scratch while data survives on the protected volume
| Component | Technology | Purpose |
|---|---|---|
| Cloud | Oracle Cloud (OCI) | Always Free tier hosting |
| Compute | A1.Flex (ARM64) | 4 vCPU, 24GB RAM |
| Storage | OCI Block Volume | 100GB persistent data (prevent_destroy) |
| IaC | Terraform | One-command infrastructure deployment |
| Containers | Docker Compose | Service orchestration |
| Application | Nextcloud AIO | Self-hosted cloud suite |
| Reverse Proxy | Caddy | Automatic HTTPS with Let's Encrypt |
| VPN | Tailscale | Private access to internal services |
| Manga/Comics | Komga | Reader integrated with Nextcloud files |
| Media Server | Jellyfin | Video, Music and Photos from Nextcloud files |
| Database | PostgreSQL | Nextcloud database (via AIO) |
| Cache | Redis | Performance optimization (via AIO) |
| Backup | BorgBackup | Encrypted, deduplicated daily backups |
| Monitoring | Prometheus + Grafana | Metrics collection and dashboards |
| Exporters | Node Exporter, cAdvisor | System and container metrics |
| CI/CD | GitHub Actions | Automated validation and security scans |
| Firewall | UFW + Fail2ban | System security and SSH protection |
| SSL/TLS | Let's Encrypt | Free automated certificates |
- Terraform IaC - Complete infrastructure defined as code (network, compute, storage)
- Cloud-init automation - System bootstrap, Docker install, service deployment
- Persistent storage - Protected block volume survives instance destroy/recreate
- Disaster recovery tested - 3 complete destroy/apply cycles validated
- Nextcloud Hub - Files, Calendar, Contacts, Tasks, Collabora Office, Photos
- Komga - Manga/comics reader serving files directly from Nextcloud library
- Jellyfin - Media server for video, music and photos from Nextcloud library (Finamp as music client)
- Monitoring - Prometheus + Grafana with pre-configured dashboards and exporters
- Multi-layer firewall - OCI Security Lists + UFW (deny by default)
- SSH hardening - Key-based auth only, Fail2ban brute-force protection
- Nextcloud brute-force protection - Fail2ban monitoring login attempts (5 attempts → 1h ban)
- HTTPS everywhere - Caddy with automatic Let's Encrypt certificates
- Security headers - HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy
- AIO admin locked down - Ports 8080/8443 closed to internet, accessible only via Tailscale
- Private services - Komga, Jellyfin, Grafana bound to localhost, accessible only via Tailscale VPN
- 2FA (TOTP) - Two-factor authentication on Nextcloud
- Unattended upgrades - Automatic security updates
- BorgBackup - Encrypted daily backups at 04:00 UTC
- Automated pruning - 7 daily, 4 weekly, 6 monthly retention
- Off-site sync - rsync to local PC with integrity verification
- Data export - Human-readable exports (calendars .ics, contacts .vcf)
- Local automation -
local-backup-sync.shfor cron-based backup sync
- 3 GitHub Actions workflows - CI validation, weekly security scans, Docker image scans
- 5-stage CI pipeline - Validation, security, Docker checks, PR automation, summary
- Security scanning - tfsec, Trivy, Gitleaks, ShellCheck
- Pre-commit hooks - Local validation before every commit
- Conventional commits - Standardized commit message format
nextcloud-oci-terraform/
|
+-- terraform/ # Infrastructure as Code
| +-- provider.tf # OCI provider configuration
| +-- variables.tf # Configurable variables
| +-- network.tf # VCN, subnet, security lists
| +-- compute.tf # A1.Flex instance + cloud-init
| +-- storage.tf # Persistent block volume (protected)
| +-- outputs.tf # Deployment outputs
| +-- cloud-init.yaml # Full system bootstrap (319 lines)
| +-- terraform.tfvars.example # Configuration template
| +-- README.md # Terraform deployment guide
|
+-- docker/ # Container orchestration
| +-- docker-compose.yml # All services definition
| +-- Caddyfile # Reverse proxy configuration
| +-- monitoring/
| +-- prometheus.yml # Prometheus scrape config
| +-- grafana/provisioning/ # Auto-provisioned dashboards & datasources
|
+-- scripts/ # Automation (11 scripts)
| +-- local-backup-sync.sh # Borg backup sync + integrity check
| +-- create-backup.sh # On-demand backup trigger
| +-- export-data.sh # Calendar/contacts export
| +-- generate-config.sh # Caddyfile generator from .env
| +-- deploy-nextcloud.sh # Initial deployment
| +-- borg-prune.sh # Server-side backup pruning
| +-- setup-cron.sh # Backup cron automation
| +-- ssh-connect.sh # Quick SSH connection
| +-- README.md # Scripts reference
|
+-- docs/ # Comprehensive guides (11 documents)
| +-- 01-INITIAL-SETUP.md # SSH and first connection
| +-- 02-SYSTEM-SETUP.md # System configuration
| +-- 03-DOCKER-SETUP.md # Docker installation
| +-- 04-FIREWALL-SECURITY.md # UFW and Fail2ban
| +-- 05-CADDY-REVERSE-PROXY.md # Caddy and SSL setup
| +-- 05-NEXTCLOUD-DEPLOYMENT.md # Nextcloud AIO deployment
| +-- 06-BACKUP-RESTORE.md # Backup strategy and recovery
| +-- 07-CRON-AUTOMATION.md # Scheduled tasks setup
| +-- 08-TERRAFORM-STRATEGY.md # IaC patterns and workflows
| +-- 09-CICD-MONITORING.md # CI/CD pipeline architecture
| +-- 10-LOCAL-BACKUP-MANAGEMENT.md # Local backup automation
|
+-- .github/workflows/ # CI/CD pipelines
| +-- ci.yml # Main CI (PR + push validation)
| +-- security-deep.yml # Weekly security scans
| +-- docker-image-scan.yml # Weekly Docker vulnerability scans
|
+-- .env.example # Environment variables template
+-- .pre-commit-config.yaml # Pre-commit hooks
+-- ROADMAP.md # Project roadmap and progress
+-- README.md # This file
One-command infrastructure deployment. Everything is automated.
Prerequisites: Oracle Cloud account (free tier), Terraform, a domain with DNS A record
# 1. Clone and configure
git clone https://github.com/Pandagan-85/nextcloud-oci-terraform.git
cd nextcloud-oci-terraform/terraform
cp terraform.tfvars.example terraform.tfvars
nano terraform.tfvars # Add OCI credentials and domain
# 2. Deploy
terraform init
terraform plan
terraform apply # Full deployment in ~10 minutes
# 3. Access
terraform output # Shows IPs, URLs, SSH commandWhat gets deployed automatically:
- OCI compute instance (4 vCPU ARM, 24GB RAM)
- Persistent data volume (100GB, protected)
- Network infrastructure (VCN, subnet, security lists, internet gateway)
- System hardening (UFW, Fail2ban, unattended-upgrades)
- Docker + all services (Nextcloud, Caddy, monitoring stack)
- SSL certificates (Let's Encrypt)
See terraform/README.md for the detailed guide.
Step-by-step deployment for learning or custom setups.
# 1. Clone and configure
git clone https://github.com/Pandagan-85/nextcloud-oci-terraform.git
cd nextcloud-oci-terraform
cp .env.example .env
nano .env # Configure your values
# 2. Generate config and deploy
./scripts/generate-config.sh
./scripts/deploy-nextcloud.shFollow the guides in docs/ for each step.
Komga, Jellyfin, and Grafana are not exposed publicly. They are accessible only through Tailscale VPN with HTTPS:
# On the server, after docker compose up:
sudo tailscale serve --bg --https 8443 https+insecure://localhost:8080 # AIO Admin
sudo tailscale serve --bg --https 25600 http://localhost:25600 # Komga
sudo tailscale serve --bg --https 8096 http://localhost:8096 # Jellyfin
sudo tailscale serve --bg --https 3000 http://localhost:3000 # GrafanaAccess from any device on your Tailscale network:
- AIO Admin:
https://your-tailscale-hostname:8443 - Komga:
https://your-tailscale-hostname:25600 - Jellyfin:
https://your-tailscale-hostname:8096 - Grafana:
https://your-tailscale-hostname:3000
The monitoring stack collects system and container metrics:
- Prometheus - Metrics storage with 30-day retention, 15s scrape interval
- Grafana - Pre-provisioned dashboards (Docker metrics, Node Exporter, Caddy)
- Node Exporter - System metrics (CPU, RAM, disk, network)
- cAdvisor - Per-container resource usage
All monitoring services bind to localhost only and are accessed via Tailscale Serve.
Dual backup system for maximum data protection:
BorgBackup (automated):
- Daily encrypted backups at 04:00 UTC via Nextcloud AIO
- Stored on persistent volume (
/mnt/nextcloud-data/borg-backups/) - Automated pruning: 7 daily, 4 weekly, 6 monthly
- Off-site sync to local PC via
local-backup-sync.sh
Data export (human-readable):
- Weekly export of calendars (.ics) and contacts (.vcf)
- Portable format, importable to Google/Apple/Outlook
# Sync backups to local PC (one-time setup)
ln -s ~/Projects/nextcloud-oci-terraform/scripts/local-backup-sync.sh ~/bin/nextcloud-backup
# Run sync
nextcloud-backup --sync-only # Automated (cron-friendly)
nextcloud-backup # Interactive (sync + extract)See docs/10-LOCAL-BACKUP-MANAGEMENT.md for the complete guide.
Three GitHub Actions workflows ensure code quality and security:
| Workflow | Trigger | Purpose |
|---|---|---|
| CI Pipeline | PR + push to main | Terraform validation, YAML/Docker/Markdown/Shell linting, security scans |
| Security Deep | Weekly (Monday) | tfsec, Trivy, Gitleaks, ShellCheck with SARIF upload |
| Docker Scan | Weekly (Wednesday) | Container image vulnerability scanning |
The CI pipeline runs in 5 stages: fast validation, security scans, Docker checks, PR automation, and summary. Pre-commit hooks provide local validation before every commit.
See docs/09-CICD-MONITORING.md for pipeline architecture details.
Typical consumption on OCI Always Free tier (single-user setup):
| Resource | Usage | Available | Note |
|---|---|---|---|
| RAM | ~1GB active | 24GB | Optimized (Talk/Whiteboard removed) |
| CPU | 5-10% avg | 4 cores | Low idle consumption |
| Storage | ~5-10GB base | 100GB data volume | + user data + backups |
| Network | Variable | 10TB/month | OCI Free Tier outbound |
| Cost | $0.00 | - | Always Free tier |
| Guide | Description |
|---|---|
01-INITIAL-SETUP.md |
SSH configuration and first connection |
02-SYSTEM-SETUP.md |
System updates and base packages |
03-DOCKER-SETUP.md |
Docker and Docker Compose installation |
04-FIREWALL-SECURITY.md |
UFW and Fail2ban configuration |
05-CADDY-REVERSE-PROXY.md |
Caddy setup for automatic SSL |
05-NEXTCLOUD-DEPLOYMENT.md |
Nextcloud AIO deployment guide |
06-BACKUP-RESTORE.md |
Backup strategy and disaster recovery |
07-CRON-AUTOMATION.md |
Scheduled tasks setup |
08-TERRAFORM-STRATEGY.md |
IaC patterns and operational workflows |
09-CICD-MONITORING.md |
CI/CD pipeline architecture |
10-LOCAL-BACKUP-MANAGEMENT.md |
Local backup automation guide |
terraform/README.md |
Terraform deployment guide |
scripts/README.md |
Scripts reference |
ROADMAP.md |
Project roadmap and progress |
- Infrastructure - OCI Always Free tier with Terraform IaC
- Nextcloud - Full deployment with Collabora, Calendar, Contacts, Files
- Security - Multi-layer firewall, Fail2ban, HTTPS, 2FA
- Backups - Borg daily + data exports + off-site sync
- Monitoring - Prometheus + Grafana + exporters
- CI/CD - 3 GitHub Actions workflows + pre-commit hooks
- Media services - Komga (manga) + Jellyfin (video) via Tailscale
- Disaster recovery - Tested with 3 destroy/apply cycles
- Alertmanager for critical notifications (disk, memory, container health)
- Off-site backup to OCI Object Storage
- Log aggregation (Loki + Promtail)
- Additional services (Vaultwarden, Uptime Kuma)
MIT License - Feel free to use and modify for your own projects.
- Nextcloud AIO - All-in-one Nextcloud distribution
- Caddy - Automatic HTTPS web server
- Tailscale - Zero-config VPN
- Oracle Cloud - Always Free tier
- Komga - Comics/manga media server
- Jellyfin - Free media server
Project by Veronica Schembri
Last updated: March 2025