<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://your-docusaurus-site.example.com/es/blog</id>
    <title>Filess.io Documentation Blog</title>
    <updated>2026-04-04T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://your-docusaurus-site.example.com/es/blog"/>
    <subtitle>Filess.io Documentation Blog</subtitle>
    <icon>https://your-docusaurus-site.example.com/es/img/filess-favicon.svg</icon>
    <entry>
        <title type="html"><![CDATA[Database Monitoring Without the Yak Shaving: Prometheus, PMM, and Alerts Built In]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts"/>
        <updated>2026-04-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Setting up database monitoring from scratch is one of those tasks that feels like it should take an afternoon but ends up consuming a week.]]></summary>
        <content type="html"><![CDATA[<p>Setting up database monitoring from scratch is one of those tasks that feels like it should take an afternoon but ends up consuming a week.</p>
<p>You need Prometheus. Then an exporter for your specific database. Then Grafana (or another dashboard). Then Alertmanager. Then you need to write the alert rules, configure notification channels, test that the alerts actually fire, and figure out why they fire at 3am for things that aren't real emergencies.</p>
<p>And this is <em>before</em> you've handled certificate rotation for the exporter, dealt with the Prometheus scrape interval tuning, or figured out why your dashboard queries are returning <code>No data</code>.</p>
<p>With Filess Dedicated databases, all of this ships by default. Here's what you get and how it's built.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="percona-monitoring-and-management-pmm-already-running">Percona Monitoring and Management (PMM), Already Running<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#percona-monitoring-and-management-pmm-already-running" class="hash-link" aria-label="Enlace directo al Percona Monitoring and Management (PMM), Already Running" title="Enlace directo al Percona Monitoring and Management (PMM), Already Running" translate="no">​</a></h2>
<p>Every Dedicated database includes a <a href="https://www.percona.com/software/database-tools/percona-monitoring-and-management" target="_blank" rel="noopener noreferrer" class=""><strong>PMM</strong></a> instance preconfigured and connected to your database. You don't install anything. You don't run any agents. It's just there.</p>
<p>PMM is Percona's open-source database observability platform. It gives you:</p>
<ul>
<li class=""><strong>Query Analytics (QAN)</strong>: Which queries are slowest? Which ones are running most frequently? Which ones have the highest I/O impact? PMM captures this at the query level — not just at the connection level.</li>
<li class=""><strong>Performance metrics</strong>: CPU, memory, disk I/O, and database-specific metrics (buffer pool hit rate, replication lag, connection count, lock waits, etc.) updated every few seconds.</li>
<li class=""><strong>Database Advisors</strong>: Automated checks that scan your database configuration and data patterns and surface recommendations. Things like "this index is never used" or "your innodb_buffer_pool_size is undersized for your working set."</li>
<li class=""><strong>Explain plans</strong>: Run <code>EXPLAIN</code> on any slow query directly from the PMM UI without opening a terminal.</li>
</ul>
<p>This is the same tooling that DBAs at large-scale deployments use. It's available to you on a $20/month database.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="alert-rules-three-signal-types">Alert Rules: Three Signal Types<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#alert-rules-three-signal-types" class="hash-link" aria-label="Enlace directo al Alert Rules: Three Signal Types" title="Enlace directo al Alert Rules: Three Signal Types" translate="no">​</a></h2>
<p>For automated alerting, we expose a structured alert rule system on top of Prometheus. Three signal types are supported today:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cpu-usage">1. CPU Usage<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#1-cpu-usage" class="hash-link" aria-label="Enlace directo al 1. CPU Usage" title="Enlace directo al 1. CPU Usage" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Rule: cpu_usage &gt; 80% for 5 minutes</span><br></span></code></pre></div></div>
<p>The threshold is expressed as a percentage of the database's allocated CPU. Internally, CPU allocation is expressed in "units" (1 unit = 0.5 vCPU), so a 4-unit database has 2 vCPUs, and a CPU alert at 80% fires when sustained usage exceeds 1.6 vCPUs.</p>
<p>The <code>forMinutes</code> parameter controls how long the condition must be true before the alert fires. Setting it to <code>1</code> means the alert fires within a minute of the threshold being crossed. Setting it to <code>15</code> means sustained high CPU for 15 minutes — useful for workloads with legitimate traffic spikes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-memory-usage">2. Memory Usage<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#2-memory-usage" class="hash-link" aria-label="Enlace directo al 2. Memory Usage" title="Enlace directo al 2. Memory Usage" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Rule: memory_usage &gt; 90% for 3 minutes</span><br></span></code></pre></div></div>
<p>Memory allocation is also expressed in units (1 unit = 500 MiB). The alert fires when RSS memory usage exceeds the threshold percentage of total allocated memory.</p>
<p>Memory alerts at 90%+ on a database are a serious signal. It typically means either:</p>
<ul>
<li class="">Your working set has outgrown your plan (time to scale up).</li>
<li class="">A query is performing a full table scan without a covering index and pulling enormous amounts of data into the buffer pool.</li>
<li class="">A connection pool is leaking and connections are accumulating unreleased memory.</li>
</ul>
<p>PMM's query analytics will usually tell you which one.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-downtime">3. Downtime<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#3-downtime" class="hash-link" aria-label="Enlace directo al 3. Downtime" title="Enlace directo al 3. Downtime" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Rule: database is unreachable</span><br></span></code></pre></div></div>
<p>The downtime rule doesn't take a threshold — it's a binary check. If the database stops responding to health checks for the configured <code>forMinutes</code> window, the alert fires.</p>
<p>This is the most critical alert type. It fires on actual outages, not capacity pressure.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="creating-alert-rules-via-api">Creating Alert Rules via API<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#creating-alert-rules-via-api" class="hash-link" aria-label="Enlace directo al Creating Alert Rules via API" title="Enlace directo al Creating Alert Rules via API" translate="no">​</a></h2>
<p>Alert rules are fully automatable:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST https://api.filess.io/v1/organizations/my-org/namespaces/prod/databases/42/alert-rules \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Authorization: Bearer $FILESS_TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -d '{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "type": "cpu_usage",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "thresholdPercent": 80,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "forMinutes": 5,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "name": "High CPU"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }'</span><br></span></code></pre></div></div>
<p>Response:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">17</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"High CPU"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"type"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"cpu_usage"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"thresholdPercent"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"forMinutes"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"isEnabled"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"status"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ok"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"createdAt"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-04-04T10:00:00Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>You can also manage alert rules via the dashboard. Rules can be enabled/disabled without deleting them — useful when you're doing planned maintenance and want to silence alerts temporarily.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-alerts-are-evaluated">How Alerts Are Evaluated<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#how-alerts-are-evaluated" class="hash-link" aria-label="Enlace directo al How Alerts Are Evaluated" title="Enlace directo al How Alerts Are Evaluated" translate="no">​</a></h2>
<p>The evaluation pipeline uses Prometheus as the underlying data source. Here's the simplified flow:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Database → Exporter → Prometheus scrape → PromQL evaluation → AlertManager → Notification</span><br></span></code></pre></div></div>
<p>Our backend has a direct integration with Prometheus. When you create or update an alert rule, we generate the corresponding PromQL expression and register it with Alertmanager. The rule includes the <code>for</code> duration — Prometheus won't fire the alert until the condition has been continuously true for that duration.</p>
<p>When an alert fires, Alertmanager routes the notification to our backend, which then:</p>
<ol>
<li class="">Records an <code>AlertEvent</code> in the database with status <code>firing</code>.</li>
<li class="">Determines which users in the namespace should be notified.</li>
<li class="">Sends notifications via the configured channels.</li>
</ol>
<p>When the condition resolves, another event is recorded with status <code>resolved</code>, and a resolution notification is sent.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="notification-channels">Notification Channels<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#notification-channels" class="hash-link" aria-label="Enlace directo al Notification Channels" title="Enlace directo al Notification Channels" translate="no">​</a></h2>
<p>Currently supported notification channels:</p>
<ul>
<li class=""><strong>Email</strong>: Delivered to all users in the namespace with notification access.</li>
<li class=""><strong>In-app notifications</strong>: Available in the dashboard notification center.</li>
</ul>
<p>Webhook notifications and Slack integration are on the roadmap.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="alert-event-history">Alert Event History<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#alert-event-history" class="hash-link" aria-label="Enlace directo al Alert Event History" title="Enlace directo al Alert Event History" translate="no">​</a></h2>
<p>Every alert firing and resolution is stored as an event. This gives you a timeline of incidents:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">2026-03-12 03:14 UTC — cpu_usage fired: CPU at 94% for 5 minutes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-03-12 03:47 UTC — cpu_usage resolved: CPU back to 23%</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-03-15 11:02 UTC — memory_usage fired: Memory at 91% for 3 minutes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-03-15 11:09 UTC — memory_usage resolved</span><br></span></code></pre></div></div>
<p>This timeline is useful for:</p>
<ul>
<li class="">Post-mortems: correlating an alert firing with a deployment, traffic spike, or schema change.</li>
<li class="">Capacity planning: how often are you hitting CPU or memory limits? Is it getting more frequent?</li>
<li class="">On-call handoffs: the incoming responder can see what's been happening without reading through a chat thread.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-prometheus-architecture-behind-it">The Prometheus Architecture Behind It<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#the-prometheus-architecture-behind-it" class="hash-link" aria-label="Enlace directo al The Prometheus Architecture Behind It" title="Enlace directo al The Prometheus Architecture Behind It" translate="no">​</a></h2>
<p>Our monitoring stack is region-scoped. Each region runs a shared Prometheus instance that scrapes all databases in that region. The per-database metrics are namespaced by database ID to prevent cross-tenant data leakage.</p>
<p>The connection config is encrypted at rest:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">HostingRegion {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  prometheusEndpoint:         "https://prometheus.eu.filess.io"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  prometheusUsername:         "filess-backend"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  prometheusPasswordEncrypted: "AES256GCM-encrypted-value"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>Credentials are decrypted in memory at query time. They're never stored in plaintext in the database.</p>
<p>When you query database metrics from the dashboard, our backend:</p>
<ol>
<li class="">Looks up the region's Prometheus endpoint.</li>
<li class="">Decrypts the credentials.</li>
<li class="">Executes a scoped PromQL query against Prometheus.</li>
<li class="">Returns the data to the frontend.</li>
</ol>
<p>You never hit Prometheus directly. You don't manage credentials. You don't write PromQL.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-youre-not-doing">What You're Not Doing<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#what-youre-not-doing" class="hash-link" aria-label="Enlace directo al What You're Not Doing" title="Enlace directo al What You're Not Doing" translate="no">​</a></h2>
<p>Let's be explicit about the yak shaving you're avoiding:</p>
<table><thead><tr><th>Without Filess</th><th>With Filess</th></tr></thead><tbody><tr><td>Install Prometheus on a server</td><td>—</td></tr><tr><td>Install mysqld_exporter / postgres_exporter</td><td>—</td></tr><tr><td>Configure scrape intervals and labels</td><td>—</td></tr><tr><td>Set up Alertmanager</td><td>—</td></tr><tr><td>Write PromQL alert expressions</td><td>Click "Add Rule" in dashboard</td></tr><tr><td>Configure notification channels</td><td>Add email in dashboard</td></tr><tr><td>Set up Grafana dashboards</td><td>PMM dashboards included</td></tr><tr><td>Renew exporter TLS certificates</td><td>—</td></tr><tr><td>Monitor the monitoring infrastructure</td><td>—</td></tr></tbody></table>
<p>The goal is for you to spend your time understanding what your database is doing, not configuring the tools that watch it.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-started">Getting Started<a href="https://your-docusaurus-site.example.com/es/blog/database-monitoring-prometheus-pmm-alerts#getting-started" class="hash-link" aria-label="Enlace directo al Getting Started" title="Enlace directo al Getting Started" translate="no">​</a></h2>
<p>Alert rules are available on all Dedicated plans. PMM access is included on Dedicated plans.</p>
<p>To add your first alert rule:</p>
<ol>
<li class="">Navigate to your database in the Filess dashboard.</li>
<li class="">Go to <strong>Monitoring → Alert Rules</strong>.</li>
<li class="">Click <strong>Add Rule</strong>, choose the type, set the threshold and duration.</li>
<li class="">Save. That's it.</li>
</ol>
<p>The next time your database hits 80% CPU for 5 minutes, you'll know about it before your users do.</p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Explore Filess Dedicated Databases →</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="monitoring" term="monitoring"/>
        <category label="prometheus" term="prometheus"/>
        <category label="pmm" term="pmm"/>
        <category label="alerts" term="alerts"/>
        <category label="databases" term="databases"/>
        <category label="devops" term="devops"/>
        <category label="sre" term="sre"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Your docker-compose.yml, Running on Kubernetes: How Filess Hosting Works]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting"/>
        <updated>2026-04-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Every indie developer has been there: you've got a docker-compose.yml that works perfectly on your laptop. Redis, Postgres, your app — all wired up, healthy, humming.]]></summary>
        <content type="html"><![CDATA[<p>Every indie developer has been there: you've got a <code>docker-compose.yml</code> that works perfectly on your laptop. Redis, Postgres, your app — all wired up, healthy, humming.</p>
<p>Then you try to deploy it.</p>
<p>You either wrangle with a VPS, a Dockerfile, a reverse proxy, SSL certificates, and systemd units — or you pay a managed platform that doesn't understand <code>docker-compose.yml</code> natively and forces you to rewrite everything in their DSL.</p>
<p>Filess Hosting takes your <code>docker-compose.yml</code> and runs it on Kubernetes, with zero Kubernetes knowledge required. Here's the full technical picture of what happens when you push a commit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-build-pipeline-from-git-to-running-container">The Build Pipeline: From Git to Running Container<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#the-build-pipeline-from-git-to-running-container" class="hash-link" aria-label="Enlace directo al The Build Pipeline: From Git to Running Container" title="Enlace directo al The Build Pipeline: From Git to Running Container" translate="no">​</a></h2>
<p>When you trigger a deployment (manually, via API, or automatically on git push), the pipeline goes through three phases.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-1-preflight-analysis">Phase 1: Preflight Analysis<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#phase-1-preflight-analysis" class="hash-link" aria-label="Enlace directo al Phase 1: Preflight Analysis" title="Enlace directo al Phase 1: Preflight Analysis" translate="no">​</a></h3>
<p>Before building anything, we analyze your repository:</p>
<ul>
<li class="">Parse the <code>docker-compose.yml</code> and validate all service definitions.</li>
<li class="">Resolve <code>${VARIABLE}</code> interpolations against your environment variables, catching missing required variables early with clear error messages.</li>
<li class="">Validate exposed ports, Dockerfile paths, build context paths, and Docker build args.</li>
<li class="">Detect the build system: if you have a <code>Dockerfile</code>, we use it. If you have a <code>docker-compose.yml</code> with <code>build:</code> stanzas, we build all services. If neither, we fall back to <a href="https://nixpacks.com/" target="_blank" rel="noopener noreferrer" class="">Nixpacks</a> for automatic detection.</li>
</ul>
<p>This step fails fast. There's no 10-minute wait for a build to fail because you had a typo in your Compose file.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-2-building--kaniko-in-the-cluster">Phase 2: Building — Kaniko in the Cluster<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#phase-2-building--kaniko-in-the-cluster" class="hash-link" aria-label="Enlace directo al Phase 2: Building — Kaniko in the Cluster" title="Enlace directo al Phase 2: Building — Kaniko in the Cluster" translate="no">​</a></h3>
<p>We build container images using <a href="https://github.com/GoogleContainerTools/kaniko" target="_blank" rel="noopener noreferrer" class=""><strong>Kaniko</strong></a>, Google's daemonless Kubernetes-native image builder. This runs entirely inside the cluster — no Docker daemon, no privileged containers.</p>
<p>The build process:</p>
<ol>
<li class="">A Kaniko job is created in your project's Kubernetes namespace.</li>
<li class="">Kaniko clones your repository (via HTTPS or SSH, depending on your repo credential configuration).</li>
<li class="">It executes your <code>Dockerfile</code> steps layer by layer.</li>
<li class="">The final image is pushed to our private container registry with a content-addressed tag based on the commit SHA.</li>
</ol>
<p>Build logs stream in real time to the dashboard. If the build fails, the error is classified by origin (<code>build_failed</code>, <code>preflight_failed</code>, <code>registry_error</code>, etc.) and surfaced with a user-facing explanation rather than a raw Kubernetes error.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-3-runtime--kubernetes-deployments">Phase 3: Runtime — Kubernetes Deployments<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#phase-3-runtime--kubernetes-deployments" class="hash-link" aria-label="Enlace directo al Phase 3: Runtime — Kubernetes Deployments" title="Enlace directo al Phase 3: Runtime — Kubernetes Deployments" translate="no">​</a></h3>
<p>Once the image is in the registry, we apply Kubernetes resources:</p>
<ul>
<li class="">A <strong>Deployment</strong> for each service, with resource limits derived from your plan.</li>
<li class=""><strong>ConfigMaps</strong> for non-sensitive environment variables.</li>
<li class=""><strong>Secrets</strong> for sensitive environment variables (anything you mark as secret in the dashboard).</li>
<li class=""><strong>PersistentVolumeClaims</strong> for any volumes you've defined.</li>
<li class="">An <strong>HTTPRoute</strong> (Gateway API) that maps your custom domain or subdomain to the main service.</li>
<li class="">A <strong>TLS certificate</strong> via our cert-manager integration.</li>
</ul>
<p>The deployment is rolled out with a rolling update strategy. Zero downtime by default.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-docker-compose-translator">The Docker Compose Translator<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#the-docker-compose-translator" class="hash-link" aria-label="Enlace directo al The Docker Compose Translator" title="Enlace directo al The Docker Compose Translator" translate="no">​</a></h2>
<p>The most technically interesting part is how we translate <code>docker-compose.yml</code> into Kubernetes resources. This isn't a direct 1:1 mapping — Compose and Kubernetes have different models — so we built our own translator.</p>
<p>A <code>docker-compose.yml</code> like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">web</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"3000:3000"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">environment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">DATABASE_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DATABASE_URL</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">REDIS_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//cache</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">6379</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> cache</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">healthcheck</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"CMD"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"curl"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://localhost:3000/health"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">interval</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 30s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">timeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">retries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">cache</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> redis_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  redis_data</span><span class="token punctuation" style="color:#393A34">:</span><br></span></code></pre></div></div>
<p>Gets translated into a <code>ComposeRuntimeSpec</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"version"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"composePath"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"docker-compose.yml"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"mainService"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"mainServiceSlug"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"mainPort"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"services"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"slug"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"runtimeName"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"my-app-web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"image"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"registry.filess.io/my-project/web:sha256-abc123"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"ports"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3000</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"env"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"key"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"DATABASE_URL"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"runtimeEnvKey"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"DATABASE_URL"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"key"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"REDIS_URL"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"redis://my-app-cache:6379"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"healthcheck"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"command"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"CMD"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"curl"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://localhost:3000/health"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"intervalSeconds"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"timeoutSeconds"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"retries"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"cache"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"slug"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"cache"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"runtimeName"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"my-app-cache"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"image"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"redis:7-alpine"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"ports"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"env"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"volumes"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"mountPath"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/data"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"claimName"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"my-app-redis-data"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"buildTasks"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"slug"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"contextPath"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"dockerfilePath"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Dockerfile"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"dockerBuildArgs"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"imageTag"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"registry.filess.io/my-project/web:sha256-abc123"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>This spec is stored in the database and used to idempotently reconcile the Kubernetes state. If you push a new commit, we diff the spec and apply only what changed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="variable-interpolation">Variable Interpolation<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#variable-interpolation" class="hash-link" aria-label="Enlace directo al Variable Interpolation" title="Enlace directo al Variable Interpolation" translate="no">​</a></h3>
<p>We implement the full Docker Compose variable interpolation spec:</p>
<table><thead><tr><th>Syntax</th><th>Behavior</th></tr></thead><tbody><tr><td><code>${VAR}</code></td><td>Use value of VAR; empty string if unset</td></tr><tr><td><code>${VAR:-default}</code></td><td>Use VAR if set and non-empty, else <code>default</code></td></tr><tr><td><code>${VAR-default}</code></td><td>Use VAR if set (even if empty), else <code>default</code></td></tr><tr><td><code>${VAR:?error}</code></td><td>Error if VAR is unset or empty</td></tr><tr><td><code>${VAR?error}</code></td><td>Error if VAR is unset</td></tr><tr><td><code>${VAR:+replacement}</code></td><td>Use <code>replacement</code> if VAR is set and non-empty</td></tr><tr><td><code>$$</code></td><td>Literal <code>$</code></td></tr></tbody></table>
<p>This matters because many real <code>docker-compose.yml</code> files use these constructs to make environments portable.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preview-environments">Preview Environments<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#preview-environments" class="hash-link" aria-label="Enlace directo al Preview Environments" title="Enlace directo al Preview Environments" translate="no">​</a></h2>
<p>This is the feature that changes how you do code review.</p>
<p>Every branch (or pull request) can get its own ephemeral deployment at a unique URL:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">https://feature-login-redesign--my-app.filess.app</span><br></span></code></pre></div></div>
<p>The URL is derived from a hash of the branch name and project ID — deterministic and permanent for the lifetime of the branch. When the PR is merged, the preview environment is automatically cleaned up.</p>
<p>The Prisma model behind this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">HostingPreviewEnvironment {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  sourceType: branch | commit | tag</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  sourceRef:  "feature/login-redesign"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  subdomain:  "feature-login-redesign--abc123"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  closedAt:   null (open) or DateTime (closed)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>Preview environments share the same build infrastructure as production. They use the same container image (built once, deployed twice) but get their own Kubernetes namespace, their own environment variables, and their own URL.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="persistent-volumes">Persistent Volumes<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#persistent-volumes" class="hash-link" aria-label="Enlace directo al Persistent Volumes" title="Enlace directo al Persistent Volumes" translate="no">​</a></h2>
<p>Stateful apps need persistent storage. You can define volumes in the dashboard or inherit them from your <code>docker-compose.yml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">uploaded_files</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">driver</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> local</span><br></span></code></pre></div></div>
<p>Each volume becomes a <code>PersistentVolumeClaim</code> in Kubernetes, mounted into the container at the specified path. Mount paths must be under <code>/app</code> or <code>/data</code> — we enforce this to prevent accidental mounts of system directories.</p>
<p>Volume sizes are specified in GiB and billed accordingly. Volumes survive deployments: if you push a new commit, your uploaded files stay where they were.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="health-checks-and-restart-policies">Health Checks and Restart Policies<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#health-checks-and-restart-policies" class="hash-link" aria-label="Enlace directo al Health Checks and Restart Policies" title="Enlace directo al Health Checks and Restart Policies" translate="no">​</a></h2>
<p>If your <code>docker-compose.yml</code> defines a healthcheck, we translate it into a Kubernetes <code>livenessProbe</code> and <code>readinessProbe</code>. This means:</p>
<ul>
<li class="">Kubernetes won't route traffic to your pod until it's ready.</li>
<li class="">If a pod becomes unhealthy, Kubernetes replaces it automatically.</li>
<li class="">The deployment rollout waits for new pods to become healthy before terminating old ones.</li>
</ul>
<p>Restart policies are configurable:</p>
<ul>
<li class=""><strong>Always</strong> (default): Restart on any exit.</li>
<li class=""><strong>OnFailure</strong>: Only restart on non-zero exit codes.</li>
<li class=""><strong>Never</strong>: Don't restart. Useful for one-shot job containers.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="custom-domains-and-tls">Custom Domains and TLS<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#custom-domains-and-tls" class="hash-link" aria-label="Enlace directo al Custom Domains and TLS" title="Enlace directo al Custom Domains and TLS" translate="no">​</a></h2>
<p>Point any domain at Filess by adding a CNAME record:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">app.yourdomain.com → cname.filess.app</span><br></span></code></pre></div></div>
<p>Add the domain in the dashboard. We verify DNS ownership and provision a TLS certificate automatically. The certificate auto-renews before expiration. You don't manage any of this.</p>
<p>For <code>*.yourdomain.com</code> wildcard certificates on your domain, contact support.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="maintenance-mode">Maintenance Mode<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#maintenance-mode" class="hash-link" aria-label="Enlace directo al Maintenance Mode" title="Enlace directo al Maintenance Mode" translate="no">​</a></h2>
<p>You can enable maintenance mode on any project without a deployment. When enabled, all traffic returns a configurable HTTP status code (503 by default) with a static maintenance page. This is a gateway-level feature — your containers don't need to change.</p>
<p>Bypass the maintenance page during a live incident by sending the <code>X-Filess-Bypass-Maintenance</code> header (value configured in the dashboard). This lets your team verify the fix before taking the site out of maintenance mode.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployment-rollback">Deployment Rollback<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#deployment-rollback" class="hash-link" aria-label="Enlace directo al Deployment Rollback" title="Enlace directo al Deployment Rollback" translate="no">​</a></h2>
<p>Every deployment is immutable. The container image for commit <code>abc123</code> will always be <code>registry.filess.io/my-project/web:abc123</code>. Rolling back is just re-deploying a previous commit — the image is already in the registry, so it's fast.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Roll back via API</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST https://api.filess.io/v1/.../deployments/{previousDeploymentId}/rollback \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Authorization: Bearer $FILESS_TOKEN"</span><br></span></code></pre></div></div>
<p>There's no "undo" button that modifies history. You roll forward to a previous state. Clean audit trail.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="build-logs-and-runtime-logs">Build Logs and Runtime Logs<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#build-logs-and-runtime-logs" class="hash-link" aria-label="Enlace directo al Build Logs and Runtime Logs" title="Enlace directo al Build Logs and Runtime Logs" translate="no">​</a></h2>
<p>All logs are available in the dashboard and via API:</p>
<ul>
<li class=""><strong>Build logs</strong>: The full Kaniko output for each build. Captured and stored so you can debug failures from last week without hunting through a CI system.</li>
<li class=""><strong>Runtime logs</strong>: Live and historical logs from your running containers. Filter by service, time range, and log level.</li>
</ul>
<p>Log redaction is automatic. We scan build and runtime logs for known secret patterns (registry credentials, API keys) and redact them before storing or displaying.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's Next<a href="https://your-docusaurus-site.example.com/es/blog/docker-compose-on-kubernetes-filess-hosting#whats-next" class="hash-link" aria-label="Enlace directo al What's Next" title="Enlace directo al What's Next" translate="no">​</a></h2>
<p>Filess Hosting is built for developers who want to ship, not manage infrastructure. If you've been looking for a platform that respects your existing <code>docker-compose.yml</code> and doesn't ask you to rewrite your entire setup, give it a try.</p>
<p>Pair it with a Filess managed database and you've got a full production stack — app + database — in one dashboard.</p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Deploy your first app on Filess →</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="hosting" term="hosting"/>
        <category label="docker" term="docker"/>
        <category label="kubernetes" term="kubernetes"/>
        <category label="devops" term="devops"/>
        <category label="cicd" term="cicd"/>
        <category label="indie-dev" term="indie-dev"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Ephemeral Databases for Every PR: Using the Filess Shared API in CI/CD]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api"/>
        <updated>2026-04-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You've built a feature. It works on your machine. You open a PR.]]></summary>
        <content type="html"><![CDATA[<p>You've built a feature. It works on your machine. You open a PR.</p>
<p>Your CI pipeline runs unit tests. They pass. Your reviewer approves the PR.</p>
<p>You merge. You deploy. Production breaks.</p>
<p>The bug was a subtle interaction between your code and the database schema — something unit tests couldn't catch because they mock the database. Integration tests could have caught it, but your integration test suite either doesn't exist or runs against a shared staging database that's full of dirty state from the last developer who also tested there.</p>
<p>The real fix is an <strong>ephemeral database per PR</strong>: a fresh database, identical to production schema, provisioned when the PR opens and destroyed when it merges. Your integration tests run against it. Nothing shares state between PRs.</p>
<p>Filess has two APIs. Knowing which one to use matters.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-apis-two-use-cases">Two APIs, Two Use Cases<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#two-apis-two-use-cases" class="hash-link" aria-label="Enlace directo al Two APIs, Two Use Cases" title="Enlace directo al Two APIs, Two Use Cases" translate="no">​</a></h2>
<p>Filess exposes two distinct REST APIs:</p>
<table><thead><tr><th></th><th>Shared API</th><th>Dedicated API</th></tr></thead><tbody><tr><td><strong>Base URL</strong></td><td><code>https://api.filess.io</code></td><td><code>https://backend.filess.io</code></td></tr><tr><td><strong>Resources</strong></td><td>Instances (<code>/v1/instances</code>)</td><td>Databases (<code>/v1/databases</code>)</td></tr><tr><td><strong>Model</strong></td><td>Simple: identifier + region + motor</td><td>Organizations + Namespaces + plan config</td></tr><tr><td><strong>Auth</strong></td><td>Bearer JWT token</td><td>Bearer API token</td></tr><tr><td><strong>Best for</strong></td><td>CI/CD, prototypes, ephemeral</td><td>Production, teams, stable projects</td></tr><tr><td><strong>Connection info</strong></td><td>Returned immediately on creation</td><td>Retrieved via separate detail call</td></tr></tbody></table>
<p>For ephemeral CI/CD databases, the <strong>Shared API</strong> is the right choice. It's designed for this: three fields in, connection string out. No org slugs, no namespace slugs, no plan configuration.</p>
<p>The Dedicated API (<code>backend.filess.io</code>) is for long-lived databases organized within your team's Organizations and Namespaces — more control, more configuration, better suited for stable environments.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-shared-api-three-endpoints">The Shared API: Three Endpoints<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#the-shared-api-three-endpoints" class="hash-link" aria-label="Enlace directo al The Shared API: Three Endpoints" title="Enlace directo al The Shared API: Three Endpoints" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GET    https://api.filess.io/v1/regions       — List available regions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">POST   https://api.filess.io/v1/instances     — Create a database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DELETE https://api.filess.io/v1/instances/{id} — Delete a database</span><br></span></code></pre></div></div>
<p>That's the entire surface for CI/CD. Clean.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-an-instance">Create an instance<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#create-an-instance" class="hash-link" aria-label="Enlace directo al Create an instance" title="Enlace directo al Create an instance" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST "https://api.filess.io/v1/instances" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Authorization: Bearer &lt;your-jwt-token&gt;" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -d '{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "identifier": "pr-452-test",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "region": "4747ed15-34b7-4f41-a80b-387a6a907a1e",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "motor": "mysql-8.0.29"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }'</span><br></span></code></pre></div></div>
<p>Response — connection details returned immediately, no second request needed:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"msg"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"OK"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"data"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"instance"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"14f831d2-923c-4352-86d0-10f06c6272ae"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"pr452test_acceptinch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"user"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"pr452test_acceptinch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"isEnabled"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"identifier"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"pr-452-test"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"host"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"z6a.h.filess.io"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"port"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3306</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"region"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Spain"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"password"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dd976df83454d5a9bb259995ae82f222ac82e59d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"createdAt"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-04-04T10:00:00.000Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="available-motors">Available motors<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#available-motors" class="hash-link" aria-label="Enlace directo al Available motors" title="Enlace directo al Available motors" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mysql-5.7.38</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mysql-8.0.29</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mariadb-10.7.4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">postgresql-14.4.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">postgresql-15.4.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mongodb-5.0.9</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mongodb-7.0.2</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="delete-an-instance">Delete an instance<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#delete-an-instance" class="hash-link" aria-label="Enlace directo al Delete an instance" title="Enlace directo al Delete an instance" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -X DELETE "https://api.filess.io/v1/instances/14f831d2-923c-4352-86d0-10f06c6272ae" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Authorization: Bearer &lt;your-jwt-token&gt;"</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="complete-github-actions-workflow">Complete GitHub Actions Workflow<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#complete-github-actions-workflow" class="hash-link" aria-label="Enlace directo al Complete GitHub Actions Workflow" title="Enlace directo al Complete GitHub Actions Workflow" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># .github/workflows/integration-tests.yml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Integration Tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">pull_request</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">types</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">opened</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> synchronize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reopened</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> closed</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> github.event.action </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'closed'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Get region ID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> region</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">FILESS_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.FILESS_SHARED_TOKEN </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          REGION_ID=$(curl -sf "https://api.filess.io/v1/regions" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            -H "Authorization: Bearer $FILESS_TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            | jq -r '.data.regions[0].id')</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          echo "id=$REGION_ID" &gt;&gt; $GITHUB_OUTPUT</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Create ephemeral database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">FILESS_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.FILESS_SHARED_TOKEN </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          RESPONSE=$(curl -sf -X POST "https://api.filess.io/v1/instances" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            -H "Authorization: Bearer $FILESS_TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            -d "{</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">              \"identifier\": \"pr-${{ github.event.number }}\",</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">              \"region\": \"${{ steps.region.outputs.id }}\",</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">              \"motor\": \"mysql-8.0.29\"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            }")</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_ID=$(echo $RESPONSE   </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.id')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_HOST=$(echo $RESPONSE </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.host')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_PORT=$(echo $RESPONSE </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.port')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_USER=$(echo $RESPONSE </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.user')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_PASS=$(echo $RESPONSE </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.password')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_NAME=$(echo $RESPONSE </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> jq </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">r '.data.instance.name')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic"># Build connection URL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          DB_URL="mysql</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DB_USER</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DB_PASS</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">@$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DB_HOST</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DB_PORT</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">DB_NAME</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          echo "db_id=$DB_ID"   </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> $GITHUB_OUTPUT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          echo "db_url=$DB_URL" </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> $GITHUB_OUTPUT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Store DB ID for cleanup</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/cache/save@v4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /dev/null  </span><span class="token comment" style="color:#999988;font-style:italic"># dummy, we use the key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> filess</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">pr</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.event.number </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.db.outputs.db_id </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run migrations</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">DATABASE_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.db.outputs.db_url </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> npx prisma migrate deploy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run integration tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">DATABASE_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.db.outputs.db_url </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> npm test </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">testPathPattern=integration</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Delete database on test failure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> failure()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">FILESS_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.FILESS_SHARED_TOKEN </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          curl -sf -X DELETE \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            "https://api.filess.io/v1/instances/${{ steps.db.outputs.db_id }}" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            -H "Authorization: Bearer $FILESS_TOKEN"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">teardown</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> github.event.action == 'closed'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Restore cached DB ID</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cache</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/cache/restore@v4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> filess</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">pr</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.event.number </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">restore-keys</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> filess</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">pr</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.event.number </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Delete database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">FILESS_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.FILESS_SHARED_TOKEN </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          # Extract DB ID from the matched cache key</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          DB_ID=$(echo "${{ steps.cache.outputs.cache-matched-key }}" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            | sed 's/filess-db-pr-[0-9]*-//')</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          curl </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">sf </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">X DELETE \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "https</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//api.filess.io/v1/instances/$DB_ID" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">-H "Authorization</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Bearer $FILESS_TOKEN"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          echo "Deleted database $DB_ID"</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-minimal-shell-helper">A Minimal Shell Helper<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#a-minimal-shell-helper" class="hash-link" aria-label="Enlace directo al A Minimal Shell Helper" title="Enlace directo al A Minimal Shell Helper" translate="no">​</a></h2>
<p>For projects that use multiple CI systems or custom scripts:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">#!/usr/bin/env bash</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># scripts/filess.sh — Shared API wrapper</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">set -e</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">TOKEN="${FILESS_SHARED_TOKEN:?FILESS_SHARED_TOKEN must be set}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BASE="https://api.filess.io"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">filess_regions() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    curl -sf "$BASE/v1/regions" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        -H "Authorization: Bearer $TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        | jq -r '.data.regions[] | "\(.id)\t\(.name)"'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">filess_create() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    local name="$1" region="$2" motor="${3:-mysql-8.0.29}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    curl -sf -X POST "$BASE/v1/instances" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        -H "Authorization: Bearer $TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        -d "{\"identifier\":\"$name\",\"region\":\"$region\",\"motor\":\"$motor\"}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">filess_delete() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    local id="$1"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    curl -sf -X DELETE "$BASE/v1/instances/$id" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        -H "Authorization: Bearer $TOKEN"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">case "$1" in</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    regions)               filess_regions ;;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    create) filess_create  "$2" "$3" "$4" ;;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    delete) filess_delete  "$2" ;;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    *) echo "Usage: $0 regions|create &lt;name&gt; &lt;region&gt; [motor]|delete &lt;id&gt;"; exit 1 ;;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">esac</span><br></span></code></pre></div></div>
<p>Usage:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Pick a region</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">./scripts/filess.sh regions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># → 4747ed15-34b7-4f41-a80b-387a6a907a1e  Spain</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Create</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">RESULT=$(./scripts/filess.sh create "pr-452" "4747ed15-34b7-4f41-a80b-387a6a907a1e")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DB_ID=$(echo $RESULT   | jq -r '.data.instance.id')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DB_HOST=$(echo $RESULT | jq -r '.data.instance.host')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DB_USER=$(echo $RESULT | jq -r '.data.instance.user')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DB_PASS=$(echo $RESULT | jq -r '.data.instance.password')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DB_NAME=$(echo $RESULT | jq -r '.data.instance.name')</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Delete</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">./scripts/filess.sh delete $DB_ID</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-to-use-each-api">When to Use Each API<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#when-to-use-each-api" class="hash-link" aria-label="Enlace directo al When to Use Each API" title="Enlace directo al When to Use Each API" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="shared-api-apifilessio--for">Shared API (<code>api.filess.io</code>) — for:<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#shared-api-apifilessio--for" class="hash-link" aria-label="Enlace directo al shared-api-apifilessio--for" title="Enlace directo al shared-api-apifilessio--for" translate="no">​</a></h3>
<ul>
<li class=""><strong>CI/CD pipelines</strong>: One database per PR, destroyed on merge.</li>
<li class=""><strong>Prototypes</strong>: Spin up a database in 30 seconds to test an idea.</li>
<li class=""><strong>Classroom / hackathon</strong>: Give each participant their own fresh database without managing accounts.</li>
<li class=""><strong>Automated test suites</strong>: Integration tests that need a real database engine, not a mock.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="dedicated-api-backendfilessio--for">Dedicated API (<code>backend.filess.io</code>) — for:<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#dedicated-api-backendfilessio--for" class="hash-link" aria-label="Enlace directo al dedicated-api-backendfilessio--for" title="Enlace directo al dedicated-api-backendfilessio--for" translate="no">​</a></h3>
<ul>
<li class=""><strong>Production databases</strong>: Long-lived, monitored, backed up.</li>
<li class=""><strong>Teams with RBAC</strong>: Organized under Organizations and Namespaces with granular permissions.</li>
<li class=""><strong>Infrastructure-as-code</strong>: Provision databases as part of a Terraform or API-driven infrastructure workflow.</li>
<li class=""><strong>Databases that need addons</strong>: Tailscale, firewall rules, PITR, SSH tunnels, PMM monitoring.</li>
</ul>
<p>The Shared API is fast and frictionless by design. The Dedicated API gives you full control. Use the right one for the job.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-ephemeral-databases-beat-shared-staging">Why Ephemeral Databases Beat Shared Staging<a href="https://your-docusaurus-site.example.com/es/blog/ephemeral-databases-cicd-rest-api#why-ephemeral-databases-beat-shared-staging" class="hash-link" aria-label="Enlace directo al Why Ephemeral Databases Beat Shared Staging" title="Enlace directo al Why Ephemeral Databases Beat Shared Staging" translate="no">​</a></h2>
<p>The shared staging database pattern has real costs:</p>
<ul>
<li class=""><strong>Test flakiness</strong>: Tests pass or fail based on what a previous test run left behind, not on your code.</li>
<li class=""><strong>Parallelism breaks</strong>: Two PRs can't simultaneously test a migration that adds and removes the same column.</li>
<li class=""><strong>Cleanup debt</strong>: You need teardown scripts that are harder to maintain than the tests themselves.</li>
<li class=""><strong>Data leakage</strong>: PII from database dumps living in a shared environment everyone on the team can access.</li>
</ul>
<p>Ephemeral databases eliminate all of this. Each PR gets a clean slate. Migrations either work or they fail clearly. Parallel PR builds never interfere. The database is destroyed on merge, taking all test data with it.</p>
<p>The cost: a few seconds to provision and a few cents per PR on your Filess bill.</p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Get started with the Filess Shared API →</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="api" term="api"/>
        <category label="cicd" term="cicd"/>
        <category label="testing" term="testing"/>
        <category label="preview-environments" term="preview-environments"/>
        <category label="automation" term="automation"/>
        <category label="indie-dev" term="indie-dev"/>
        <category label="github-actions" term="github-actions"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[From Solo Dev to Team: How Filess Models Multi-Tenancy with Organizations, Namespaces, and RBAC]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces"/>
        <updated>2026-04-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You start as a solo developer. One account, one database, no access control needed.]]></summary>
        <content type="html"><![CDATA[<p>You start as a solo developer. One account, one database, no access control needed.</p>
<p>Then you hire a backend developer. You want them to see the production database metrics but not be able to delete anything. Then a contractor joins for three months — you want them to access the staging namespace only. Then your company gets acquired and the acquirer wants their DevOps team to manage infrastructure without touching billing.</p>
<p>Most database platforms weren't designed for this. You end up sharing root credentials via Slack DMs and hoping nobody does something irreversible.</p>
<p>Filess was designed from day one for teams that grow. Here's how the access model works.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-three-layer-model">The Three-Layer Model<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#the-three-layer-model" class="hash-link" aria-label="Enlace directo al The Three-Layer Model" title="Enlace directo al The Three-Layer Model" translate="no">​</a></h2>
<p>Access in Filess is organized in three layers:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Organization</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── Namespace (prod / staging / ci / team-a / team-b)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    └── Resources (databases, tunnels, hosting projects)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="organizations">Organizations<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#organizations" class="hash-link" aria-label="Enlace directo al Organizations" title="Enlace directo al Organizations" translate="no">​</a></h3>
<p>An <strong>Organization</strong> is the top-level billing and access unit. It represents a company, a team, or a project. All resources — databases, tunnels, hosting deployments — belong to an organization.</p>
<p>Key organization-level permissions:</p>
<ul>
<li class=""><code>organization:view</code> — Can see the organization exists.</li>
<li class=""><code>organization:update</code> — Can edit organization settings.</li>
<li class=""><code>organization:billing:view</code> — Can see billing and invoices.</li>
<li class=""><code>organization:invite:create</code> — Can invite new members.</li>
<li class=""><code>organization:transfer_ownership</code> — Can change who owns the organization.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="namespaces">Namespaces<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#namespaces" class="hash-link" aria-label="Enlace directo al Namespaces" title="Enlace directo al Namespaces" translate="no">​</a></h3>
<p>A <strong>Namespace</strong> is a logical partition within an organization. You might have:</p>
<ul>
<li class=""><code>prod</code> — Production databases, locked down. Only senior engineers can touch.</li>
<li class=""><code>staging</code> — Staging databases. Full team access.</li>
<li class=""><code>ci</code> — Ephemeral databases created and destroyed by CI pipelines.</li>
<li class=""><code>team-frontend</code> — Backend databases that the frontend team needs read access to.</li>
</ul>
<p>Namespaces let you implement environment isolation without separate accounts. The same team member can have write access in <code>staging</code> and read-only access in <code>prod</code> — from a single login.</p>
<p>Namespace-level permissions:</p>
<ul>
<li class=""><code>namespace:create_in_organization</code> — Can create new namespaces.</li>
<li class=""><code>namespace:view_in_organization</code> — Can see a namespace.</li>
<li class=""><code>namespace:update_in_organization</code> — Can rename/modify a namespace.</li>
<li class=""><code>namespace:delete_in_organization</code> — Can delete a namespace and all its resources.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="resources">Resources<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#resources" class="hash-link" aria-label="Enlace directo al Resources" title="Enlace directo al Resources" translate="no">​</a></h3>
<p>Resources (databases, tunnels, SSH keys, IP allowlists, hosting projects) live inside namespaces. Each resource type has its own granular permission set.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="roles-and-groups">Roles and Groups<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#roles-and-groups" class="hash-link" aria-label="Enlace directo al Roles and Groups" title="Enlace directo al Roles and Groups" translate="no">​</a></h2>
<p>Rather than assigning permissions directly to users (which doesn't scale), Filess uses <strong>Roles</strong> and <strong>Groups</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="roles">Roles<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#roles" class="hash-link" aria-label="Enlace directo al Roles" title="Enlace directo al Roles" translate="no">​</a></h3>
<p>A <strong>Role</strong> is a named set of permissions. You create roles that match your team structure:</p>
<p><strong>Example: <code>db-reader</code></strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">database:view_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metrics:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">log:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">backup:view_in_database</span><br></span></code></pre></div></div>
<p><strong>Example: <code>db-operator</code></strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">database:view_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database:update_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metrics:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">log:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">backup:create_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">backup:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">backup:restore_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">maintenance_window:view_in_database</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">maintenance_window:create_in_database</span><br></span></code></pre></div></div>
<p><strong>Example: <code>db-admin</code></strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">database:create_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database:view_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database:update_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">database:delete_in_namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">... (all database permissions)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">backup:*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">maintenance_window:*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">alert_rule:*</span><br></span></code></pre></div></div>
<p>Roles are defined at the <strong>organization level</strong> and can be applied to any namespace within that organization.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="groups">Groups<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#groups" class="hash-link" aria-label="Enlace directo al Groups" title="Enlace directo al Groups" translate="no">​</a></h3>
<p>A <strong>Group</strong> is a collection of users. Instead of assigning roles to individual users, you assign roles to groups, then add users to groups.</p>
<p>Why groups?</p>
<ul>
<li class="">When an employee joins, add them to the right group and they inherit all permissions immediately.</li>
<li class="">When an employee leaves, remove them from the group and all access is revoked in one operation.</li>
<li class="">When you onboard a contractor, create a time-limited group with restricted access.</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Group: "backend-engineers"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Members: alice, bob, charlie</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Namespaces: prod (role: db-operator), staging (role: db-admin)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Group: "frontend-engineers"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Members: diana, erin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Namespaces: staging (role: db-reader)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Group: "ci-bots"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Members: github-actions-bot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Namespaces: ci (role: db-admin)</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-full-permission-matrix">The Full Permission Matrix<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#the-full-permission-matrix" class="hash-link" aria-label="Enlace directo al The Full Permission Matrix" title="Enlace directo al The Full Permission Matrix" translate="no">​</a></h2>
<p>Here's every permission in the system, organized by resource type:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="databases">Databases<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#databases" class="hash-link" aria-label="Enlace directo al Databases" title="Enlace directo al Databases" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>database:create_in_namespace</code></td><td>Create new databases</td></tr><tr><td><code>database:view_in_namespace</code></td><td>See database details and connection info</td></tr><tr><td><code>database:update_in_namespace</code></td><td>Modify database configuration</td></tr><tr><td><code>database:delete_in_namespace</code></td><td>Delete databases</td></tr><tr><td><code>metrics:view_in_database</code></td><td>See Prometheus metrics and charts</td></tr><tr><td><code>log:view_in_database</code></td><td>Access database logs</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="backups">Backups<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#backups" class="hash-link" aria-label="Enlace directo al Backups" title="Enlace directo al Backups" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>backup:create_in_database</code></td><td>Trigger manual backups</td></tr><tr><td><code>backup:view_in_database</code></td><td>See backup history</td></tr><tr><td><code>backup:restore_in_database</code></td><td>Restore from backup (including PITR)</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maintenance-windows">Maintenance Windows<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#maintenance-windows" class="hash-link" aria-label="Enlace directo al Maintenance Windows" title="Enlace directo al Maintenance Windows" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>maintenance_window:view_in_database</code></td><td>See scheduled maintenance</td></tr><tr><td><code>maintenance_window:create_in_database</code></td><td>Schedule maintenance windows</td></tr><tr><td><code>maintenance_window:update_in_database</code></td><td>Modify existing windows</td></tr><tr><td><code>maintenance_window:delete_in_database</code></td><td>Cancel scheduled maintenance</td></tr><tr><td><code>maintenance_window:change_scheduled_date</code></td><td>Reschedule maintenance</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="alert-rules">Alert Rules<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#alert-rules" class="hash-link" aria-label="Enlace directo al Alert Rules" title="Enlace directo al Alert Rules" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>alert_rule:view_in_database</code></td><td>See alert configuration</td></tr><tr><td><code>alert_rule:create_in_database</code></td><td>Create new alert rules</td></tr><tr><td><code>alert_rule:update_in_database</code></td><td>Modify alert rules</td></tr><tr><td><code>alert_rule:delete_in_database</code></td><td>Remove alert rules</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tunnels">Tunnels<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#tunnels" class="hash-link" aria-label="Enlace directo al Tunnels" title="Enlace directo al Tunnels" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>tunnel:view_in_namespace</code></td><td>See tunnel details</td></tr><tr><td><code>tunnel:create_in_namespace</code></td><td>Create tunnels</td></tr><tr><td><code>tunnel:update_in_namespace</code></td><td>Modify tunnel configuration</td></tr><tr><td><code>tunnel:delete_in_namespace</code></td><td>Delete tunnels</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ssh-keys">SSH Keys<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#ssh-keys" class="hash-link" aria-label="Enlace directo al SSH Keys" title="Enlace directo al SSH Keys" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>sshkey:create_in_organization</code></td><td>Add SSH keys</td></tr><tr><td><code>sshkey:view_in_organization</code></td><td>List SSH keys</td></tr><tr><td><code>sshkey:update_in_organization</code></td><td>Modify SSH keys</td></tr><tr><td><code>sshkey:delete_in_organization</code></td><td>Remove SSH keys</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ip-allowlists">IP Allowlists<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#ip-allowlists" class="hash-link" aria-label="Enlace directo al IP Allowlists" title="Enlace directo al IP Allowlists" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>ip:create_in_namespace</code></td><td>Add IP allowlist entries</td></tr><tr><td><code>ip:view_in_namespace</code></td><td>See IP allowlists</td></tr><tr><td><code>ip:update_in_namespace</code></td><td>Modify allowlist entries</td></tr><tr><td><code>ip:delete_in_namespace</code></td><td>Remove allowlist entries</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tailscale">Tailscale<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#tailscale" class="hash-link" aria-label="Enlace directo al Tailscale" title="Enlace directo al Tailscale" translate="no">​</a></h3>
<table><thead><tr><th>Permission</th><th>What it allows</th></tr></thead><tbody><tr><td><code>tailscale:view_in_organization</code></td><td>See Tailscale configurations</td></tr><tr><td><code>tailscale:create_in_organization</code></td><td>Add Tailscale configs</td></tr><tr><td><code>tailscale:delete_in_organization</code></td><td>Remove Tailscale configs</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-real-scenario-fintech-startup">A Real Scenario: Fintech Startup<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#a-real-scenario-fintech-startup" class="hash-link" aria-label="Enlace directo al A Real Scenario: Fintech Startup" title="Enlace directo al A Real Scenario: Fintech Startup" translate="no">​</a></h2>
<p>You're building a fintech product. Here's how you'd structure Filess access:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Organization: acme-fintech</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Namespaces:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - prod       (Production databases)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - staging    (Staging databases)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - dev        (Development databases)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - ci         (CI ephemeral databases)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Groups:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - sre-team</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      prod: db-admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      staging: db-admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      dev: db-admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ci: db-admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - backend-team</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      prod: db-reader          ← Can see metrics, not modify</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      staging: db-operator     ← Can manage backups, not delete</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      dev: db-admin            ← Full control</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ci: db-admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - auditors</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      prod: db-reader          ← Read-only, can see audit logs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      staging: (no access)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      dev: (no access)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - github-actions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ci: db-admin             ← Create/delete ephemeral DBs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      staging: db-operator     ← Run migrations on staging</span><br></span></code></pre></div></div>
<p>A new backend engineer joins → add to <code>backend-team</code>. They immediately have the right access to every environment.</p>
<p>A compliance audit starts → add the auditor to <code>auditors</code>. They can see production metrics and logs without being able to modify anything.</p>
<p>A contractor leaves → remove from their group. All access revoked instantly, no password rotation needed.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="audit-logs">Audit Logs<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#audit-logs" class="hash-link" aria-label="Enlace directo al Audit Logs" title="Enlace directo al Audit Logs" translate="no">​</a></h2>
<p>Every administrative action is logged:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">2026-04-01 09:14 UTC  alice@acme.com  created database "payments-prod"  namespace=prod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-04-01 09:45 UTC  alice@acme.com  created backup  database="payments-prod"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-04-02 14:22 UTC  bob@acme.com    updated alert rule "High CPU"  database="payments-prod"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-04-03 03:17 UTC  github-actions  created database "pr-452-test"  namespace=ci</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2026-04-03 03:31 UTC  github-actions  deleted database "pr-452-test"  namespace=ci</span><br></span></code></pre></div></div>
<p>The audit log is viewable by anyone with <code>audit_log:view_in_organization</code> permission. Export it for compliance purposes.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-security-model-under-the-hood">The Security Model Under the Hood<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#the-security-model-under-the-hood" class="hash-link" aria-label="Enlace directo al The Security Model Under the Hood" title="Enlace directo al The Security Model Under the Hood" translate="no">​</a></h2>
<p>Permission checks happen server-side on every API request. The middleware:</p>
<ol>
<li class="">Extracts the authenticated user from the session or JWT token.</li>
<li class="">Determines the target resource and what action is being performed.</li>
<li class="">Looks up the user's group memberships.</li>
<li class="">For each group, checks if the group has a role assigned to the relevant namespace.</li>
<li class="">Checks if that role includes the required permission.</li>
<li class="">If any path returns <code>true</code>, the request proceeds. Otherwise, <code>403 Forbidden</code>.</li>
</ol>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// From the codebase — every protected controller wraps this check:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doesUserHavePermission</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  req</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ActionTypes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DATABASE_DELETE_IN_NAMESPACE</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> organizationId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> org</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> namespaceId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">FilessError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">You do not have permission to delete this database</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">403</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>There's no way to bypass this check by passing different parameters in the request body — the resource ownership is always verified independently.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="starting-simple">Starting Simple<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#starting-simple" class="hash-link" aria-label="Enlace directo al Starting Simple" title="Enlace directo al Starting Simple" translate="no">​</a></h2>
<p>You don't have to use all of this on day one. When you're a solo developer:</p>
<ul>
<li class="">You have one organization.</li>
<li class="">You have one namespace.</li>
<li class="">You're the owner — you have all permissions.</li>
</ul>
<p>You can add team members, create namespaces, define roles, and build groups incrementally as your team grows. The system scales with you rather than forcing you to over-engineer from the start.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's Next<a href="https://your-docusaurus-site.example.com/es/blog/teams-rbac-organizations-namespaces#whats-next" class="hash-link" aria-label="Enlace directo al What's Next" title="Enlace directo al What's Next" translate="no">​</a></h2>
<p>The RBAC system is actively being extended. On the roadmap:</p>
<ul>
<li class="">Time-limited group memberships (perfect for contractors).</li>
<li class="">Per-database access grants (in addition to per-namespace).</li>
<li class="">API token scoping — limit a token to specific namespaces or operations.</li>
</ul>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Invite your team to Filess →</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="teams" term="teams"/>
        <category label="rbac" term="rbac"/>
        <category label="organizations" term="organizations"/>
        <category label="security" term="security"/>
        <category label="devops" term="devops"/>
        <category label="multi-tenancy" term="multi-tenancy"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Tunnels as a Service: We Built a Managed ngrok Alternative on SSH]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels"/>
        <updated>2026-04-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You're building a Stripe webhook handler. Your local dev server is running on port 3000. Stripe needs a public URL to send events to. You do what every developer has done before: open a terminal and type ngrok http 3000.]]></summary>
        <content type="html"><![CDATA[<p>You're building a Stripe webhook handler. Your local dev server is running on port 3000. Stripe needs a public URL to send events to. You do what every developer has done before: open a terminal and type <code>ngrok http 3000</code>.</p>
<p>It works. For a while.</p>
<p>Then you hit the rate limit. Or the random subdomain changes every restart. Or you need to whitelist a specific IP and ngrok's plan doesn't cover it. Or your company's security policy blocks third-party tunneling software.</p>
<p>At Filess, we built our own managed tunnel infrastructure, and we're making it available as part of the platform. Here's the full technical breakdown of how it works.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-architecture-ssh-reverse-tunnels">The Architecture: SSH Reverse Tunnels<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#the-architecture-ssh-reverse-tunnels" class="hash-link" aria-label="Enlace directo al The Architecture: SSH Reverse Tunnels" title="Enlace directo al The Architecture: SSH Reverse Tunnels" translate="no">​</a></h2>
<p>The core mechanism is the classic <strong>SSH reverse tunnel</strong> (<code>-R</code> flag). When you connect, your machine dials outward through SSH to our tunnel server, and the server opens a port on its side that forwards all incoming traffic back to you through the open SSH connection.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Internet → Filess Tunnel Server → SSH connection → Your localhost:3000</span><br></span></code></pre></div></div>
<p>No firewall rules to open. No router config. No public IP required. The only prerequisite is that your machine can make an outbound TCP connection on port 22222.</p>
<p>Here's the raw SSH command (we also have a CLI that wraps this):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ssh -R filess-tunnel-hostname:80:localhost:3000 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    tunnel@tunnel.eu.filess.io \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    -p 22222 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    -i ~/.ssh/id_rsa \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    -N</span><br></span></code></pre></div></div>
<p>Your local port 3000 is now reachable at <code>https://filess-tunnel-hostname.tunnel.eu.filess.io</code>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-makes-it-different-from-a-simple-ssh--r">What Makes It Different from a Simple SSH -R<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#what-makes-it-different-from-a-simple-ssh--r" class="hash-link" aria-label="Enlace directo al What Makes It Different from a Simple SSH -R" title="Enlace directo al What Makes It Different from a Simple SSH -R" translate="no">​</a></h2>
<p>Running your own reverse tunnel on a VPS is straightforward, but productionizing it is a different story. Here's what we built on top:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tls-certificates--automatic-zero-config">TLS Certificates — Automatic, Zero Config<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#tls-certificates--automatic-zero-config" class="hash-link" aria-label="Enlace directo al TLS Certificates — Automatic, Zero Config" title="Enlace directo al TLS Certificates — Automatic, Zero Config" translate="no">​</a></h3>
<p>Every tunnel gets a unique hostname and a TLS certificate provisioned automatically via Let's Encrypt. No self-signed certs. No "your connection is not secure" warnings.</p>
<p>The certificate lifecycle is tracked in our database:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">TunnelCertificate {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  status: pending | obtaining | valid | expired | failed</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  domain: "abc123.tunnel.eu.filess.io"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  issuer: "Let's Encrypt"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  expiresAt: 2026-07-03T00:00:00Z</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  obtainedAt: 2026-04-03T12:00:00Z</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>When a certificate nears expiration, our job scheduler picks it up and renews it. You never think about this.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="request-observability">Request Observability<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#request-observability" class="hash-link" aria-label="Enlace directo al Request Observability" title="Enlace directo al Request Observability" translate="no">​</a></h3>
<p>Every HTTP request that flows through your tunnel is logged:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GET /webhooks/stripe 200 47ms 1.2kb from 54.187.174.169</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">POST /api/callback  201 12ms 0.4kb from 185.93.54.20</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">GET /health         200  3ms  0.1kb from 10.0.0.1</span><br></span></code></pre></div></div>
<p>The dashboard shows:</p>
<ul>
<li class=""><strong>Total requests</strong> in the last 24h</li>
<li class=""><strong>Average response time</strong></li>
<li class=""><strong>Status code distribution</strong> (2xx, 4xx, 5xx)</li>
<li class=""><strong>Bandwidth transferred</strong></li>
<li class=""><strong>Top client IPs</strong></li>
</ul>
<p>This is valuable during development. Instead of sprinkling <code>console.log</code> statements and squinting at terminal output, you see exactly what's hitting your tunnel in a clean UI.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="connection-events">Connection Events<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#connection-events" class="hash-link" aria-label="Enlace directo al Connection Events" title="Enlace directo al Connection Events" translate="no">​</a></h3>
<p>Every time a client connects or disconnects from the tunnel via SSH, the event is recorded with timestamp, client IP, and auth method used. If your tunnel shows unexpected connection attempts from unknown IPs, you'll know.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="webhook-delivery">Webhook Delivery<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#webhook-delivery" class="hash-link" aria-label="Enlace directo al Webhook Delivery" title="Enlace directo al Webhook Delivery" translate="no">​</a></h3>
<p>You can configure webhooks on your tunnel to get notified about connection events. Useful if you're building automation: start your dev server automatically when someone dials into the tunnel, for example.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="security-controls">Security Controls<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#security-controls" class="hash-link" aria-label="Enlace directo al Security Controls" title="Enlace directo al Security Controls" translate="no">​</a></h2>
<p>The default configuration is secure. But you can tighten it further:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ip-allowlists">IP Allowlists<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#ip-allowlists" class="hash-link" aria-label="Enlace directo al IP Allowlists" title="Enlace directo al IP Allowlists" translate="no">​</a></h3>
<p>Two independent allowlists:</p>
<ol>
<li class=""><strong><code>sshIPWhitelist</code></strong>: Controls who can <em>connect</em> to your tunnel via SSH. Lock it down to your office IP range.</li>
<li class=""><strong><code>ingressIPWhitelist</code></strong>: Controls who can <em>send HTTP traffic</em> through your tunnel. Lock it to Stripe's IP ranges if that's all you need.</li>
</ol>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"sshIPWhitelist"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"203.0.113.42/32"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"ingressIPWhitelist"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"3.18.12.63/32"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"3.130.192.231/32"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"13.235.14.237/32"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="auth-methods">Auth Methods<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#auth-methods" class="hash-link" aria-label="Enlace directo al Auth Methods" title="Enlace directo al Auth Methods" translate="no">​</a></h3>
<p>Three modes:</p>
<ul>
<li class=""><strong><code>key</code></strong>: SSH key only. No passwords. Recommended.</li>
<li class=""><strong><code>token</code></strong>: Temporary password (4-hour TTL, bcrypt-hashed in storage). Useful for CI runners where you can't manage SSH keys.</li>
<li class=""><strong><code>both</code></strong>: Accept either. Flexible for team setups.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="https-only-mode">HTTPS-Only Mode<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#https-only-mode" class="hash-link" aria-label="Enlace directo al HTTPS-Only Mode" title="Enlace directo al HTTPS-Only Mode" translate="no">​</a></h3>
<p>Set <code>httpsOnly: true</code> and the tunnel server will reject plain HTTP connections, redirecting to HTTPS with a 301. Your webhook receiver always gets encrypted traffic.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="live-header-modifications">Live Header Modifications<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#live-header-modifications" class="hash-link" aria-label="Enlace directo al Live Header Modifications" title="Enlace directo al Live Header Modifications" translate="no">​</a></h2>
<p>This one is for power users. You can inject or modify HTTP headers on every request/response flowing through your tunnel, without touching your backend code.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"liveHeaderModifications"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"X-Filess-Tunnel-ID"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"my-dev-tunnel"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"type"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"request"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Access-Control-Allow-Origin"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"type"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"response"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>Use cases:</p>
<ul>
<li class="">Inject an <code>Authorization</code> header so your backend can verify requests came through the tunnel.</li>
<li class="">Add CORS headers without modifying your app code.</li>
<li class="">Stamp a <code>X-Environment: development</code> header to prevent your app from sending real emails when receiving tunneled requests.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cors-preflight-passthrough">CORS Preflight Passthrough<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#cors-preflight-passthrough" class="hash-link" aria-label="Enlace directo al CORS Preflight Passthrough" title="Enlace directo al CORS Preflight Passthrough" translate="no">​</a></h3>
<p>If your frontend calls your tunneled backend directly, enable <code>allowCorsPreflight: true</code>. The tunnel server will handle <code>OPTIONS</code> requests automatically, which is useful when your local server doesn't respond to preflight properly.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-forwardtootherhosts-flag">The <code>forwardToOtherHosts</code> Flag<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#the-forwardtootherhosts-flag" class="hash-link" aria-label="Enlace directo al the-forwardtootherhosts-flag" title="Enlace directo al the-forwardtootherhosts-flag" translate="no">​</a></h2>
<p>By default, the tunnel only forwards to <code>localhost</code>. Enable <code>forwardToOtherHosts: true</code> and you can forward to any host reachable from your machine:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Forward to a database in your local Docker network</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ssh -R tunnel-hostname:5432:db.internal:5432 ...</span><br></span></code></pre></div></div>
<p>This is how you can use a tunnel to give a colleague temporary read access to your local database without setting up a VPN.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-use-cases">Real Use Cases<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#real-use-cases" class="hash-link" aria-label="Enlace directo al Real Use Cases" title="Enlace directo al Real Use Cases" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-receiving-webhooks-during-local-development">1. Receiving Webhooks During Local Development<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#1-receiving-webhooks-during-local-development" class="hash-link" aria-label="Enlace directo al 1. Receiving Webhooks During Local Development" title="Enlace directo al 1. Receiving Webhooks During Local Development" translate="no">​</a></h3>
<p>The canonical use case. Instead of deploying a staging environment every time you need to test a Stripe, GitHub, or Twilio webhook, you point the webhook URL at your tunnel and develop against real events locally.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Start tunnel</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">filess tunnel start --port 3000 --name dev-webhooks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Your webhook URL is now:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># https://abc123.tunnel.eu.filess.io/webhooks/stripe</span><br></span></code></pre></div></div>
<p>Configure the URL once in Stripe's dashboard. Since the hostname is persistent (not random like ngrok's free tier), you don't need to update it every time you restart.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-sharing-a-work-in-progress-ui-with-a-client">2. Sharing a Work-in-Progress UI with a Client<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#2-sharing-a-work-in-progress-ui-with-a-client" class="hash-link" aria-label="Enlace directo al 2. Sharing a Work-in-Progress UI with a Client" title="Enlace directo al 2. Sharing a Work-in-Progress UI with a Client" translate="no">​</a></h3>
<p>You're building a feature. Your client wants to see it before it's deployed. Instead of pushing to staging, run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">filess tunnel start --port 5173 --name client-preview</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># https://abc123.tunnel.eu.filess.io — share this with your client</span><br></span></code></pre></div></div>
<p>The tunnel stays up as long as your dev server runs. The client sees live changes as you code.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-testing-mobile-apps-against-a-local-api">3. Testing Mobile Apps Against a Local API<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#3-testing-mobile-apps-against-a-local-api" class="hash-link" aria-label="Enlace directo al 3. Testing Mobile Apps Against a Local API" title="Enlace directo al 3. Testing Mobile Apps Against a Local API" translate="no">​</a></h3>
<p>Your React Native app needs to hit your API. You can't use <code>localhost</code> from a physical device. Point the app at your tunnel URL, and all traffic flows through to your local machine.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-cicd-smoke-tests-against-a-local-database">4. CI/CD Smoke Tests Against a Local Database<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#4-cicd-smoke-tests-against-a-local-database" class="hash-link" aria-label="Enlace directo al 4. CI/CD Smoke Tests Against a Local Database" title="Enlace directo al 4. CI/CD Smoke Tests Against a Local Database" translate="no">​</a></h3>
<p>Some integration tests need a real database. Instead of spinning up a cloud database for every test run, you keep a local database running and expose it through a tunnel for your CI pipeline to hit.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-tunnels-fit-into-filess-organizations">How Tunnels Fit Into Filess Organizations<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#how-tunnels-fit-into-filess-organizations" class="hash-link" aria-label="Enlace directo al How Tunnels Fit Into Filess Organizations" title="Enlace directo al How Tunnels Fit Into Filess Organizations" translate="no">​</a></h2>
<p>Tunnels are first-class resources in the Filess data model. They live inside a <strong>Namespace</strong> (within an <strong>Organization</strong>), which means:</p>
<ul>
<li class="">Multiple team members can have tunnel access via RBAC.</li>
<li class="">Audit logs capture who created, modified, or deleted a tunnel.</li>
<li class="">Billing is per-tunnel, tracked via Stripe subscriptions.</li>
<li class="">Tunnels can be created, listed, and deleted via the REST API — automatable from scripts or CI.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create a tunnel via API</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST https://api.filess.io/v1/organizations/my-org/namespaces/dev/tunnels \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Authorization: Bearer $FILESS_TOKEN" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -d '{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "name": "webhook-receiver",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "regionId": 1,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "config": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "httpsOnly": true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "ingressIPWhitelist": ["3.18.12.63/32"]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }'</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-infrastructure-behind-it">The Infrastructure Behind It<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#the-infrastructure-behind-it" class="hash-link" aria-label="Enlace directo al The Infrastructure Behind It" title="Enlace directo al The Infrastructure Behind It" translate="no">​</a></h2>
<p>Each region runs one or more <strong>Tunnel Endpoints</strong> — servers that handle SSH connections and proxy HTTP/HTTPS traffic. The endpoint schema:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">TunnelEndpoint {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  domain:    "tunnel.eu.filess.io"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  sshHost:   "ssh.eu.filess.io"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  sshPort:   22222</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  httpPort:  28080</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  httpsPort: 28443</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>SSH runs on a non-standard port (22222) to avoid collisions with system SSH. The tunnel server manages the mapping from <code>{hostname}.{domain}</code> to the corresponding SSH connection.</p>
<p>When you create a tunnel via the API, the system:</p>
<ol>
<li class="">Generates a random 16-character hex hostname.</li>
<li class="">Finds an active endpoint in the requested region.</li>
<li class="">Records the tunnel in the database.</li>
<li class="">Provisions a TLS certificate.</li>
<li class="">Returns the full tunnel URL.</li>
</ol>
<p>The hostname is permanent for the lifetime of the tunnel. Delete the tunnel, the hostname is released.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it">Try It<a href="https://your-docusaurus-site.example.com/es/blog/tunnels-as-a-service-ssh-reverse-tunnels#try-it" class="hash-link" aria-label="Enlace directo al Try It" title="Enlace directo al Try It" translate="no">​</a></h2>
<p>Tunnels are available to all Filess users. Head to the dashboard, create a namespace, and spin up your first tunnel in under a minute.</p>
<p>If you're building something where persistent, observable, secure tunnels would help — local development, webhook testing, client previews, or team demos — give it a shot.</p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Get started with Filess Tunnels →</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="tunnels" term="tunnels"/>
        <category label="ssh" term="ssh"/>
        <category label="networking" term="networking"/>
        <category label="devops" term="devops"/>
        <category label="webhooks" term="webhooks"/>
        <category label="indie-dev" term="indie-dev"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Enterprise-Grade Database Monitoring: Percona Monitoring and Management in FILESS]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management"/>
        <updated>2025-01-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Your database is running. But is it really running well?]]></summary>
        <content type="html"><![CDATA[<p>Your database is running. But is it <em>really</em> running well?</p>
<p>You check your application logs. Everything seems fine. Your users aren't complaining. But deep down, you know you're flying blind. You have no idea if:</p>
<ul>
<li class="">Your queries are getting slower over time</li>
<li class="">Your connection pool is about to hit the limit</li>
<li class="">Your disk I/O is becoming a bottleneck</li>
<li class="">Your replication lag is growing</li>
</ul>
<p>In the old days, you'd cobble together a monitoring solution: install Prometheus, configure Grafana, write custom exporters, set up alerting rules. Weeks of work, and you'd still miss critical metrics.</p>
<p><strong>Filess.io</strong> solves this by providing <strong>Percona Monitoring and Management (PMM)</strong> out of the box on all Dedicated Runtime databases.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-building-your-own-monitoring-stack">The Pain: Building Your Own Monitoring Stack<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#the-pain-building-your-own-monitoring-stack" class="hash-link" aria-label="Enlace directo al The Pain: Building Your Own Monitoring Stack" title="Enlace directo al The Pain: Building Your Own Monitoring Stack" translate="no">​</a></h2>
<p>Setting up comprehensive database monitoring from scratch is a nightmare:</p>
<ol>
<li class=""><strong>Install Prometheus</strong>: Set up the time-series database, configure retention, manage storage.</li>
<li class=""><strong>Deploy Exporters</strong>: Install <code>mysqld_exporter</code>, configure authentication, expose metrics endpoints.</li>
<li class=""><strong>Build Grafana Dashboards</strong>: Create dashboards from scratch, figure out which metrics matter, design visualizations.</li>
<li class=""><strong>Configure Alerting</strong>: Write PromQL queries, set thresholds, integrate with PagerDuty/Slack.</li>
<li class=""><strong>Maintain Everything</strong>: Keep exporters updated, fix broken dashboards, tune retention policies.</li>
</ol>
<p>And even after all that work, you're still missing enterprise features like:</p>
<ul>
<li class="">Query Analytics to identify slow queries</li>
<li class="">Database advisors that suggest optimizations</li>
<li class="">Historical performance trends</li>
<li class="">Security auditing capabilities</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-percona-monitoring-and-management-built-in">The Solution: Percona Monitoring and Management Built-In<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#the-solution-percona-monitoring-and-management-built-in" class="hash-link" aria-label="Enlace directo al The Solution: Percona Monitoring and Management Built-In" title="Enlace directo al The Solution: Percona Monitoring and Management Built-In" translate="no">​</a></h2>
<p><strong>Percona Monitoring and Management (PMM)</strong> is an open-source platform for managing and monitoring MySQL, MariaDB, PostgreSQL, and MongoDB performance. It's the same tool used by companies like GitHub, Slack, and Etsy to monitor their databases.</p>
<p>On Filess.io, PMM is <strong>pre-configured and ready to use</strong> on every Dedicated Runtime database.</p>
<img src="https://your-docusaurus-site.example.com/es/assets/images/pmm-dashboard-8d95e5be0319ae3eac68f43a4148b1b9.png" width="600" alt="Percona Monitoring and Management Dashboard">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-get-out-of-the-box">What You Get Out of the Box<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#what-you-get-out-of-the-box" class="hash-link" aria-label="Enlace directo al What You Get Out of the Box" title="Enlace directo al What You Get Out of the Box" translate="no">​</a></h3>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-column-increasing" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><path d="M5 21v-6"></path><path d="M12 21V9"></path><path d="M19 21V3"></path></svg> <strong>Query Analytics</strong>: See exactly which queries are slow, how often they run, and where they're spending time.</p>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#3b82f6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-database" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M3 5V19A9 3 0 0 0 21 19V5"></path><path d="M3 12A9 3 0 0 0 21 12"></path></svg> <strong>Performance Metrics</strong>: Real-time monitoring of connections, queries per second, replication lag, buffer pool usage, and more.</p>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#3b82f6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-target" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="6"></circle><circle cx="12" cy="12" r="2"></circle></svg> <strong>Database Advisors</strong>: Automated recommendations for query optimization, index creation, and configuration tuning.</p>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"></path></svg> <strong>Security Monitoring</strong>: Track authentication failures, privilege escalations, and suspicious activity.</p>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clock" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><path d="M12 6v6l4 2"></path><circle cx="12" cy="12" r="10"></circle></svg> <strong>Historical Data</strong>: Keep months of performance data for capacity planning and trend analysis.</p>
<p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trending-up" aria-hidden="true" style="display:inline-block;vertical-align:middle;margin-right:4px"><path d="M16 7h6v6"></path><path d="m22 7-8.5 8.5-5-5L2 17"></path></svg> <strong>Custom Dashboards</strong>: Pre-built dashboards for MySQL/MariaDB with the most important metrics at a glance.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works-in-filess">How It Works in FILESS<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#how-it-works-in-filess" class="hash-link" aria-label="Enlace directo al How It Works in FILESS" title="Enlace directo al How It Works in FILESS" translate="no">​</a></h2>
<p>When you deploy a database on Filess.io Dedicated Runtime:</p>
<ol>
<li class=""><strong>PMM Server is automatically deployed</strong> alongside your database cluster</li>
<li class=""><strong>PMM Client agents are installed</strong> on each database node</li>
<li class=""><strong>Metrics collection starts immediately</strong> - no configuration needed</li>
<li class=""><strong>Dashboards are pre-configured</strong> with best-practice visualizations</li>
</ol>
<p>You don't need to:</p>
<ul>
<li class="">Install any software</li>
<li class="">Configure exporters</li>
<li class="">Write PromQL queries</li>
<li class="">Build dashboards</li>
<li class="">Set up alerting infrastructure</li>
</ul>
<p>It just works.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="key-features-of-pmm-in-filess">Key Features of PMM in FILESS<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#key-features-of-pmm-in-filess" class="hash-link" aria-label="Enlace directo al Key Features of PMM in FILESS" title="Enlace directo al Key Features of PMM in FILESS" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="query-analytics-dashboard">Query Analytics Dashboard<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#query-analytics-dashboard" class="hash-link" aria-label="Enlace directo al Query Analytics Dashboard" title="Enlace directo al Query Analytics Dashboard" translate="no">​</a></h3>
<p>Identify performance bottlenecks at a glance:</p>
<ul>
<li class=""><strong>Top slow queries</strong>: See which queries are taking the most time</li>
<li class=""><strong>Query patterns</strong>: Group similar queries to find optimization opportunities</li>
<li class=""><strong>Execution plans</strong>: Understand how queries are being executed</li>
<li class=""><strong>Index recommendations</strong>: Get suggestions for missing indexes</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-monitoring">Performance Monitoring<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#performance-monitoring" class="hash-link" aria-label="Enlace directo al Performance Monitoring" title="Enlace directo al Performance Monitoring" translate="no">​</a></h3>
<p>Monitor all critical database metrics:</p>
<ul>
<li class=""><strong>Connection metrics</strong>: Active connections, connection errors, max connections</li>
<li class=""><strong>Query performance</strong>: Queries per second, slow queries, query response times</li>
<li class=""><strong>Resource usage</strong>: CPU, memory, disk I/O, network I/O</li>
<li class=""><strong>InnoDB metrics</strong>: Buffer pool usage, read/write operations, lock waits</li>
<li class=""><strong>Replication</strong>: Replication lag, replication status, binlog position</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="database-advisors">Database Advisors<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#database-advisors" class="hash-link" aria-label="Enlace directo al Database Advisors" title="Enlace directo al Database Advisors" translate="no">​</a></h3>
<p>Get automated recommendations for:</p>
<ul>
<li class=""><strong>Query optimization</strong>: Identify queries that could benefit from indexes</li>
<li class=""><strong>Configuration tuning</strong>: Suggestions for <code>my.cnf</code> optimizations</li>
<li class=""><strong>Index analysis</strong>: Find missing or unused indexes</li>
<li class=""><strong>Table optimization</strong>: Recommendations for table maintenance</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="alerting">Alerting<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#alerting" class="hash-link" aria-label="Enlace directo al Alerting" title="Enlace directo al Alerting" translate="no">​</a></h3>
<p>Set up alerts for:</p>
<ul>
<li class="">High connection count</li>
<li class="">Slow query rate</li>
<li class="">Replication lag</li>
<li class="">Disk space usage</li>
<li class="">Memory pressure</li>
<li class="">CPU utilization</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-world-example-the-slow-query-mystery">Real-World Example: The Slow Query Mystery<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#real-world-example-the-slow-query-mystery" class="hash-link" aria-label="Enlace directo al Real-World Example: The Slow Query Mystery" title="Enlace directo al Real-World Example: The Slow Query Mystery" translate="no">​</a></h2>
<p>Imagine your <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a> starts experiencing intermittent slowdowns. Users report pages taking 5+ seconds to load.</p>
<p><strong>Without PMM</strong>: You'd spend hours digging through logs, running <code>SHOW PROCESSLIST</code>, trying to correlate application metrics with database performance. You might never find the root cause.</p>
<p><strong>With PMM in FILESS</strong>:</p>
<ol>
<li class="">Open the PMM dashboard (accessible from your Filess.io console)</li>
<li class="">Navigate to Query Analytics</li>
<li class="">See immediately that a specific <code>SELECT</code> query is taking 3+ seconds</li>
<li class="">Click on the query to see its execution plan</li>
<li class="">PMM Advisor suggests adding an index on <code>customer_id</code></li>
<li class="">You add the index, and the problem is solved</li>
</ol>
<p>All in under 10 minutes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-percona-monitoring-and-management">Why Percona Monitoring and Management?<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#why-percona-monitoring-and-management" class="hash-link" aria-label="Enlace directo al Why Percona Monitoring and Management?" title="Enlace directo al Why Percona Monitoring and Management?" translate="no">​</a></h2>
<p>PMM is the industry standard for database monitoring because:</p>
<ul>
<li class=""><strong>Open Source</strong>: No vendor lock-in, fully auditable</li>
<li class=""><strong>Enterprise-Grade</strong>: Used by companies managing thousands of databases</li>
<li class=""><strong>Comprehensive</strong>: Covers all aspects of database performance</li>
<li class=""><strong>Active Development</strong>: Regular updates with new features and improvements</li>
<li class=""><strong>Community Support</strong>: Large community of users and contributors</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="best-practices-for-database-monitoring">Best Practices for Database Monitoring<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#best-practices-for-database-monitoring" class="hash-link" aria-label="Enlace directo al Best Practices for Database Monitoring" title="Enlace directo al Best Practices for Database Monitoring" translate="no">​</a></h2>
<p>With PMM in FILESS, you can:</p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Monitor proactively</strong>: Set up alerts before issues impact users</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Optimize continuously</strong>: Use Query Analytics to find slow queries regularly</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Plan capacity</strong>: Use historical data to predict when you'll need to scale</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Troubleshoot quickly</strong>: When issues arise, you have all the data you need</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Document performance</strong>: Use dashboards to communicate database health to stakeholders</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-started-today">Get Started Today<a href="https://your-docusaurus-site.example.com/es/blog/percona-monitoring-management#get-started-today" class="hash-link" aria-label="Enlace directo al Get Started Today" title="Enlace directo al Get Started Today" translate="no">​</a></h2>
<p>Every Dedicated Runtime database on Filess.io includes Percona Monitoring and Management at no additional cost. No setup, no configuration, no maintenance.</p>
<p><strong>Stop flying blind. Start monitoring like the pros.</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Deploy a Database with Built-in PMM on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="monitoring" term="monitoring"/>
        <category label="observability" term="observability"/>
        <category label="pmm" term="pmm"/>
        <category label="database-performance" term="database-performance"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[The Secret Tunnel: Accessing Production DBs Without Exposing Ports]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access"/>
        <updated>2025-01-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You're debugging a critical bug in the Example App. You need to see the raw data in the sale table to understand why the totals aren't adding up.]]></summary>
        <content type="html"><![CDATA[<p>You're debugging a critical bug in the <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a>. You need to see the raw data in the <code>sale</code> table to understand why the totals aren't adding up.</p>
<p>You fire up TablePlus or DBeaver, but you hit a wall. The database is (rightfully) in a private network.</p>
<p>How do you get in?</p>
<p>Do you temporarily open port 3306 to the world? <strong>Dangerous.</strong>
Do you deploy a VPN server just for this? <strong>Expensive.</strong></p>
<p>The answer is an <strong>SSH Tunnel</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-the-bastion-host-maintenance">The Pain: The "Bastion Host" Maintenance<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#the-pain-the-bastion-host-maintenance" class="hash-link" aria-label="Enlace directo al The Pain: The &quot;Bastion Host&quot; Maintenance" title="Enlace directo al The Pain: The &quot;Bastion Host&quot; Maintenance" translate="no">​</a></h2>
<p>Traditionally, to access a private database, you'd set up a "Jump Box" or "Bastion Host"—a tiny Linux server that sits on the edge of your network.</p>
<p>You'd have to:</p>
<ol>
<li class="">Provision an EC2/Droplet.</li>
<li class="">Harden the OS (updates, fail2ban).</li>
<li class="">Manage SSH keys for every developer.</li>
<li class="">Run a command like:<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ssh -L 3306:private-db-host:3306 user@bastion-host</span><br></span></code></pre></div></div>
</li>
</ol>
<p>It's another server to pay for, patch, and worry about.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-built-in-ssh-gateways">The Solution: Built-in SSH Gateways<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#the-solution-built-in-ssh-gateways" class="hash-link" aria-label="Enlace directo al The Solution: Built-in SSH Gateways" title="Enlace directo al The Solution: Built-in SSH Gateways" translate="no">​</a></h2>
<p>Filess.io gives you a managed Bastion Host for free with every database.</p>
<ol>
<li class="">Go to your database <strong>Settings</strong>.</li>
<li class="">Add your <strong>Public SSH Key</strong>.</li>
<li class="">Copy the connection string.</li>
</ol>
<img src="https://your-docusaurus-site.example.com/es/assets/images/ssh-1-ec6d7895173041f17f474e7a195301e8.png" width="600" alt="Configuración de SSH Tunnel en Filess">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="connecting-with-tableplus--dbeaver">Connecting with TablePlus / DBeaver<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#connecting-with-tableplus--dbeaver" class="hash-link" aria-label="Enlace directo al Connecting with TablePlus / DBeaver" title="Enlace directo al Connecting with TablePlus / DBeaver" translate="no">​</a></h3>
<p>You don't even need the command line. Most SQL clients support SSH tunneling natively.</p>
<ol>
<li class=""><strong>Host</strong>: <code>127.0.0.1</code></li>
<li class=""><strong>Port</strong>: <code>3306</code></li>
<li class=""><strong>SSH Host</strong>: <code>ssh.filess.io</code></li>
<li class=""><strong>SSH User</strong>: <code>filess</code></li>
<li class=""><strong>SSH Key</strong>: Select your private key file.</li>
</ol>
<p>Click <strong>Connect</strong>, and you're in. It feels like the database is running on your laptop, but all traffic is securely encrypted through the tunnel.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-command-line-way">The Command Line Way<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#the-command-line-way" class="hash-link" aria-label="Enlace directo al The Command Line Way" title="Enlace directo al The Command Line Way" translate="no">​</a></h3>
<p>If you prefer the terminal, it's just one command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Forward remote port 3306 to local port 3307</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ssh -N -L 3307:db-endpoint:3306 filess@ssh.filess.io -i ~/.ssh/id_rsa</span><br></span></code></pre></div></div>
<p>Now you can run your app locally against production data (carefully!):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">DATABASE_URL="mysql://user:pass@127.0.0.1:3307/filess_example" npm start</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-its-secure">Why It's Secure<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#why-its-secure" class="hash-link" aria-label="Enlace directo al Why It's Secure" title="Enlace directo al Why It's Secure" translate="no">​</a></h2>
<ul>
<li class=""><strong>Encrypted</strong>: All traffic is wrapped in SSH encryption.</li>
<li class=""><strong>Key-Based</strong>: No passwords to brute force. Only holders of the private key can enter.</li>
<li class=""><strong>No Public Ports</strong>: Your database port <code>3306</code> remains closed to the internet. The only entry point is the hardened SSH gateway.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="security-best-practices">Security Best Practices<a href="https://your-docusaurus-site.example.com/es/blog/ssh-tunneling-secure-access#security-best-practices" class="hash-link" aria-label="Enlace directo al Security Best Practices" title="Enlace directo al Security Best Practices" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Use Passphrases</strong>: Protect your local private SSH keys with a passphrase.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Rotate Keys</strong>: Remove old keys from the Filess dashboard when developers leave.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Read-Only Users</strong>: When debugging, log in with a read-only database user to avoid accidental <code>DELETE</code>s.</li>
</ul>
<p><strong>Get secure access without the hassle.</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Start Your Secure Database on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="security" term="security"/>
        <category label="ssh" term="ssh"/>
        <category label="tunneling" term="tunneling"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Coding from a Coffee Shop? Secure Your Database with Tailscale]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking"/>
        <updated>2025-01-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You're building features for the Example App from your favorite coffee shop. You need to connect to the production database to debug a weird order issue.]]></summary>
        <content type="html"><![CDATA[<p>You're building features for the <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a> from your favorite coffee shop. You need to connect to the production database to debug a weird order issue.</p>
<p>But wait—you're on public Wi-Fi. Your IP address changes every time you reconnect.</p>
<p>Do you open port 3306 to the world? <strong>No.</strong>
Do you constantly update your firewall rules with your new IP? <strong>Tedious.</strong>
Do you set up a complex OpenVPN server? <strong>Overkill.</strong></p>
<p>Enter <strong>Filess.io + Tailscale</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-the-dynamic-ip-dance">The Pain: The "Dynamic IP" Dance<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#the-pain-the-dynamic-ip-dance" class="hash-link" aria-label="Enlace directo al The Pain: The &quot;Dynamic IP&quot; Dance" title="Enlace directo al The Pain: The &quot;Dynamic IP&quot; Dance" translate="no">​</a></h2>
<p>If you want to access a private database securely from a remote location, you typically have two bad options:</p>
<ol>
<li class=""><strong>The "Insecure" Way</strong>: Open the firewall to <code>0.0.0.0/0</code>. Now hackers can brute-force your root password.</li>
<li class=""><strong>The "Annoying" Way</strong>: Log in to your cloud provider console, find your current IP (which changes hourly), add it to the whitelist, and repeat this every time you move.</li>
</ol>
<p>And if you have a team of 10 developers? Good luck managing that whitelist.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-a-private-mesh-network">The Solution: A Private Mesh Network<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#the-solution-a-private-mesh-network" class="hash-link" aria-label="Enlace directo al The Solution: A Private Mesh Network" title="Enlace directo al The Solution: A Private Mesh Network" translate="no">​</a></h2>
<p>With Filess.io's native Tailscale integration, your database joins your private network as if it were a device on your LAN.</p>
<ol>
<li class="">Go to your database <strong>Settings</strong>.</li>
<li class="">Enable <strong>Tailscale</strong>.</li>
<li class="">Authenticate with your Tailscale account.</li>
</ol>
<img src="https://your-docusaurus-site.example.com/es/assets/images/tailscale-1-2caf9740be6277e69049ac35f45c3813.png" width="600" alt="Configuración de Tailscale en Filess">
<p>Your database gets a private IP (e.g., <code>100.x.y.z</code>) that is <strong>only accessible to you and your team</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="connecting-to-example-app">Connecting to Example App<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#connecting-to-example-app" class="hash-link" aria-label="Enlace directo al Connecting to Example App" title="Enlace directo al Connecting to Example App" translate="no">​</a></h3>
<p>Now, from your laptop in the coffee shop:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># 1. Install Tailscale</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">brew install tailscale &amp;&amp; sudo tailscale up</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># 2. Connect securely (Magic!)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mysql -h 100.101.102.103 -u user -p filess_example</span><br></span></code></pre></div></div>
<p>No ports opened to the internet. No firewall rules to update. Just secure, encrypted WireGuard® tunnels.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-developers-love-this">Why Developers Love This<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#why-developers-love-this" class="hash-link" aria-label="Enlace directo al Why Developers Love This" title="Enlace directo al Why Developers Love This" translate="no">​</a></h2>
<ul>
<li class=""><strong>Zero Config VPN</strong>: No certificates to manage, no ports to forward.</li>
<li class=""><strong>Team Access</strong>: Grant access to your database using your existing identity provider (Google, Okta, GitHub).</li>
<li class=""><strong>CI/CD Secure Access</strong>: Let your GitHub Actions runners connect to your DB securely without public exposure.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How It Works<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#how-it-works" class="hash-link" aria-label="Enlace directo al How It Works" title="Enlace directo al How It Works" translate="no">​</a></h2>
<p>Tailscale builds a peer-to-peer mesh network. When you connect to your database:</p>
<ol>
<li class="">Your laptop and the Filess database server exchange keys.</li>
<li class="">They establish a direct, encrypted connection (NAT traversal included).</li>
<li class="">Traffic flows directly between them, not through a central bottleneck.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="secure-your-workflow">Secure Your Workflow<a href="https://your-docusaurus-site.example.com/es/blog/tailscale-private-networking#secure-your-workflow" class="hash-link" aria-label="Enlace directo al Secure Your Workflow" title="Enlace directo al Secure Your Workflow" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Install Tailscale</strong> on your dev machine.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Enable Tailscale</strong> on your Filess database.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Close Public Ports</strong>: Disable public access entirely for maximum security.</li>
</ul>
<p><strong>Work from anywhere, securely.</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Get a Private Database on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="networking" term="networking"/>
        <category label="tailscale" term="tailscale"/>
        <category label="vpn" term="vpn"/>
        <category label="security" term="security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[No More 3 AM Wake-Up Calls: Stress-Free Database Upgrades]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades"/>
        <updated>2025-01-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[It's 2:00 AM. Your alarm goes off.]]></summary>
        <content type="html"><![CDATA[<p>It's 2:00 AM. Your alarm goes off.</p>
<p>Why? Because the <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a> needs more RAM to handle the upcoming holiday traffic, and you have to manually resize the database server during the "low traffic" window.</p>
<p>You groggily open your laptop, SSH in, stop the service, resize the VM, restart the service, and pray it comes back up.</p>
<p>This is the "old way" of operations. It burns out engineers and risks human error.</p>
<p><strong>Filess.io</strong> fixes this with automated Maintenance Windows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-the-manual-upgrade-dance">The Pain: The Manual Upgrade Dance<a href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades#the-pain-the-manual-upgrade-dance" class="hash-link" aria-label="Enlace directo al The Pain: The Manual Upgrade Dance" title="Enlace directo al The Pain: The Manual Upgrade Dance" translate="no">​</a></h2>
<p>Upgrading a database manually is a high-stakes choreography:</p>
<ol>
<li class=""><strong>Announce Downtime</strong>: Tell your users the site will be slow or down.</li>
<li class=""><strong>Snapshot</strong>: Take a backup (just in case).</li>
<li class=""><strong>Stop Traffic</strong>: Put the app in maintenance mode.</li>
<li class=""><strong>Perform Upgrade</strong>: <code>apt-get upgrade</code> or resize the instance.</li>
<li class=""><strong>Restart &amp; Verify</strong>: Check logs, check connections.</li>
<li class=""><strong>Resume Traffic</strong>: Cross your fingers.</li>
</ol>
<p>If anything goes wrong, you're debugging at 3 AM while losing money.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-set-it-and-forget-it">The Solution: Set It and Forget It<a href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades#the-solution-set-it-and-forget-it" class="hash-link" aria-label="Enlace directo al The Solution: Set It and Forget It" title="Enlace directo al The Solution: Set It and Forget It" translate="no">​</a></h2>
<p>With Filess.io, you define <em>when</em> you want changes to happen, and we handle the execution automatically.</p>
<ol>
<li class="">Go to your database <strong>Maintenance</strong> tab.</li>
<li class="">Set your preferred window (e.g., <strong>Sunday at 02:00 UTC</strong>).</li>
<li class="">Request an upgrade (e.g., "Scale to 16GB RAM").</li>
</ol>
<img src="https://your-docusaurus-site.example.com/es/assets/images/maintenance-window-82c82675d18d6ac2c94ce59c8f8664d1.png" width="600" alt="Configuración de Ventana de Mantenimiento en Filess">
<p><strong>That's it.</strong></p>
<p>Filess queues the change. When Sunday at 02:00 rolls around, our orchestration engine:</p>
<ol>
<li class="">Spins up a new replica with the new specs.</li>
<li class="">Syncs data.</li>
<li class="">Performs a seamless failover (often with zero downtime).</li>
<li class="">Decommissions the old node.</li>
</ol>
<p>You wake up on Sunday morning to a more powerful database, without having lifted a finger.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-world-example-the-holiday-rush">Real-World Example: The Holiday Rush<a href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades#real-world-example-the-holiday-rush" class="hash-link" aria-label="Enlace directo al Real-World Example: The Holiday Rush" title="Enlace directo al Real-World Example: The Holiday Rush" translate="no">​</a></h3>
<p>Imagine our <code>example-app</code> is expecting 10x traffic for a flash sale next week.</p>
<p><strong>Without Filess</strong>: You spend the weekend stressing about capacity planning and manual resizing.</p>
<p><strong>With Filess</strong>: You click "Upgrade Plan" on Friday afternoon. You set the maintenance window for Saturday 01:00 AM. You go enjoy your weekend. By the time the sale starts, your database is ready.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-it-matters">Why It Matters<a href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades#why-it-matters" class="hash-link" aria-label="Enlace directo al Why It Matters" title="Enlace directo al Why It Matters" translate="no">​</a></h2>
<ul>
<li class=""><strong>Predictability</strong>: Your team knows exactly when changes happen.</li>
<li class=""><strong>Safety</strong>: Our automated workflows have rollback capabilities built-in.</li>
<li class=""><strong>Sanity</strong>: No more 3 AM alarms for routine tasks.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="best-practices-for-maintenance">Best Practices for Maintenance<a href="https://your-docusaurus-site.example.com/es/blog/maintenance-windows-upgrades#best-practices-for-maintenance" class="hash-link" aria-label="Enlace directo al Best Practices for Maintenance" title="Enlace directo al Best Practices for Maintenance" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Pick Low-Traffic Times</strong>: Use your analytics to find the quietest hour.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Communicate</strong>: Even with zero-downtime upgrades, it's good practice to notify stakeholders.</li>
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Test First</strong>: Apply changes to a staging environment first (easy to clone in Filess!).</li>
</ul>
<p><strong>Stop babysitting your database.</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Automate Your Operations on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="maintenance" term="maintenance"/>
        <category label="upgrades" term="upgrades"/>
        <category label="downtime" term="downtime"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Stop Hackers at the Door: Securing Your E-Commerce DB in 30 Seconds]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/firewall-database-security</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security"/>
        <updated>2025-01-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Your Example App store is growing. You have thousands of customers, which means you have thousands of emails, addresses, and purchase histories.]]></summary>
        <content type="html"><![CDATA[<p>Your <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a> store is growing. You have thousands of customers, which means you have thousands of emails, addresses, and purchase histories.</p>
<p>But there's a problem. Your database port (<code>3306</code>) is open to the entire internet.</p>
<p>Any script kiddie with a port scanner can find your server, start brute-forcing passwords, or exploit a zero-day vulnerability.</p>
<p>You need to lock it down, <strong>now</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-the-iptables-headache">The Pain: The <code>iptables</code> Headache<a href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security#the-pain-the-iptables-headache" class="hash-link" aria-label="Enlace directo al the-pain-the-iptables-headache" title="Enlace directo al the-pain-the-iptables-headache" translate="no">​</a></h2>
<p>Securing a database server manually involves messing with Linux kernel firewall rules (<code>iptables</code> or <code>ufw</code>). It's a rite of passage for sysadmins, but a nightmare for developers.</p>
<p>To allow just your office IP and your app server, you have to SSH in and run commands like this:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Install persistent rules so they survive a reboot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sudo apt install iptables-persistent</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Allow your office IP (hope you don't have a dynamic IP!)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sudo iptables -A INPUT -p tcp -s 79.148.34.11/32 --dport 3306 -j ACCEPT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Allow your app server subnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sudo iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 3306 -j ACCEPT</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># BLOCK EVERYTHING ELSE (Don't lock yourself out of SSH!)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">sudo iptables -A INPUT -p tcp --dport 3306 -j DROP</span><br></span></code></pre></div></div>
<p>One wrong move, and you lock yourself out of your own server. Or worse, you think you blocked everyone, but you didn't.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-filessio-cloud-firewall">The Solution: Filess.io Cloud Firewall<a href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security#the-solution-filessio-cloud-firewall" class="hash-link" aria-label="Enlace directo al The Solution: Filess.io Cloud Firewall" title="Enlace directo al The Solution: Filess.io Cloud Firewall" translate="no">​</a></h2>
<p>With Filess.io, you don't touch the command line. You manage security where it belongs: in your dashboard.</p>
<ol>
<li class="">Go to your database <strong>Settings</strong>.</li>
<li class="">Enable the <strong>Firewall</strong> addon.</li>
<li class="">Add your trusted IPs or CIDR blocks.</li>
</ol>
<img src="https://your-docusaurus-site.example.com/es/assets/images/firewall-1-09500348eac91ca0df5f0ad3b2658a2e.png" width="600" alt="Configuración de Firewall en Filess">
<p><strong>Done.</strong></p>
<p>Our infrastructure instantly propagates these rules to the edge. Any connection attempt from an unauthorized IP is dropped before it even touches your database server.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="protecting-the-example-app">Protecting the Example App<a href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security#protecting-the-example-app" class="hash-link" aria-label="Enlace directo al Protecting the Example App" title="Enlace directo al Protecting the Example App" translate="no">​</a></h3>
<p>For our <code>example-app</code>, we only want two things talking to the database:</p>
<ol>
<li class=""><strong>Our App Server</strong>: <code>10.0.0.0/24</code> (Private Network)</li>
<li class=""><strong>Our Developer VPN</strong>: <code>79.148.34.11/32</code> (For debugging)</li>
</ol>
<p>We add these two rules in Filess, and suddenly, the rest of the internet ceases to exist for our database.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-its-better-than-iptables">Why It's Better Than <code>iptables</code><a href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security#why-its-better-than-iptables" class="hash-link" aria-label="Enlace directo al why-its-better-than-iptables" title="Enlace directo al why-its-better-than-iptables" translate="no">​</a></h2>
<ul>
<li class=""><strong>Zero Risk of Lockout</strong>: You manage rules via our API/UI, not the server's network stack. You can always log in to Filess to fix a mistake.</li>
<li class=""><strong>Instant Updates</strong>: Rules apply in seconds without restarting the database.</li>
<li class=""><strong>DDOS Protection</strong>: By blocking traffic at the infrastructure level, we save your database CPU from having to process handshake attempts from attackers.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="security-checklist-for-your-store">Security Checklist for Your Store<a href="https://your-docusaurus-site.example.com/es/blog/firewall-database-security#security-checklist-for-your-store" class="hash-link" aria-label="Enlace directo al Security Checklist for Your Store" title="Enlace directo al Security Checklist for Your Store" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled="" checked=""> <strong>Enable Firewall</strong>: Whitelist only your app servers.</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <strong>Use SSL/TLS</strong>: Filess enforces this by default.</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <strong>Rotate Credentials</strong>: Use our API to rotate passwords regularly.</li>
</ul>
<p><strong>Don't leave your front door open.</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Secure Your Database on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="security" term="security"/>
        <category label="firewall" term="firewall"/>
        <category label="ip-allowlist" term="ip-allowlist"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Oops, I Deleted Production: Saving Black Friday with 1-Click PITR]]></title>
        <id>https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery</id>
        <link href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery"/>
        <updated>2025-01-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[It's Black Friday. Traffic is peaking on our Example App e-commerce store. You're monitoring the sales dashboard, and everything looks great.]]></summary>
        <content type="html"><![CDATA[<p>It's Black Friday. Traffic is peaking on our <a href="https://github.com/filess-io/example-app" target="_blank" rel="noopener noreferrer" class="">Example App</a> e-commerce store. You're monitoring the sales dashboard, and everything looks great.</p>
<p>Then, disaster strikes.</p>
<p>A developer, intending to clean up some test data, accidentally runs a <code>DELETE</code> command on the production database.</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">DELETE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> sale </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">-- Forgot the WHERE status = 'test' clause!</span><br></span></code></pre></div></div>
<p><strong>Poof.</strong> Hundreds of real customer orders just vanished. The phone starts ringing. The CEO is walking towards your desk.</p>
<p>In the old days, this would be the start of a very long, very bad night. But with <strong>Filess.io</strong>, it's just a 2-minute fix.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-pain-the-manual-recovery-nightmare">The Pain: The Manual Recovery Nightmare<a href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery#the-pain-the-manual-recovery-nightmare" class="hash-link" aria-label="Enlace directo al The Pain: The Manual Recovery Nightmare" title="Enlace directo al The Pain: The Manual Recovery Nightmare" translate="no">​</a></h2>
<p>If you were managing your own database server (the "hard way"), recovering from this would be a panic-inducing ordeal.</p>
<p>First, you'd have to hope you configured binary logs correctly <em>before</em> the incident:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Did you remember to set this?</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">log_bin = /var/log/mysql/mysql-bin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">expire_logs_days = 10</span><br></span></code></pre></div></div>
<p>Then, you'd have to scramble to find your last full backup and start the manual replay process:</p>
<ol>
<li class=""><strong>Find the backup</strong>: <code>ls -l /backups/mariadb/full_backup_*.sql</code></li>
<li class=""><strong>Restore it</strong>: <code>mysql -u root -p &lt; full_backup.sql</code> (This takes time!)</li>
<li class=""><strong>Find the binlog position</strong>: Dig through files to find where the backup ended.</li>
<li class=""><strong>Replay logs</strong>: Carefully construct a <code>mysqlbinlog</code> command to replay everything <em>up to</em> the accident.</li>
</ol>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># One typo here and you corrupt data again</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">mysqlbinlog \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --start-datetime="2025-11-21 14:00:00" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --stop-datetime="2025-11-21 17:32:58" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  /var/log/mysql/mysql-bin.000123 | mysql -u root -p filess_example</span><br></span></code></pre></div></div>
<p>It's slow, error-prone, and terrifying when money is on the line.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-filessio-1-click-time-travel">The Solution: Filess.io 1-Click Time Travel<a href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery#the-solution-filessio-1-click-time-travel" class="hash-link" aria-label="Enlace directo al The Solution: Filess.io 1-Click Time Travel" title="Enlace directo al The Solution: Filess.io 1-Click Time Travel" translate="no">​</a></h2>
<p>With Filess.io, we handle the complexity for you. We automatically take physical backups and stream transaction logs continuously.</p>
<p>To save our Black Friday sales, you simply:</p>
<ol>
<li class="">Go to your database dashboard.</li>
<li class="">Click <strong>"Point-in-Time Recovery"</strong>.</li>
<li class="">Select the exact time <em>before</em> the query ran (e.g., <code>17:32:58</code>).</li>
</ol>
<p><img decoding="async" loading="lazy" alt="PITR Interface" src="https://your-docusaurus-site.example.com/es/assets/images/pitr-en-filess-1-85c6a19483b9ba55621ca5d513d6f530.png" width="3104" height="1826" class="img_ev3q"></p>
<p><strong>That's it.</strong></p>
<p>Filess spins up a <em>new</em> database instance cloned from that exact second. Your original broken database stays there (just in case), and you get a fresh, perfect copy to verify.</p>
<img src="https://your-docusaurus-site.example.com/es/assets/images/pitr-en-filess-2-856f13e405324f610cd40ac46df1a50e.png" width="600" alt="Restaurado satisfactoriamente">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="verifying-the-fix">Verifying the Fix<a href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery#verifying-the-fix" class="hash-link" aria-label="Enlace directo al Verifying the Fix" title="Enlace directo al Verifying the Fix" translate="no">​</a></h3>
<p>Let's check our <code>example-app</code> data on the restored instance. We can run a quick query to see if our missing sales are back:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">count</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> sale </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">-- Result: 452 (They are back!)</span><br></span></code></pre></div></div>
<p>Once verified, you just point your application to the new database endpoint. Crisis averted.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works-under-the-hood">How It Works Under the Hood<a href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery#how-it-works-under-the-hood" class="hash-link" aria-label="Enlace directo al How It Works Under the Hood" title="Enlace directo al How It Works Under the Hood" translate="no">​</a></h2>
<p>We don't use magic, just rock-solid engineering.</p>
<ol>
<li class=""><strong>Physical Backups</strong>: We use tools like Percona XtraBackup or WAL-G to take non-blocking, physical snapshots of your disk. This is much faster than logical dumps (<code>mysqldump</code>).</li>
<li class=""><strong>Continuous Archiving</strong>: Every transaction (write, update, delete) is written to a Write-Ahead Log (WAL) or Binary Log. We stream these logs to secure object storage in real-time.</li>
<li class=""><strong>Automated Replay</strong>: When you request a restore, our orchestration engine spins up a fresh container, pulls the closest base backup, and automatically replays the logs up to your chosen timestamp.</li>
</ol>
<p>You get the power of an enterprise DBA team, without hiring one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dont-wait-for-a-disaster">Don't Wait for a Disaster<a href="https://your-docusaurus-site.example.com/es/blog/backups-pitr-recovery#dont-wait-for-a-disaster" class="hash-link" aria-label="Enlace directo al Don't Wait for a Disaster" title="Enlace directo al Don't Wait for a Disaster" translate="no">​</a></h2>
<p>The best time to set up a recovery plan is <em>before</em> you need it. With Filess.io, it's enabled by default on all Dedicated plans.</p>
<p><strong>Ready to sleep better at night?</strong></p>
<p><a href="https://filess.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Deploy a Production-Ready Database on Filess.io</strong></a></p>]]></content>
        <author>
            <name>Filess Team</name>
            <uri>https://filess.io</uri>
        </author>
        <category label="backups" term="backups"/>
        <category label="pitr" term="pitr"/>
        <category label="database-recovery" term="database-recovery"/>
        <category label="devops" term="devops"/>
    </entry>
</feed>