
Self-Hosted Stack for a Digital Agency
Consolidation of fragmented SaaS subscriptions into a self-hosted open-source stack featuring pull-based Portainer management and perimeter defense via Caddy with Coraza WAF.
CONFIDENTIALITY DISCLAIMER: Due to non-disclosure agreements and the sensitive nature of the infrastructure described, the client name is kept under a pseudonym. Technical details reflect the deployed architecture.
1. Problem
A digital agency had accumulated multiple Software-as-a-Service (SaaS) subscriptions to handle client management, web analytics, code hosting, and team collaboration. Monthly licensing fees escalated as new staff joined, while operational data was fragmented across third-party multi-tenant vendors. Unilateral changes to vendor pricing models or API policies created recurring technical and financial uncertainty. The agency sought to regain ownership of its operational tools without ongoing per-seat subscription constraints.
2. Context
The digital agency operated daily workflows across several cloud platforms. Developing custom internal tools from scratch was evaluated, but long-term software maintenance exceeded the team’s engineering capacity. As a viable alternative, I identified mature open-source applications and designed a self-hosted environment on dedicated virtual private servers, consolidating core technical workflows under a predictable cost model. This engagement represents an ongoing relationship active since April 2026.
3. Trade-offs
| Approach | Cost Structure | Data Ownership | Software Maintenance | Operational Considerations |
|---|---|---|---|---|
| Standard SaaS subscriptions | Variable per seat or usage tier | Delegated to third-party vendors | None at server level | Ongoing dependency on vendor policies |
| In-house custom software development | Very high engineering investment | Full | Continuous and heavy on internal team | Diverts resources from client delivery |
| Unmanaged self-hosting on basic VPS | Low direct licensing fees | Full | High: vulnerable to insecure defaults | Lack of structured update procedures |
| Hardened self-hosted stack with pull-based management (this case) | Fixed hosting costs plus orchestration tooling | Full: data remains on private hosts | Automated via playbooks and stable tags | Portainer Business Edition requires a commercial license |
In weighing architectural trade-offs, note that the selected management platform (Portainer Business Edition) is a commercial, paid solution. It was chosen over the free community edition because of its pull-based Edge Agent capabilities and official enterprise support for centralized cluster coordination.
4. Decision
I designed and deployed a self-hosted platform across a fleet of dedicated virtual instances using Docker containers and a pull-based management topology:
Previous State: Fragmented SaaS Tools
(Collaboration platforms, analytics, and repositories)
|
v
Dedicated Server Fleet
+------------------------------------------+
| Pull-Based Management |
| Portainer Business Edition (Edge Agents) |
| GitOps configuration deployments |
+------------------------------------------+
+------------------------------------------+
| Ingress and Security Layer |
| Caddy reverse proxy + Coraza WAF |
| Automated TLS termination (Let's Encrypt)|
| UFW firewall: default-deny policy |
+------------------------------------------+
+------------------------------------------+
| Self-Hosted Open-Source Applications |
| Plausible Analytics (web traffic metrics)|
| Forgejo and Fider (code and feedback) |
| Nextcloud and Vikunja (files and tasks) |
+------------------------------------------+
Pull-based management: I deployed Portainer Business Edition Edge Agents so that worker nodes initiate outbound secure connections to the central instance. This architecture allowed enforcing a default-deny inbound firewall policy across all hosts, closing administrative ports to the public internet.
Perimeter security: I configured Caddy as the unified reverse proxy paired with the Coraza WAF engine running the OWASP Core Rule Set. Automated TLS certificates are provisioned through Let’s Encrypt.
Automated provisioning: I developed Ansible playbooks to harden the base operating systems, standardize container configurations, and inject encrypted secrets using Mozilla SOPS.
Backup routines: I implemented automated backup pipelines targeting S3-compatible remote storage, with periodic verification drills for databases and persistent volumes.
5. Result
The digital agency has operated this self-hosted environment in production since April 2026. Web analytics, source code repositories, document sharing, and task tracking run on dedicated instances under direct control of the internal team. The pull-based architecture keeps administrative ports closed to incoming internet probes, while the reverse proxy and WAF inspect application requests. The infrastructure replaced priority SaaS dependencies with stable operating expenses.
6. Known issues
Default container configurations: Upstream open-source images occasionally ship with permissive credentials or default passwords. I updated Ansible provisioning playbooks to enforce runtime generation of unique database credentials and sanitize environment variables prior to exposing traffic.
WAF tuning on administrative forms: Specific administrative panels triggered false positive blocks within OWASP Core Rule Set inspection. I resolved this by authoring rule exclusions scoped strictly to internal authenticated endpoint paths.
Backup lifecycle management: Daily snapshots generated high volume on secondary storage. I configured retention policies to prune older incremental snapshots systematically, keeping storage costs aligned with capacity limits.
7. Limits
I did not manage end-user application support or audit data protection legal compliance for the agency’s end clients; my delivery focused on host provisioning, perimeter security, and container lifecycle automation.
Method note. I publish a metric only when I hold records that support it, with its period and measurement method. This case omits figures I cannot yet document.
Want this engineering approach for your own infrastructure?
About Developmi