Self-hosted application stack running on Oracle Cloud Infrastructure. Fedora CoreOS instance provisioned via Terraform and Ignition, with Podman containers managed through systemd (Compose for app services, Quadlets for infrastructure). Secrets are delivered at runtime by Infisical Agent, and backups go to OCI Object Storage via Autorestic.
flowchart LR
CF[Cloudflare] --> LB
subgraph OCI[OCI]
LB[Load Balancer] --> Traefik
subgraph Instance
Traefik --> Services
Infisical[Infisical Agent] -.->|secrets| Services
Services -->|data| Autorestic
end
Autorestic --> Bucket[Object Storage]
end
Infisical -.-> Infisical.com
oci-apps/
├── terraform/ # Infrastructure as Code
├── os-config/ # Butane/Ignition + Quadlet container units
│ ├── butane.yaml
│ ├── scripts/
│ ├── systemd/
│ └── quadlets/ # Traefik, Infisical Agent, Autorestic
├── containers/ # Podman Compose stacks
│ ├── freshrss/
│ ├── planka/
│ ├── nitter/
│ └── redlib/
└── .github/workflows/ # CI/CD pipelines
- Terraform >= 1.10
- Infisical CLI
- butane CLI (
brew install butane) - Access to OCI tenancy with oci-core infrastructure deployed
Deployments are triggered automatically:
- Feature branches — pre-commit +
terraform plan(posts to PR) - Tags (
v*) —terraform apply
| Name | Version |
|---|---|
| terraform | ~> 1.10 |
| cloudflare | ~> 5.0 |
| ct | ~> 0.14 |
| http | ~> 3.0 |
| null | ~> 3.0 |
| oci | ~> 8.0 |
| tailscale | ~> 0.29 |
| tls | ~> 4.0 |
| Name | Version |
|---|---|
| cloudflare | 5.19.1 |
| ct | 0.14.0 |
| http | 3.6.0 |
| null | 3.3.0 |
| oci | 8.15.0 |
| tailscale | 0.29.2 |
| terraform | n/a |
| tls | 4.3.0 |
No modules.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| availability_domain | Availability domain where instance will be launched | string |
n/a | yes |
| boot_volume_size | Boot volume size in GB | number |
50 |
no |
| bucket_name | Name for the bucket (defaults to {name}) | string |
"" |
no |
| cloudflare_custom_list | The name of the custom list in CloudFlare containing trusted IP ranges | string |
n/a | yes |
| infisical_client_id | Infisical Universal Auth client ID | string |
n/a | yes |
| infisical_client_secret | Infisical Universal Auth client secret | string |
n/a | yes |
| instance_ocpus | Number of OCPUs to allocate to the instance | number |
4 |
no |
| instance_ram | RAM in GB to allocate to the instance | number |
24 |
no |
| instance_shape | Instance shape (default is always free ARM) | string |
"VM.Standard.A1.Flex" |
no |
| lb_bandwidth | Load balancer bandwidth in Mbps (default is always free) | number |
10 |
no |
| name | Name prefix for all resources | string |
"oci-apps" |
no |
| oci_fingerprint | Fingerprint of the key used to authenticate with OCI | string |
n/a | yes |
| oci_private_key | Private key to authenticate with OCI | string |
n/a | yes |
| oci_region | OCI region for resources | string |
n/a | yes |
| oci_tenancy_id | OCI tenancy ID | string |
n/a | yes |
| oci_user_id | OCI user ID for Terraform | string |
n/a | yes |
| private_key_pem | Base64 encoded private key PEM for TLS certificate | string |
n/a | yes |
| remote_state_endpoint | S3-compatible endpoint for remote state | string |
n/a | yes |
| restic_password | Restic repository encryption password | string |
n/a | yes |
| services | Service configuration map | map(object({ |
{ |
no |
| zone_id | CloudFlare zone ID | string |
n/a | yes |
No outputs.