# Connect an AI Agent (MCP) Source: https://docs.suga.app/agents/mcp Connect Claude Code, Cursor, and other AI agents to your Suga account over MCP Suga runs a hosted [Model Context Protocol](https://modelcontextprotocol.io) server that lets an AI agent drive your Suga account the way you would through the dashboard: list projects, edit environment configuration, set variables and secrets, watch deployments, and read logs. The server lives at a single endpoint: ``` https://dashboard.suga.app/api/mcp ``` It speaks streamable HTTP and authenticates with OAuth, so any MCP client that supports remote servers can connect with just the URL. No API keys to copy or rotate. ## The safety model The most important thing to understand before you connect an agent: **the agent can prepare changes, but it can never deploy them.** Every environment in Suga has a **Draft** (a working copy of its configuration) and an **Apply** step that pushes the Draft to running infrastructure. The MCP server has no `apply` or `deploy` tool, and no `delete_project` or `delete_environment` tool, by design. Anything the agent changes about a service, its variables, its volumes, or its scaling lands in the Draft and waits for you. Four tools act immediately rather than going into the Draft: `create_project`, `create_environment`, `add_custom_domain`, and `remove_custom_domain`. Removing a custom domain takes it out of service straight away. When an agent makes a change, the tool response includes a **deeplink** back to the affected environment in the Suga UI. You open it, review the rendered diff, and click **Apply** yourself. That visual review is the gate that keeps a misread instruction or a hallucinated container spec from reaching production. * View your projects, environments, and deployments * Create projects and environments * Edit draft configuration: services, volumes, scaling, networking * Set and remove environment variables and secrets in the draft * Manage custom domains and connected GitHub repositories * Read logs, events, and metrics * Deploy or publish. Configuration changes stay as drafts until you review and apply them yourself * Read secret values. Secrets are write-only; only names and metadata are ever returned * Delete projects or environments The agent acts as **you**: it can only see and touch the organizations you're a member of, and every action is subject to your existing permissions. ## Before you start * A Suga account. If you don't have one, [sign up](https://dashboard.suga.app/signup) first. * An MCP client that supports remote servers with OAuth (Claude Code, Cursor, Claude Desktop, and others). ## Connect your agent Add the server from your terminal: ```bash theme={null} claude mcp add --transport http suga https://dashboard.suga.app/api/mcp ``` Then start Claude Code and run `/mcp`. Select **suga** and choose **Authenticate** to open the Suga sign-in and approval flow in your browser. Once you approve, the tools are available in your session. Add Suga to your `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project): ```json theme={null} { "mcpServers": { "suga": { "url": "https://dashboard.suga.app/api/mcp" } } } ``` Open **Cursor Settings → MCP**, find the **suga** server, and click **Login** (or **Needs login**) to complete the OAuth flow in your browser. Open **Settings → Connectors → Add custom connector**, give it a name (e.g. `Suga`), and paste the URL: ``` https://dashboard.suga.app/api/mcp ``` Save, then click **Connect** and approve access in your browser. Edit your Codex configuration (`~/.codex/config.toml`) to add the Suga MCP server: ```toml theme={null} [mcp_servers.suga] url = "https://dashboard.suga.app/api/mcp" ``` Save, then authenticate with this command: ```bash theme={null} codex mcp login suga ``` Any client that supports remote MCP servers over streamable HTTP with OAuth can connect. Point it at: ``` https://dashboard.suga.app/api/mcp ``` The server supports OAuth dynamic client registration, so you don't need to pre-register the client or supply a client ID. The OAuth flow starts automatically on first connect. ## Authorize access The first connection sends you through a browser flow: You're taken to the Suga login page. Sign in with the same account you use for the dashboard. A consent screen shows exactly what the connected app can and can't do. Confirm it's the app you're connecting, then approve. You're redirected back and the connection completes. Your agent can now call Suga tools. You won't need to repeat this unless you disconnect or the session expires. ## A typical workflow Once connected, you can ask your agent to work on Suga in plain language. A first deployment usually flows like this: 1. The agent creates a project and an environment. 2. It adds a container, either from an image or by connecting a GitHub repository to build from source. 3. It sets any environment variables and secrets the container needs. 4. It hands you a **deeplink**. You open it, review the pending changes, and click **Apply**. 5. The agent watches the deployment and reports back when it's live. Steps 2 and 3 happen in the Draft. Nothing changes in your running infrastructure until you apply. ## Good to know * **Secrets are write-only.** An agent can set or rotate a secret, but no tool ever returns a secret's value, only its name and metadata. New values take effect the next time you apply. * **Building from source needs the GitHub App.** Install the Suga GitHub App from the dashboard first; the agent can't start that install flow itself. * **Custom domains wait on DNS.** A newly added domain stays pending until you add the DNS records the agent surfaces for it. ## Related How drafts, deployments, and rollbacks work Projects, environments, and configuration Reading logs from your services Environment variables, secrets, and references ## Need help? * Join our [Discord community](https://suga.app/chat) for support * Email us at [support@suga.app](mailto:support@suga.app) # Suga vs Railway Source: https://docs.suga.app/comparisons/suga-vs-railway How Suga Cloud compares to Railway for container deployment Suga and Railway start from very similar premises. Both run your code as always-on containers rather than serverless functions, both treat Dockerfiles and source builds as first-class inputs, and both support persistent volumes, raw TCP, multi-service applications, and container-based databases. Because the container side overlaps so heavily, the interesting differences show up around the container rather than inside it: the edge tier in front of it, the regions it can run in, how it's billed, and whose infrastructure it runs on. Railway runs everything on Railway's own infrastructure, so you pay a flat workspace fee and per-minute compute charges, and you assemble multi-service applications on a visual canvas that wires databases, workers, and crons together, all of which gives you an end-to-end experience on a single provider. Suga runs on managed infrastructure behind Cloudflare's global edge by default, meters usage as you go, and bundles \$20 of hosting credits into every Pro seat before usage charges accrue. On Enterprise, the same control plane can also target infrastructure you already own on any cloud or on-premises, so one deployment surface can drive the managed environment, workloads running on your existing cloud footprint, or systems already sitting on-prem. Choosing between them often comes down to a single question about where your infrastructure lives, since a fully managed runtime tied to one provider keeps everything simple and uniform, while a control plane that can also point at your own infrastructure on Enterprise gives you the option to bring your own cluster when that matters. ## How Suga and Railway differ Both platforms run containers always-on with no cold starts on either side, so the interesting differences show up elsewhere, specifically across the edge tier, the available compute regions, the pricing model, and whether you can run on your own infrastructure. Railway details are drawn from [Railway's documentation](https://docs.railway.com) and [pricing](https://railway.com/pricing). Competitor capabilities change frequently, so check their current docs before making a decision. ### Compute | Concern | Railway | Suga Cloud | | ----------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Runtimes | 11 via Railpack and any via Dockerfile | Any via Dockerfile or auto-detected source builds; Deno for Functions | | Memory | Up to 32 GB per replica (Pro) | Up to 8 GiB per service on Pro | | Timeout | No service timeout, 15-min HTTP request max | No execution timeout on the container; HTTP requests typically capped at around 100s by the Cloudflare proxy | | Scaling | Manual horizontal up to 42 replicas, plus auto vertical | Manual horizontal up to 10 replicas on Pro, plus vertical auto-scaling | | Container support | Dockerfile and private registries, with SSH access | Dockerfile, auto-detected source builds, and pre-built images from any registry | | Cold starts | None | None | | Billing | Per-minute for allocated CPU and RAM | Usage-based metering across compute and storage | Both platforms run containers always-on and avoid cold starts, but Railway has higher per-replica resource ceilings on the Pro tier, supporting up to 32 GB of memory and 42 replicas compared to Suga's 8 GiB per service and 10 replicas, and Railway also exposes SSH directly into running containers for ad-hoc debugging. Suga meters usage across compute and storage and includes \$20 of hosting credits with every Pro seat that apply before usage charges accrue. ### CDN and Delivery | Concern | Railway | Suga Cloud | | ------------------ | ------------------------------------------- | -------------------------------------------------------------- | | Edge network | 100+ PoPs via Fastly; 4 compute regions | Cloudflare global network (300+ cities); 3 GCP compute regions | | CDN caching | Static assets only, HTML always from origin | Cloudflare default caching for proxied domains | | Image optimization | External service needed | Not currently exposed to customers | | Compression | Not documented | Cloudflare-managed | Railway uses Fastly to cache static assets, but HTML responses always come back from the origin, which keeps things simple and means HTML rendering happens entirely on Railway's infrastructure on every request. Suga fronts every proxied domain with Cloudflare, so your traffic picks up automatic Brotli and Gzip compression, L3/L4/L7 DDoS protection, and TLS termination at the edge, with application-level caching controlled through the standard HTTP response headers your container emits. On the compute side, Suga currently runs in 3 GCP regions (Americas, Europe, Asia-Pacific) with more on the roadmap, while Railway operates in 4, so the bigger geographic differentiator between the two is what happens at the edge rather than at the origin. ### Security Defaults | Concern | Railway | Suga Cloud | | ----------------- | ----------------------------------------- | ---------------------------------------------- | | DDoS | L3/L4 | L3/L4/L7 via Cloudflare | | WAF | External provider recommended | Managed WAF, applied by default | | Bot protection | External provider recommended | Not currently exposed | | Rate limiting | External provider recommended | Not currently exposed | | TLS | Automatic | Automatic, with mutual TLS to the origin | | Compliance | SOC 2 Type II, SOC 3, GDPR; HIPAA BAA | Working toward published certifications | | Network isolation | Encrypted private networking on all plans | Default-deny network isolation per environment | Railway's edge security stack is intentionally light, which means for WAF rules, bot protection, and rate limiting you'd integrate an external provider into your traffic path. Suga's traffic flows through Cloudflare's proxy, where DDoS protection and TLS termination apply automatically. A managed WAF is applied by default. Suga maintains the rules, so there is nothing to configure and no custom rules to write today. On compliance, Railway is ahead today with published SOC 2 Type II, SOC 3, GDPR, and a HIPAA BAA available with committed spend, while Suga is working toward those certifications but doesn't publish them yet. ## Compare Suga and Railway features | Feature | Railway | Suga Cloud | | ------------------------------ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | | Application hosting | Included | Included on Suga's managed infrastructure, or on infrastructure you already run via BYOC on Enterprise | | CDN | Fastly, 100+ PoPs, static assets only | Cloudflare global network (300+ cities) | | Image optimization | External service | Not currently exposed | | WAF | External provider | Managed WAF, applied by default | | DDoS protection | L3/L4 | L3/L4/L7 via Cloudflare | | Bot protection | External provider | Not currently exposed | | Rate limiting | External provider | Not currently exposed | | Observability | Resource metrics and log explorer (7–30 day retention) | Pod logs and resource metrics; bring your own APM | | AI infrastructure | Not offered | Bring your own (LiteLLM template) | | Databases | Container-based (Postgres, MySQL, Redis, Mongo) | Container-based templates (Postgres, MySQL, MariaDB, Mongo, Redis, MinIO) | | Private networking | Encrypted private networking, zero-config | Per-environment isolation, default-deny between environments | | Persistent volumes | Yes | Yes | | TCP proxy | Yes | Yes | | Compute regions | 4 | 3 GCP regions (or any region via BYOC on Enterprise) | | SSH access | Yes | Not currently exposed | | Run on your own infrastructure | Not offered | Supported on Enterprise (BYOC to any cloud or on-premises) | | Compliance | SOC 2 Type II, SOC 3, GDPR, HIPAA BAA | Working toward published certifications | ## Choosing between Suga and Railway | If you need | Choose | Why | | ------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- | | L7 DDoS and WAF at the edge | Suga | Cloudflare is on by default; Railway's Fastly tier doesn't include those layers. | | To run on infrastructure you already own | Suga | Suga's Enterprise plan can deploy workloads onto your own infrastructure on any cloud or on-premises; Railway runs only on Railway. | | Per-seat pricing with hosting credits bundled in | Suga | Each Pro seat unlocks \$20 in hosting credits before metering kicks in. | | SSH into running containers | Railway | Railway exposes direct SSH access; Suga uses logs and history-based debugging instead. | | 32 GB RAM per replica or more than 10 replicas at Pro pricing | Railway | Suga's Pro tier caps at 8 GiB per service and 10 replicas. | | 7–30 day searchable log retention | Railway | Railway's log explorer retains 7–30 days; Suga streams logs in real time without a persisted archive. | Choose **Suga** if you want Cloudflare's edge tier included by default (with the option on Enterprise of running on infrastructure you already own on any cloud or on-premises), or choose **Railway** if you need SSH access into running containers, higher per-replica memory ceilings at Pro pricing, or published compliance certifications today. ## Try Suga * [Sign up for Suga Free](https://dashboard.suga.app/signup) * [Read the Quickstart](/quickstart) * [Talk to us](/support/contact) if you're evaluating a migration from Railway # Suga vs Render Source: https://docs.suga.app/comparisons/suga-vs-render How Suga Cloud compares to Render for container deployment Suga and Render both put the container at the centre of the deployment model, running code as always-on services with Dockerfiles and source builds as first-class inputs, and covering the surrounding pieces most longer-lived workloads need like persistent disks, WebSockets, multi-service topologies, and managed data stores. Because that side lines up so heavily, the interesting differences show up outside the workload itself: the edge in front of it, the geographic reach behind it, how pricing is put together, and whose infrastructure carries the deployment. Render runs everything on its own infrastructure with a flat monthly workspace fee, per-service compute metered by the second, and a broad catalogue of instance sizes that scales up to 32 GB of RAM and 8 CPU per service. Suga runs workloads on managed infrastructure fronted by Cloudflare's global edge, meters usage across compute and storage, and drops hosting credits into every Pro seat that draw down before any overage kicks in. Enterprise workspaces unlock a second option: the same control plane can also deploy onto infrastructure you already own on any cloud or on-premises, without switching deployment tooling. The decision usually turns on where you want your workloads to physically live. Sticking with a single vendor keeps the operating model uniform, while an Enterprise tier that can also target existing infrastructure preserves the option to consolidate under cloud commitments you already run. ## How Suga and Render differ The tables below step through the four areas where the two platforms genuinely diverge: how the edge in front of the container behaves, which compute regions each covers, how workspace and usage pricing are structured, and whether the workload can run on infrastructure the customer already owns. Render details are drawn from [Render's documentation](https://render.com/docs) and [pricing](https://render.com/pricing). Competitor capabilities change frequently, so check their current docs before making a decision. ### Compute | Concern | Render | Suga Cloud | | ----------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Runtimes | Native runtimes for Node.js/Bun, Python, Ruby, Go, Rust, and Elixir; any via Dockerfile | Any runtime via Dockerfile or auto-detected source builds; Deno for Functions | | Memory | Up to 32 GB per instance on Pro Ultra | Up to 8 GiB per service on Pro | | CPU | Up to 8 CPU per instance on Pro Ultra | Up to 4 cores per service on Pro | | Timeout | Up to 100-minute HTTP request duration | No total-request cap; a 5-minute stream idle timeout closes connections that go silent | | Scaling | Manual horizontal up to 100 instances; autoscaling on Pro workspace plan and higher | Manual horizontal up to 10 replicas on Pro, plus vertical auto-scaling | | Container support | Dockerfile, native runtimes, and pre-built images from Docker Hub, GHCR, GitLab CR, Google Artifact Registry, and ECR | Dockerfile, auto-detected source builds, and pre-built images from [most registries](https://docs.suga.app/configure/private-registries#supported-registries) | | Cold starts | None | None | | Billing | Flat workspace fee plus per-second compute metering | Usage-based metering across compute and storage | Render offers a wider set of instance sizes at the top end, scaling up to 32 GB of RAM and 8 CPU per service on Pro Ultra, and it supports up to 100 manually scaled instances against Suga's ten on Pro. On HTTP request lifetimes, Render caps each request at up to 100 minutes as a hard total-duration ceiling, whereas Suga applies no total-request cap but does enforce a 5-minute stream idle timeout, so long streaming or AI workloads that emit data continuously fit naturally on Suga, while requests that need to sit silent for more than five minutes are the ones Render's ceiling is built for. ### CDN and Delivery | Concern | Render | Suga Cloud | | ------------------ | ------------------------------------------------------------------------------------ | ----------------------------------------------------------- | | Edge network | Global CDN backed by Cloudflare for static sites; edge caching for paid web services | Cloudflare global network (300+ cities) for proxied domains | | CDN caching | Static sites globally cached by default; opt-in edge caching for paid web services | Cloudflare default caching for proxied domains | | Image optimization | Not currently exposed | Not currently exposed | | Compression | Automatic | Cloudflare-managed | | Compute regions | 5 (Oregon, Ohio, Virginia, Frankfurt, Singapore) | 3 regions (Americas, Europe, Asia-Pacific) | Render's static sites are served through a global CDN by default, and paid web services can opt into edge caching that reuses the same network, with cache invalidation on every deploy plus a manual purge from the dashboard. Every proxied Suga domain sits behind Cloudflare's proxy, which handles Brotli and Gzip compression, provides L3/L4/L7 DDoS mitigation, and terminates TLS at the edge, while application-level caching is driven by the `Cache-Control` headers the container returns. At the origin layer, Suga runs in three regions today with additional regions on the roadmap and Render operates in five, keeping the two platforms broadly comparable in origin coverage. ### Security Defaults | Concern | Render | Suga Cloud | | ----------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | DDoS | Free DDoS protection powered by Cloudflare | L3/L4/L7 via Cloudflare | | WAF | Not exposed as a customer-configurable product | Managed WAF, applied by default | | Bot protection | Not currently exposed | Not currently exposed | | Rate limiting | Not currently exposed | Not currently exposed | | TLS | Automatic (Let's Encrypt and Google Trust Services) | Automatic (Automatic, with mutual TLS to the origin) | | Compliance | SOC 2 Type 2, ISO 27001, GDPR DPA, HIPAA on Scale plan and above, EU-US DPF | Working toward published certifications | | Network isolation | Private networking across all plans within a workspace and region; blocking cross-environment traffic requires Pro or above | Default-deny network isolation per environment | Render provides free DDoS protection powered by Cloudflare on every deployed service, and WAF, bot protection, and rate limiting are not currently exposed as customer-configurable products at the edge. Every request to a Suga service passes through Cloudflare's proxy first, so DDoS mitigation, WAF filtering, and TLS termination apply without any per-service setup. Suga maintains the WAF rules, so there are no custom rules to write today. For teams that need audited compliance, Render currently ships more of the paperwork, holding SOC 2 Type 2, ISO 27001, GDPR DPA, and HIPAA on the Scale plan and above, whereas Suga has those certifications in progress but hasn't published them yet. ### Pricing model | Concern | Render | Suga Cloud | | ------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------- | | Workspace fee | Hobby free; Pro \$25/mo flat; Scale \$499/mo flat; Enterprise custom | Suga Pro per-seat, with \$20 hosting credits per seat | | Team members | Unlimited on Pro and above | Per-seat | | Included bandwidth | 5 GB (Hobby), 25 GB (Pro), 1 TB (Scale) then \$0.15/GB overage | Cloudflare-fronted egress metered as part of usage-based billing | | Autoscaling | Pro workspace plan and above | Included | | Autoscaling ceiling | Up to 100 instances | Up to 10 replicas on Pro | | SSO / SCIM | Scale plan and above | Enterprise | | HIPAA workspace | Scale plan (20% compute uplift, no minimum) | Not currently offered | Render's pricing model separates a flat workspace fee from per-second compute metering, so once you're on Pro or Scale you invite as many teammates as you want under a single monthly workspace charge, and bandwidth is bundled into each tier with overage billed at \$0.15 per GB. Suga charges per seat and drops \$20 of hosting credits into each Pro seat that offset usage charges before you start paying for compute and storage, which tends to suit smaller teams running production workloads without needing enterprise governance features up front. ## Compare Suga and Render features | Feature | Render | Suga Cloud | | ------------------------------ | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | Application hosting | Included (Render infrastructure) | Included on Suga's managed infrastructure, or on infrastructure you already run via BYOC on Enterprise | | CDN | Global CDN for static sites; edge caching for paid web services | Cloudflare global network (300+ cities) | | Image optimization | Not currently exposed | Not currently exposed | | WAF | Not currently exposed as a customer product | Managed WAF, applied by default | | DDoS protection | Free, powered by Cloudflare | L3/L4/L7 via Cloudflare | | Bot protection | Not currently exposed | Not currently exposed | | Rate limiting | Not currently exposed | Not currently exposed | | Observability | Logs, metrics, health checks, per-service dashboards | Pod logs and resource metrics; bring your own APM | | AI infrastructure | Not offered as a first-party product | Bring your own (LiteLLM template) | | Databases | Managed Postgres and Key Value (Redis-compatible) | Container-based templates (Postgres, MySQL, MariaDB, Mongo, Redis, MinIO) | | Private networking | Within a workspace and region on all plans; cross-environment isolation on Pro and above | Per-environment isolation, default-deny between environments | | Persistent disks | Yes, single-instance only | Yes | | Public TCP proxy | Not currently exposed | Yes, raw TCP proxying | | WebSockets | Yes | Yes | | Compute regions | 5 | 3 regions (or any region via BYOC on Enterprise) | | Container support | Dockerfile and prebuilt images from 5 supported registries | Dockerfile, auto-detected source builds, and pre-built images from any registry | | Run on your own infrastructure | Not offered | Supported on Enterprise (BYOC to any cloud or on-premises) | | Compliance | SOC 2 Type 2, ISO 27001, GDPR DPA, HIPAA on Scale, EU-US DPF | Working toward published certifications | ## Choosing between Suga and Render | If you need | Choose | Why | | ------------------------------------------------------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | DDoS and WAF at the edge | Suga | Cloudflare's proxy applies DDoS protection and a managed WAF by default; Render ships free DDoS protection at the edge, with WAF not currently exposed as a customer product. | | To run on infrastructure you already own | Suga | Suga's Enterprise plan can deploy workloads onto your own infrastructure on any cloud or on-premises; Render runs only on Render. | | Per-seat pricing with hosting credits bundled in | Suga | Each Pro seat unlocks \$20 in hosting credits before metering kicks in. | | Managed Postgres with point-in-time recovery and read replicas | Render | Render's Postgres is fully managed with tiered compute, PITR, and read replicas; Suga ships container-based templates you operate. | | 32 GB RAM per instance or more than 10 replicas at similar pricing | Render | Render's Pro Ultra tier scales to 32 GB of RAM per instance and up to 100 manually scaled instances; Suga's Pro tier caps at 8 GiB per service and 10 replicas. | Choose **Suga** when the edge layer sitting in front of your services matters, with the option on Enterprise to keep those services running on infrastructure you already own or are contractually committed to, or choose **Render** when the priorities are higher per-instance memory ceilings, HTTP requests that need to sit idle for many minutes before returning, managed Postgres with point-in-time recovery and read replicas, or published compliance certifications available today. ## Try Suga * [Sign up for Suga Free](https://dashboard.suga.app/signup) * [Read the Quickstart](/quickstart) * [Talk to us](/support/contact) if you're evaluating a migration from Render # Suga vs Vercel Source: https://docs.suga.app/comparisons/suga-vs-vercel How Suga Cloud compares to Vercel for application deployment Vercel and Suga both help you ship applications to the cloud, but they make very different assumptions about what you're shipping. Vercel is built around the framework you're using, so when you push code on Next.js, Nuxt, SvelteKit, or one of about thirty others, the platform reads the framework's output and provisions matching infrastructure for you, with ISR caches, edge functions, image optimization, and the AI Gateway all wired in automatically based on what your framework expects. Suga is built around the container you want to run, so you can push a Dockerfile, point us at a source repository for an auto-detected build, or deploy a pre-built image from any registry, and Suga will run it as an always-on container behind Cloudflare's global edge with persistent volumes, raw TCP, and multi-service private networking available when you need them. Vercel is a strong fit when you're shipping a web application on a supported framework and you want the platform to handle most of the infrastructure decisions, while Suga is a strong fit when you're shipping containers (backends, workers, multi-service architectures, anything that needs persistent state), with the option on Enterprise to run those containers on infrastructure you already own on any cloud or on-premises. ## How Suga and Vercel differ Both platforms deploy code to the cloud, but the interesting differences show up across how the runtime works, how the edge tier behaves, how scaling happens, and how billing is structured, which the tables and prose below work through in turn. Vercel details are drawn from [Vercel's documentation](https://vercel.com/docs) and [pricing](https://vercel.com/pricing). Competitor capabilities change frequently, so check their current docs before making a decision. ### Compute | Concern | Vercel | Suga Cloud | | ------------ | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Runtimes | Node.js, Python, Go, Ruby, Rust, Bun | Any via Dockerfile or auto-detected source builds; Deno for Functions | | Memory | Up to 4 GB per instance | Up to 8 GiB per service on Pro | | CPU | Up to 2 vCPU | Up to 4 cores per service on Pro | | Timeout | Up to 800s with Fluid compute | No execution timeout on the container; HTTP requests typically capped at around 100s by the Cloudflare proxy | | Scaling | Auto to 30,000 concurrent (Pro) | Manual horizontal up to 10 replicas on Pro, plus vertical auto-scaling | | Build inputs | 37+ frameworks auto-detected, no Dockerfile needed | Dockerfile, auto-detected source builds, or pre-built images from any registry | | Cold starts | Effectively eliminated | None, since containers are always on | | Billing | Active CPU time (I/O wait excluded) | Usage-based metering across compute and storage | Vercel's Fluid Compute model bills only for active CPU time, which is a meaningful advantage for I/O-heavy workloads like model inference or third-party API fan-out where the CPU spends a lot of time waiting on external services. Suga meters the allocated container's usage across compute and storage, which is more predictable for always-on services where the CPU stays busy most of the time, so the right pricing model depends on whether your workload sits idle a lot or works the whole time. ### CDN and Delivery | Concern | Vercel | Suga Cloud | | ------------------ | -------------------------------------- | -------------------------------------------------------------- | | Edge network | 126+ PoPs, 51 countries | Cloudflare global network (300+ cities) for proxied domains | | CDN caching | Framework-aware (ISR, SWR, Data Cache) | Cloudflare default caching for proxied domains | | Invalidation | \~300ms global via framework API | Cloudflare TTL behavior; no programmatic cache purge from Suga | | Image optimization | Built-in (WebP/AVIF, edge-cached) | Not currently exposed to customers | | Compression | Automatic Brotli + Gzip | Cloudflare-managed | | Edge key-value | Edge Config (P99 \< 15ms) | Not offered | Vercel analyzes your framework's output and provisions matching caching primitives for you, including ISR for static-regenerable pages, SWR for data fetching, and the Image API for asset transforms, with cache invalidation programmatic through the framework's API and propagating globally in milliseconds. Suga keeps caching explicit and container-controlled, so the container you ship goes behind Cloudflare's global edge where Cloudflare's default caching applies alongside whatever `Cache-Control` headers your application emits, which gives you direct control over what gets cached where without giving up the edge entirely, at the cost of framework-aware behaviors like ISR not being derived automatically. ### Security Defaults | Concern | Vercel | Suga Cloud | | ----------------- | ------------------------------------------------- | ---------------------------------------------- | | DDoS | L3/L4/L7 on all plans | L3/L4/L7 via Cloudflare proxy | | WAF | Custom rules on all plans | Managed WAF, applied by default | | Bot protection | Managed rulesets + BotID | Not currently exposed | | Rate limiting | `@vercel/firewall` SDK | Not currently exposed | | TLS | Automatic | Automatic, with mutual TLS to the origin | | Compliance | SOC 2 Type 2, ISO 27001, PCI DSS, GDPR; HIPAA BAA | Working toward published certifications | | Network isolation | Secure Compute with VPC peering (Enterprise) | Default-deny network isolation per environment | Vercel ships WAF, BotID, and rate limiting as platform primitives that you configure directly in the Vercel dashboard. Suga's edge security comes from the Cloudflare proxy in front of your app, where DDoS protection and TLS termination apply automatically. A managed WAF is applied by default, with rules maintained by Suga rather than written by you. At the cluster layer, every Suga environment is isolated with default-deny network policies, which block lateral movement between environments even if a workload is compromised. ## Compare Suga and Vercel features | Feature | Vercel | Suga Cloud | | ------------------------------ | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | Application hosting | Included | Included on Suga's managed infrastructure, or on infrastructure you already run via BYOC on Enterprise | | CDN | Framework-aware, 126+ PoPs | Cloudflare global network (300+ cities) | | Image optimization | Included | Not currently exposed | | WAF | Custom rules on all plans | Managed WAF, applied by default | | DDoS protection | L3/L4/L7 | L3/L4/L7 via Cloudflare | | Bot protection | Managed rulesets + BotID | Not currently exposed | | Rate limiting | All plans + SDK | Not currently exposed | | Observability | Speed Insights, Web Analytics, Log Drains, OTel | Pod logs and resource metrics | | AI infrastructure | AI Gateway, AI SDK, Sandbox, Agent | Bring your own | | Databases | Managed providers via Marketplace | Container-based templates (Postgres, MySQL, MariaDB, Mongo, Redis, MinIO) | | Private networking | Secure Compute with VPC peering (Enterprise) | Per-environment isolation, default-deny between environments | | Persistent volumes | Not supported | Yes | | TCP proxy | Not supported | Yes, raw TCP proxying | | Docker support | Not supported | Yes | | Multi-service architectures | Single project model | Multiple computes per environment with internal service discovery | | Preview environments | Per-branch URL, zero cost | Manual environment creation | | Run on your own infrastructure | Not supported | Supported on Enterprise (BYOC to any cloud or on-premises) | ## Choosing between Suga and Vercel | If you need | Choose | Why | | --------------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- | | Framework-aware caching, edge SSR, image optimization | Vercel | ISR, SWR, the Image API, and middleware are wired up automatically from your framework's output. | | AI Gateway, AI SDK, or sandboxed code execution | Vercel | Vercel includes these primitives natively; Suga is a deployment substrate without them. | | Active-CPU pricing for I/O-heavy workloads | Vercel | Vercel excludes I/O wait time from billing, which favors workloads with significant external waits. | | Always-on containers, persistent volumes, or raw TCP | Suga | Suga supports first-class container deployments with state and direct TCP access. | | Multi-service backends with private networking | Suga | Suga deploys multiple computes per environment with internal service discovery between them. | | To run on infrastructure you already own | Suga | Suga's Enterprise plan can deploy workloads onto your own infrastructure on any cloud or on-premises; Vercel runs only on Vercel. | | Container-based databases (Postgres, MySQL, Redis, Mongo) | Suga | Suga ships container templates that run inside your environment. | Choose **Vercel** if you're shipping a web application on a supported framework and you want infrastructure derived automatically from the framework's output, or choose **Suga** if you're shipping containers (backends, workers, multi-service architectures, anything with persistent state), with the option on Enterprise to run those containers on infrastructure you already own. ## Try Suga * [Sign up for Suga Free](https://dashboard.suga.app/signup) * [Read the Quickstart](/quickstart) * [Talk to us](/support/contact) if you're evaluating a migration from Vercel # Environments Source: https://docs.suga.app/concepts/environments Isolated deployment targets for different stages of development Environments are isolated deployment targets within a project. Run multiple versions of your application simultaneously—production, staging, development—without them interfering with each other. Each environment maintains its own deployment history with full audit trails and rollback capability. ## What is an Environment? An environment is an isolated namespace where you deploy your application: * **Isolated Infrastructure** - Each environment has its own services, volumes, and configuration * **Separate Secrets** - Environment variables don't leak between environments * **Independent Scaling** - Production can have 5 replicas while dev has 1 * **Version Control** - Full deployment history with rollback to any previous state Every project starts with a default **production** environment. Create additional environments as needed. ## Common Environment Types | Environment | Purpose | Typical Configuration | | --------------- | ---------------------- | -------------------------- | | **production** | Live customer-facing | High resources, redundancy | | **staging** | Pre-production testing | Production-like, test data | | **development** | Active feature work | Minimal resources | ## Creating an Environment From the environment dropdown in the top bar: 1. Click **New Environment** 2. Enter an environment name 3. Under **Starting point**, choose **Clone from existing** (and pick the source environment) or **Empty environment** 4. Click **Create**, then apply when you're ready to deploy Free plans are limited to 1 environment across the whole organization. Pro and Enterprise plans have no limit. ## Environment Isolation Each environment is completely isolated: **Separate Namespaces:** * Services in "production" cannot communicate with services in "staging" * Private networking only works within the same environment **Independent Configuration:** * Different environment variables per environment * Different secrets (database passwords, API keys) * Different resource allocations (CPU, memory, replicas) **Separate Deployments:** * Deploy to production without affecting staging * Each environment has its own deployment history * Rollback independently per environment ## Cloning an Environment **Clone from existing** creates a complete, isolated copy of your infrastructure. All services, configuration, and volume definitions are duplicated to a new environment where you can experiment safely. ### What Gets Copied **Copied:** * All services (containers and functions) with their images * Resource allocations (CPU, memory, replicas) * Networking configuration (HTTPS endpoints, TCP proxies) * Volume definitions and mount paths * Service connections and dependencies * Environment variables, including their values **Not copied:** * Volume data (volumes are created empty) * Deployment history (starts fresh) * Logs and metrics ### The Variable Review Step After you name the environment and pick a source, Suga shows every variable it found, grouped by service. Each one has a checkbox and an editable value, so you can drop or change anything before the environment is created. Variables marked sensitive, and values Suga detects as secrets, start **unchecked**. Everything else starts checked. Tick a sensitive variable to carry its value over, or leave it off and set a fresh value later. ### After Cloning 1. **Fill in any variables you skipped** - Set passwords, API keys, and other secrets you chose not to copy. 2. **Apply** - The new environment starts undeployed. Click **Apply** to provision infrastructure. 3. **Populate Data** - Volumes are empty. Load data from backups or seed manually if needed. ### Clone vs. Empty **Clone when:** * Testing changes to existing infrastructure * You need environment parity, such as staging matching production * Debugging issues that require exact replication **Start empty when:** * Starting a new architecture from scratch * Existing environments don't match what you need * Experimenting with a completely different setup Cloning captures every detail: image tags, resource limits, volume sizes, networking. Nothing is missed or approximated. ## Switching Environments 1. Click the environment dropdown in the top-right 2. Select the environment 3. The canvas updates to show that environment's infrastructure ## Deleting Environments Use the environment selector to switch to the target environment. Open the environment dropdown in the top bar, choose **Delete Environment**, and confirm. Deleting permanently removes all services, volumes, deployments, and data. It cannot be undone, and it works on any environment, including production. ## Common Questions No, environments are isolated. Private networking only works within the same environment. For cross-environment communication, use public networking (HTTPS/TCP). Yes. Cloning captures configuration, not running state, and it is instant. No, volumes are created empty. Load data from backups or seed manually if needed. Yes. Each environment can use different image tags (e.g., production uses `v1.0.0` while staging uses `v1.1.0-beta`). No, cloning only works within the same project. Environment merging is planned for a future release. For now, apply changes from the cloned environment to the original by hand. # Organizations Source: https://docs.suga.app/concepts/organizations Team workspaces, member management, and access control Organizations are the top-level entity in Suga. They serve as team workspaces where you manage projects, collaborate with team members, and handle billing. ## What is an Organization? An organization represents your team or company: * **Team Workspace** - Shared space for all team projects * **Billing Entity** - Subscription and payment handled at org level * **Access Control** - Invite members and assign roles * **Audit Trail** - Every deployment tracked with who, when, and what Every Suga account starts with a personal organization. You can create additional organizations for teams or clients. ## Organization Structure ```mermaid theme={null} graph TD org[Organization: Acme Corp] org --> members[Members
5 users] org --> projects[Projects
8 active] org --> billing[Billing
Pro Plan] ``` ## Creating an Organization Click the organization dropdown in the top-left corner. Select **New Organization** and enter a name. ## Roles and Permissions Suga uses role-based access control with three built-in roles: | Role | Description | | ---------- | --------------------------------------------------------- | | **Owner** | Full control, including billing and removing other owners | | **Admin** | Manage projects, team, and billing, cannot remove owners | | **Member** | Create and deploy, view team | Roles are set at the organization level and apply to all projects. ### Permissions Matrix | Permission | Owner | Admin | Member | | --------------------------- | :---: | :-------: | :----: | | **Projects & Environments** | | | | | View projects/environments | ✅ | ✅ | ✅ | | Create/edit projects | ✅ | ✅ | ✅ | | Delete projects | ✅ | ✅ | ✅ | | **Deployments** | | | | | View deployments | ✅ | ✅ | ✅ | | Deploy/rollback | ✅ | ✅ | ✅ | | **Team Management** | | | | | View members | ✅ | ✅ | ✅ | | Invite/remove members | ✅ | ✅ | ❌ | | Change roles | ✅ | Non-Owner | ❌ | | **Organization** | | | | | Edit org settings | ✅ | ✅ | ❌ | | **Billing** | | | | | Manage subscription | ✅ | ✅ | ❌ | | View invoices | ✅ | ✅ | ❌ | ### Role Guidelines **Owner** - Keep to 1-3 people (founders, CTO). Can make irreversible changes, including removing other owners. **Admin** - Senior engineers and team leads who need full project access. **Member** - Default role for developers. Can build and deploy but cannot manage the team. ## Inviting Team Members Click **Members** in the left sidebar. Enter email address and select role. They receive an email invitation and gain access upon accepting. Invited members don't count toward your seat limit until they accept. ## Removing Team Members When someone leaves the team: Go to **Members** in the left sidebar, click the "..." menu next to the person, and choose **Remove**. If they had production access, rotate: * Database passwords * API keys * Registry credentials Seat count decreases immediately and billing adjusts at the next cycle. ## Changing Roles Owners can change anyone's role. Admins can change Member and Admin roles (not Owners). 1. Go to **Members** in the left sidebar 2. Find the member 3. Click the "..." menu, choose **Change Role**, and pick the new role 4. Changes take effect immediately ## Billing Pro plan uses seat-based pricing (\$20/user/month): * Each team member with any role counts as one seat * Owners, Admins, and Members all count equally * Billed monthly based on active seats **Plan limits:** Member count, project count, compute, memory, storage, and replica caps all vary by tier. See [Plan Limits](/reference/limits) for the full breakdown, and [suga.app/pricing](https://www.suga.app/pricing) for current pricing. ## Organization Navigation Organization pages live in the left sidebar: * **Projects** - Every project in the organization * **GitHub Integration** - Manage the Suga GitHub App and repository access * **Usage** - Resource usage and costs for the current period * **Members** - Invite, manage, and remove team members * **Billing** - Subscription, invoices, and payment method * **Cluster** - Cluster connection, shown only when you bring your own cluster * **Organization Settings** - Organization name and other details ## Handing Over Ownership There is no one-click ownership transfer. Hand over ownership in two steps: Go to **Members**, open the "..." menu next to the person, choose **Change Role**, and set them to **Owner**. From your own row in **Members**, open the "..." menu and choose **Leave Organization**, or ask the new Owner to change your role to Admin or Member. An organization must always have at least one Owner, so promote the new Owner before you leave. Suga blocks the last Owner from leaving. ## Common Questions Yes. Switch between them using the dropdown in the top-left corner. Not from the dashboard. Email [support@suga.app](mailto:support@suga.app) and we'll do it for you. Deletion permanently removes all projects, environments, deployments, and data, and it cannot be undone. Yes, currently there are no per-project permissions. All members can access all projects within the organization. Enterprise custom permissions are coming soon. # Overview Source: https://docs.suga.app/concepts/overview Understanding Suga's architecture and fundamental building blocks This section introduces the core concepts that make up Suga's architecture. Understanding these concepts will help you design and manage applications effectively. Suga canvas with services ## Hierarchy Suga organizes infrastructure in a clear hierarchy: ```mermaid theme={null} graph TD A[Organization] --> B[Projects] B --> C[Environments] C --> D[Deployments] D --> E[Services
Containers or Functions] D --> F[Volumes
Persistent Storage] ``` ### The Mental Model Think of Suga as **applications, not servers**: * You design what you want to run (services and volumes) * You don't manage where or how it runs * You focus on configuration and connections * Suga handles provisioning, networking, and orchestration Kubernetes powers Suga under the hood, but you never need to learn Kubernetes concepts or YAML files. ## Key Concepts at a Glance | Concept | Description | Example | | ---------------- | ------------------------------------------------- | --------------------------- | | **Organization** | Team workspace and billing entity | "Acme Corp" | | **Project** | Application container | "Marketing Website" | | **Environment** | Isolated deployment target | "production", "staging" | | **Deployment** | Immutable snapshot of infrastructure | "Deploy #42 on Jan 28" | | **Service** | Running workload (Container or Function) | "api", "frontend", "worker" | | **Volume** | Persistent block storage | "postgres-data" (5 GB) | | **Networking** | Public (HTTPS/TCP) or private (service discovery) | HTTPS domain or TCP proxy | ## Organizations Organizations are team workspaces: * The top-level entity in Suga * Billing and subscription management * Team member invitations and roles * Own multiple projects [Learn more about Organizations →](/concepts/organizations) ## Projects Projects are application containers: * Belong to one organization * Have a display name you can change at any time, which does not have to be unique * Are addressed by an internal ID, so renaming a project never changes its URL * Contain multiple environments [Learn more about Projects →](/concepts/projects) ## Environments Environments are isolated deployment targets: * Separate namespaces for production, staging, development * Each has its own services and volumes * Independent configuration and secrets * Share the same project structure Preview Environments (automatic PR environments) are coming soon in a future release. [Learn more about Environments →](/concepts/environments) ## Deployments Deployments are immutable snapshots: * Capture complete infrastructure state at a point in time * Include all services, volumes, configuration, and networking * Tracked in deployment history for rollback * Only one deployment is active per environment [Learn more about Deployments →](/operate/deployments) ## Services Services are your running workloads: **Docker-based service:** * Run any Docker image * Support for public and private registries * Configure commands and ports * Best for existing applications and standard workloads **Serverless-style service:** * Write Deno/TypeScript code directly in Suga * Built-in code editor, no Docker build needed * Ideal for APIs and lightweight services * Automatically scaled and managed All services support: * Environment variables with secrets encryption * Resource limits (CPU and memory) * Horizontal scaling with replicas * Public networking (HTTPS/TCP) and private networking (service discovery) [Learn more about Services →](/concepts/services) ## Volumes Volumes provide persistent storage: * Block storage that survives restarts and redeployments * Size limits vary by plan (check dashboard for current limits) * Mount to services at specified paths * Essential for databases and stateful applications Volumes can only be mounted to one service at a time, and that service must have exactly 1 replica. [Learn more about Storage →](/configure/volumes) ## Networking Suga offers two networking modes: **Private Networking (Service Discovery):** * Automatic DNS-based discovery * Services communicate using service names * Format: `service-name:port` * Example: `postgres:5432`, `redis:6379` **Public Networking:** * **HTTPS Endpoints** - Port 443 with automatic TLS and domains * **TCP Proxy** - Non-HTTP protocols like PostgreSQL or SSH * Automatic load balancing across replicas [Learn more about Networking →](/configure/networking) ## Templates Templates are pre-configured project resources: * Vetted configurations for common services * Auto-fill images, ports, volumes, and environment variables * Available for databases, frameworks, and tools * Save time with best-practice defaults [Learn more about Configuration →](/reference/configuration) ## Next Steps Explore each concept in depth: Team workspaces and billing Application containers Isolated deployment targets Immutable infrastructure snapshots Containers and functions Public and private networking Persistent storage Templates and settings # Projects Source: https://docs.suga.app/concepts/projects Services, environments, and infrastructure for your application Projects are the primary organizational unit in Suga. Each project represents a complete application with all its services, databases, and infrastructure. ## Key Features of a Project A project contains your application: * **Logical Boundary** - Groups related services and infrastructure * **Multiple Environments** - Each project has production, staging, dev, etc. * **Canvas Workspace** - Visual design space for your infrastructure * **Deployment History** - Complete record of infrastructure changes per project * **Version Control** - Every change tracked with commit messages and author Think of a project as one complete application, like "Marketing Website", "E-commerce API", or "Internal Dashboard". ## Project Structure ```mermaid theme={null} graph TD project[Project: E-commerce API] project --> envs[Environments] envs --> prod[production] envs --> staging[staging] envs --> dev[development] project --> infra[Infrastructure per environment] infra --> services[Services: api, worker, postgres, redis] infra --> volumes[Volumes: postgres-data 5 GB] ``` ## Creating a Project Click **New project** in the dashboard to open the New Project page, which offers three ways to start. Whichever you pick, the project is created with a default `production` environment and full deployment tracking, and the canvas opens. ### Import from a GitHub repository Click **Connect GitHub** to install the Suga GitHub App on your account or organization (once per account or org), then pick the repository you want to deploy. Suga takes you to an import page where you set the project name and the build and deploy settings: * **Branch** - the branch Suga watches and builds from * **Build method** - auto-detect, or point Suga at your Dockerfile * **Root directory** - for monorepos, the subdirectory holding the app * **Build args** - values passed to the build Click **Create project**. The project opens on the canvas with a container already connected to the repository. See [Build from GitHub](/concepts/services#build-from-github) for how rebuilds work after that. ### Start from a template Under **Starting from scratch?**, pick a template such as PostgreSQL, Redis, MySQL, or MongoDB. Suga creates the project with that service configured and ready on the canvas. Templates are single services, so add the rest of your infrastructure from the canvas afterwards. ### Start with an empty project Click **Create empty project** for a blank canvas. Use this when you're importing a Compose file, adding a function, or bringing a pre-built image from a registry. ## Project Settings Access project settings from the project dropdown menu. Settings are minimal and focused on project identity: ### General * **Project Name** - Change the display name shown in the dashboard * **Description** - Optional description for the project ### Delete Project Permanently delete the project and all its data. This action is in the danger zone section at the bottom of settings. Deleting a project permanently deletes all environments, deployments, services, volumes, and data. This action cannot be undone. ## The Canvas Every project has a visual canvas where you design infrastructure: **Canvas Features:** * Add services, volumes, and templates to your infrastructure * Visual connections between services and volumes * Real-time configuration panel * Environment selector to switch between production/staging/dev * Deploy button to push changes live ## Environments Each project can have multiple environments (production, staging, development, preview, etc.) with isolated namespaces and independent configuration. See [Environments](/concepts/environments) for detailed information. ## Common Questions Yes, you can change the project name anytime in Project Settings. Not currently. You'll need to recreate the project in the target organization. Export your configuration from the canvas first. There's no hard limit on services per project. Resource availability depends on your plan. All deployments are immediately stopped and all data is permanently deleted. Make sure to back up any important data before deleting a project. # Services Source: https://docs.suga.app/concepts/services Running workloads - containers and functions Services are the building blocks of your application. They represent running workloads that handle requests, process data, serve web pages, or perform background jobs. ## What is a Service? A service is a running instance of your application code: * **Execution Environment** - Where your code runs * **Configurable Resources** - CPU, memory, and replicas * **Network Accessible** - Public (HTTPS/TCP) or private (service discovery) * **Stateless** - Use volumes for persistent storage Suga supports two types: **Containers** and **Functions**. ## Containers vs. Functions | Feature | Container | Function | | ----------------- | ---------------------------- | -------------------------- | | **Runtime** | Any (Docker) | Deno only | | **Language** | Any | TypeScript/JavaScript | | **Configuration** | Image + tag | Code in editor | | **Setup** | Docker build externally | Write code directly | | **Flexibility** | High | Simple and fast | | **Best For** | Full applications, databases | APIs, webhooks, prototypes | *** ## Containers Containers run Docker images from any registry. They provide maximum flexibility for existing applications in any language or framework. A container's image comes from one of two sources: * **Build from GitHub** - Connect a repository so Suga builds the image for you. Each push to the watched branch triggers an automatic rebuild and redeploy. * **Pre-built Image** - Pull an existing image from any Docker registry. Best when you already build elsewhere (CI, local Docker, another platform) or are running off-the-shelf images like databases, caches, etc. ### Build from GitHub Connect a GitHub repository and Suga builds the image for you. Pushes to the watched branch trigger an automatic rebuild and redeploy. In the container's Image section, choose **Build from GitHub** and install the Suga GitHub App on your account or organization. Grant access to the repositories you want to build from. Pick a repository and the branch to watch. Pushes to this branch trigger a new build. * **Dockerfile** - point Suga at a `Dockerfile` in the repo. * **Auto-detect** - leave the Dockerfile field empty and Suga reads the repo to generate a build. Works for most Node.js, Python, Go, Ruby, Rust, Java, and PHP projects. Click **Apply** to build the image and roll out the service. Subsequent pushes to the watched branch trigger an automatic rebuild and redeploy. The Suga GitHub App is installed once per account or organization. After installation, any container service can build from the repositories you've granted access to. Use a release branch (e.g. `main` or `release`) for production environments and a development branch for staging. Each environment can watch a different branch of the same repo. #### Build Configuration Dockerfile builds expose four settings: | Setting | Default | Purpose | | ------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | **Dockerfile path** | `Dockerfile` | Path to the Dockerfile, relative to the repo root. Set this when your Dockerfile lives in a subdirectory (e.g. `apps/api/Dockerfile`). | | **Build context** | `.` (repo root) | Directory sent as build context. Narrow it to a sub-path (e.g. `apps/api`) in monorepos. | | **Target stage** | *(final stage)* | For multi-stage Dockerfiles, build up to a named `FROM ... AS ` target. | | **Build args** | *(none)* | Key/value pairs passed as `--build-arg`, available at build time. | Branch and build configuration together identify a build, so two services on the same repo can build different stages or contexts without colliding. #### Auto-Build on Push Auto-build is on by default. Each push to the watched branch: 1. Builds the configured Dockerfile (or the auto-detected project). 2. Tags the image with the commit SHA. 3. Rolls out the new image to every environment whose service is wired to that branch. Suga deduplicates by commit SHA and build configuration, so the same commit doesn't rebuild twice. Changing only env vars or resource sizing redeploys without a rebuild. Turn off auto-build on the service to pause this. Manual builds from the dashboard still work. ### Pre-built Image Pull an image from any Docker-compatible registry (Docker Hub, GHCR, GCR, ECR, ACR, or self-hosted) by its full reference: ``` [registry/]repository:tag ``` Examples: * `nginx:alpine` - Official Nginx from Docker Hub * `postgres:16-alpine` - PostgreSQL 16 * `ghcr.io/username/myapp:v1.0.0` - GitHub Container Registry **Command** (Optional) - Override the container's default entrypoint. **Ports** - Which ports your application listens on inside the container. For private registries, attach credentials to the service. See [Private Registries](/configure/private-registries). #### Automatic Updates from External Registries After a pre-built image is deployed, Suga polls the registry for a new digest at the same tag and rolls the service forward when one appears. Useful for: * Mutable tags like `:latest`, `:stable`, or `:edge`. * External CI pipelines that build outside Suga and push to a tag your service tracks. Images Suga builds itself don't wait on the poll — the build triggers the rollout directly when it finishes. Pin to a specific version tag (e.g. `myapp:v1.2.3`) instead of `:latest` if you want the service to roll out only when you bump the tag. ### Creating a Container Click **Add** in the top right of the canvas, or right-click empty space. The palette is searchable and lists **Service from GitHub**, **Service from Container**, **Template**, **Function**, and **Import Compose**. Choose **Service from GitHub** to [build from source](#build-from-github), **Service from Container** for a [pre-built image](#pre-built-image) from a registry, or **Template** for a pre-configured service. Then set the display name. If your app listens on a port, specify it. Enable HTTPS or TCP proxy for public access. Database URLs, API keys (mark as Sensitive), feature flags. Allocate CPU and memory. New services start at 0.1 CPU and 128 MiB. Click **Apply** to provision the container. ### Supported Registries **Public (no credentials):** * Docker Hub: `nginx`, `postgres`, `redis` * GitHub Container Registry: `ghcr.io/username/image` * Quay.io: `quay.io/organization/image` **Private (with credentials):** * Docker Hub, GHCR, GCR, ECR, ACR, self-hosted Enter credentials in the **Service from Container** dialog (or the service's **Config** tab for an existing service), under **Registry credentials**. See [Private Registries](/configure/private-registries) for setup. Suga runs on Linux AMD64. If building on Apple Silicon, use `--platform linux/amd64`. ### Docker Compose Import Import existing Docker Compose files: 1. Open the Add palette and choose **Import Compose** 2. Paste YAML or upload file 3. Review parsed services 4. Import to canvas **Supported:** Services, images, env vars, ports, named volumes, resource limits. **Not supported:** Build contexts (use pre-built images), bind mounts, health checks. *** ## Functions Functions run Deno code. Write TypeScript/JavaScript directly in the dashboard instead of building Docker images. ### How Functions Work Functions start an HTTP server on a configured port. Configuration (env vars, resources, networking, replicas) is identical to containers, but you write code in the **Code** tab instead of specifying an image. There's no container build for functions. Your TypeScript ships with the deployment and runs on a managed Deno runtime, so changes go live in seconds. That makes functions a good fit for small APIs, webhooks, and quick prototyping. ### Default Template New functions use this Hono-based template: ```typescript theme={null} import { Hono } from "npm:hono@^4"; import { serve } from "https://deno.land/std@0.224.0/http/server.ts"; const app = new Hono(); app.get("/", (c) => { return c.json({ message: "Hello from Deno function!" }); }); const port = parseInt(Deno.env.get("PORT") || "8080"); console.log(`Server running on port ${port}`); serve(app.fetch, { port }); ``` Your code must start an HTTP server on the configured port (default 8080). ### Code Editor Select function → **Code** tab → write code → **Apply**. The editor supports TypeScript syntax highlighting and basic completion. ### Imports ```typescript theme={null} // npm packages import { Hono } from "npm:hono@^4"; // Deno standard library import { serve } from "https://deno.land/std@0.224.0/http/server.ts"; // Third-party modules import { Client } from "https://deno.land/x/postgres@v0.17.0/mod.ts"; ``` ### Environment Variables ```typescript theme={null} const dbUrl = Deno.env.get("DATABASE_URL"); const apiKey = Deno.env.get("API_KEY"); ``` Configure in the Config tab. Mark sensitive values as Sensitive. *** ## Common Configuration Both containers and functions share these configuration options: Service configuration panel showing environment variables, networking, and resources ### Resources Each service is configured with CPU, memory, and replicas. Your allocation is a guaranteed floor, not a cap: services can burst above it for free, and billing is based on the allocation. See [Billing and Resource Allocation](/reference/billing) for how that works and how to size a service, and [Plan Limits](/reference/limits) for tier maximums, resource pools, volume limits, and the CPU/memory ratio rules. ### Networking **Private** - Services in the same environment communicate via service names: ``` http://api:3000 postgres:5432 ``` **Public HTTPS** - Web traffic with automatic TLS through Cloudflare. **Public TCP** - Non-HTTP protocols (databases, SSH, custom protocols). See [Networking](/configure/networking) for details. ### Environment Variables Key-value configuration for your services: * Database connection strings * API keys and secrets (mark as Sensitive) * Feature flags and settings ### Volumes Persistent storage that survives restarts and redeployments: * Mount paths inside the container * Size limits vary by plan * Single-mount only (one service per volume) See [Storage Reference](/configure/volumes) for details. ## Service Templates Templates provide pre-configured services for common use cases: * **PostgreSQL** - Database with volume and default credentials * **Redis** - Cache with persistence options * **MariaDB** - MySQL-compatible database Templates auto-generate secure passwords and configure networking. # Custom Domains Source: https://docs.suga.app/configure/custom-domains Use your own domain names with Suga services Custom domains let you serve your Suga services from your own domain (e.g., `app.example.com`) instead of the auto-generated Suga domains. ## How It Works When you add a custom domain to a service, Suga provides the DNS records you need to configure with your DNS provider. Once the records are in place, Suga automatically verifies ownership and provisions TLS certificates. No manual certificate management required. **What you get:** * Automatic TLS certificates * Cloudflare CDN, WAF, and DDoS protection * Zero-downtime certificate renewals ## Adding a Custom Domain Click on the service you want to assign a custom domain to. In the properties panel, open the **Config** tab. In the **Public Networking** section, click **+ Custom Domain**. Enter your domain name (e.g., `app.example.com`) and the target port your application listens on (e.g., `3000`). Suga will display the DNS records you need to add. Create a **CNAME** record with your DNS provider pointing your domain to the target Suga shows you. Example: | Type | Name | Target | | ----- | ----- | ------------------------------------------------------------- | | CNAME | `app` | `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4.cname.us-central1.suga.run` | Copy the target from the UI. It contains a hash of your environment, so you cannot work it out yourself, and it is different for every environment. Click **Apply**. Once your DNS records propagate, Suga automatically verifies your domain and provisions a TLS certificate. This typically takes a few minutes. DNS verification must complete within **48 hours** of adding the domain. If your DNS records aren't detected in that time, the claim will expire and you'll need to re-add the domain to start a new verification. Your service will then be accessible at your custom domain. ## Apex Domains Apex (root) domains like `example.com` (without a subdomain prefix) require special DNS support because the DNS specification doesn't allow CNAME records at the zone apex. Your DNS provider must support **CNAME flattening**, **ANAME**, or **ALIAS** records to use an apex domain. Not all providers support this. ### Supported DNS Providers Providers that support CNAME flattening or equivalent include: | Provider | Mechanism | | ------------------------------ | ------------------------------------- | | **Cloudflare** | CNAME flattening (automatic for apex) | | **NS1** | ANAME records | | **DNSimple** | ALIAS records | | **Constellix / DNS Made Easy** | ANAME records | | **EasyDNS** | ALIAS records | | **DigitalOcean DNS** | ALIAS records (CNAME flattening) | | **Namecheap** | ALIAS records | | **Netlify DNS** | ALIAS records | **AWS Route 53** and **Azure DNS** support ALIAS records, but only for pointing to their own services. They do not support arbitrary external targets. These will **not** work for Suga custom domains. Some traditional registrar DNS providers (e.g., GoDaddy) do not support any of these mechanisms. You'll need to either switch to a supported provider or use a subdomain instead. Check your DNS provider's documentation if you're unsure whether they support this. ### Configuring an Apex Domain When you add an apex domain, Suga will provide two DNS records: | Type | Name | Target / Value | | ----- | -------------------------- | ------------------------------------------------------------- | | CNAME | `example.com` | `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4.cname.us-central1.suga.run` | | TXT | `_suga-verify.example.com` | `suga-verify=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4` | Note the TXT record's name: it goes on the `_suga-verify` subdomain, not on the apex itself. Copy both records from the UI rather than typing them from this page. 1. Add both the **CNAME** (or ALIAS/ANAME equivalent) and the **TXT** record with your DNS provider 2. Wait for DNS propagation and automatic verification 3. Apply your changes If your DNS provider doesn't support CNAME flattening, you can use a subdomain like `www.example.com` or `app.example.com` and redirect to it from the apex domain. ## Domains Already Using Cloudflare If your domain is already on Cloudflare, you'll need to adjust the proxy setting for the CNAME record that points to Suga. Cloudflare's proxy (orange cloud) must be **disabled** for the CNAME record pointing to Suga. Set the record to **DNS only** (grey cloud). Suga cannot verify your domain while the Cloudflare proxy is enabled, because it hides the underlying CNAME target. Suga provides its own Cloudflare CDN, WAF, and DDoS protection for custom domains, so disabling the proxy on your side does not reduce protection, your traffic is still routed through Cloudflare's edge network via Suga. ## Domain Conflicts A domain can only be active on one Suga environment at a time. If another organization has already verified and activated the same domain, you'll receive an error when trying to add it. Unverified (pending) claims from other organizations do not block you, only proven ownership counts. If you need to move a domain between environments within your organization, remove it from the original environment first, then add it to the new one. ## Common Questions Usually a few minutes, but DNS propagation can take up to 48 hours depending on your provider and TTL settings. If verification doesn't complete within 48 hours, the claim expires and you'll need to re-add the domain. Yes. Add each domain separately through the Public Networking configuration. No. Suga automatically provisions and renews SSL/TLS certificates for all custom domains. Yes. The auto-generated Suga domain continues to work alongside your custom domain. Standard DNS does not allow CNAME records at the zone apex. Your provider needs to support CNAME flattening, ANAME, or ALIAS records. If it doesn't, use a subdomain like `www.example.com` with a redirect instead. Make sure the CNAME record pointing to Suga has the Cloudflare proxy **disabled** (grey cloud / DNS only). Suga can't verify the CNAME target while it's hidden behind Cloudflare's proxy. ## Next Steps Learn about HTTPS endpoints, TCP proxy, and private networking How Cloudflare's edge and Suga regions route traffic Configure environment variables, resources, and scaling # Environment Variables Source: https://docs.suga.app/configure/environment-variables Set values on a service, mark secrets, and reference values from other services Environment variables configure a service without changing its image. Suga keeps them per service, per environment, so the same image can run with different settings in staging and production. ## Adding a Variable Select the service on the canvas, then open the **Env Vars** tab. Click **Edit environment variables**. Add a key and a value for each variable. Keys are usually uppercase with underscores, like `DATABASE_URL`. **Save** records your changes on the canvas. They do not reach the running service until you click **Apply** and the environment is deployed. To bring in many variables at once, click **Import** in the dialog and choose a `.env` file. Suga shows you what it found so you can drop anything you do not want before confirming. Saved values are hidden by default. Click the eye button beside a value to reveal it. ## Secrets Click the lock button beside a value to mark it **Sensitive**. The value is encrypted, and once saved it is never shown again in the canvas, in logs, or through the API. You can replace it, but you cannot read it back. You can turn this off while you are still editing. Once you save, the choice is fixed. To make a saved sensitive value readable again, delete the variable and add it back. There is no way to unlock it in place. When you import a `.env` file, keys that look like secrets are marked sensitive for you. Check the review list before confirming, because saving locks them. ## Referencing Another Service A service often needs a value that belongs to another service, like a database password or the address of an internal API. Rather than copying the value, reference it. Type `{{` in a value field. A picker opens listing everything you can reference, and typing filters it. Pick a value and the reference drops in where your cursor was. A reference looks like this: ```bash theme={null} DATABASE_PASSWORD={{postgres.POSTGRES_PASSWORD}} ``` The first part is the service you are pointing at. The second is the variable on that service. References work inside a longer value, so you can build a connection string from several of them: ```bash theme={null} DATABASE_URL=postgres://appuser:{{postgres.POSTGRES_PASSWORD}}@{{postgres.SUGA_PRIVATE_HOSTNAME}}:5432/app ``` References are resolved when the environment is deployed, so the value your service receives is always the current one. If you change the password on the database, every service referencing it picks up the new value on the next deploy. Two problems are caught before you can deploy. A reference to a service or variable that no longer exists is marked as broken, and references that form a loop, where two services each wait on the other, are rejected. Renaming a variable updates the references pointing at it, so nothing breaks. Deleting one that other services reference asks you to confirm and names them. ## Values Suga Provides Every service receives a set of variables describing where it can be reached. You will mostly use them through references, so one service can read the address of another. | Variable | What it holds | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | `SUGA_PRIVATE_HOSTNAME` | The name other services in this environment use to reach this one | | `SUGA_PUBLIC_HOSTNAME` | The address this service serves on publicly. A custom domain once one is working, otherwise the address Suga generated | | `SUGA_PUBLIC_TARGET_PORT` | The port inside the container that public traffic is sent to | | `SUGA_TCP_HOSTNAME` | The host raw TCP connections are made to | | `SUGA_TCP_PORT` | The port raw TCP connections are made to | | `SUGA_TCP_TARGET_PORT` | The port inside the container that TCP traffic is sent to | A variable only exists when it applies. A service with no public endpoint has no `SUGA_PUBLIC_HOSTNAME`, rather than an empty one. `SUGA_TCP_PORT` is assigned while the deploy runs, so it is not available on a service that has never been deployed. To give one service the public address of another, reference it: ```bash theme={null} API_URL=https://{{api.SUGA_PUBLIC_HOSTNAME}} ``` If you add a custom domain later, the reference picks it up. A copied URL would not. A reference to a `SUGA_` value the target does not have, such as the public hostname of a service with no public endpoint, is not reported as broken. It resolves to nothing and your service receives the text `{{...}}` unchanged. Check that the service you are pointing at has the endpoint you expect. `SUGA_` is reserved. You cannot create a variable whose name starts with it. ## Build Time and Run Time The variables above are available while your service runs. A build needs its own, because the build happens before the service exists. Some frameworks read configuration when they build rather than when they start. Values that end up in code the browser downloads are in this group, like `VITE_` variables in a Vite app or `NEXT_PUBLIC_` variables in Next.js. Setting these as service variables has no effect, because the build already finished without them. To set them, open the **Config** tab, click the pencil on the connected repository to open **Edit Build Configuration**, and expand **Additional Settings**. * On an auto-detected build the field is **Environment Variables**. Values are available to the build and are not stored in the image. * On a Dockerfile build the field is **Build Arguments**. Declare each one with `ARG KEY` in your Dockerfile, or the build will not see it. Values passed this way can be read back out of the finished image. Whatever your build writes into its output stays there. A value used to build browser code is readable by anyone who loads the page, whichever field you used to supply it. Keep secrets out of client-side builds. Saving build configuration starts a new build straight away. It does not wait for **Apply**. Some names are reserved and will be rejected, including anything starting with `DEPOT_`, `BUILDKIT_` or `GIT_`, and common system names like `PATH`, `HOME` and `NODE_OPTIONS`. # Networking Source: https://docs.suga.app/configure/networking Public and private networking for your applications Suga provides two networking modes: **Private Networking** for internal service communication, and **Public Networking** for exposing services to the internet. ## Networking Overview | Type | Purpose | Configuration | Security | | ---------------- | -------------------------------- | ------------- | ----------------- | | **Private** | Service-to-service communication | Automatic | Internal only | | **Public HTTPS** | Web traffic with TLS | Port 443 | Automatic TLS | | **Public TCP** | Non-HTTP protocols | Custom port | No TLS by default | ## Private Networking (Service Discovery) All services in the same environment can communicate privately using automatic service discovery. Private traffic stays inside the environment and is never exposed to the internet. ### How It Works **Automatic DNS:** * Every service gets an internal hostname * Internal DNS resolves service hostnames to addresses within the environment * No manual configuration required **Format:** ``` hostname:port ``` **Examples:** * PostgreSQL: `postgres:5432` * Redis: `redis:6379` * API service: `api:3000` * WebSocket server: `websocket:8080` ### Configuring Hostname and Ports Each service has a **Private Networking** section in its **Config** tab where you can set: * **Hostname**: the name other services use to reach this service. It starts as a DNS-safe version of the service's display name (lower case, with spaces and underscores turned into hyphens and other characters dropped), with a `-2` or `-3` suffix if that name is already taken. Override it to use a friendlier name like `postgres` or `api`. Hostnames must be unique within an environment. * **Ports**: the ports this service listens on internally. Add every port you want reachable from other services in the same environment. Public networking ports (HTTPS endpoints, TCP proxies, custom domains) are automatically reachable on the private hostname as well, so you don't need to list them twice. ### Connection Strings Use service names in connection strings: ```javascript Node.js theme={null} // PostgreSQL const connectionString = `postgresql://user:pass@postgres:5432/database`; // Redis const redisUrl = `redis://:password@redis:6379`; // HTTP API const apiUrl = `http://api:3000/endpoint`; ``` ```python Python theme={null} # PostgreSQL DATABASE_URL = "postgresql://user:pass@postgres:5432/database" # Redis REDIS_URL = "redis://:password@redis:6379" # HTTP API API_URL = "http://api:3000/endpoint" ``` ```go Go theme={null} // PostgreSQL connStr := "postgresql://user:pass@postgres:5432/database" // Redis redisAddr := "redis:6379" // HTTP API apiURL := "http://api:3000/endpoint" ``` Private networking currently only works within the same environment. Services in "production" cannot reach services in "staging". ## Public Networking Public networking exposes services to the internet. Suga offers two modes: **HTTPS** and **TCP Proxy**. ### HTTPS Endpoints HTTPS endpoints provide secure web access with automatic TLS certificates. All HTTPS traffic goes through Cloudflare's global CDN. See [CDN and Regions](/reference/cdn-and-regions) for the edge architecture and where requests get routed. **Features:** * Port 443 (HTTPS) * Automatic TLS certificates via Cloudflare * Cloudflare CDN, WAF, and DDoS protection * Auto-generated domain names * Traffic spread across replicas **Auto-Generated Domains:** Suga generates a domain for each HTTPS endpoint. It combines the service's ID, the environment name, and a label identifying the cluster your organization runs in. Example: ``` https://k3f9x2mq7p1a-production-a1b2c3d4.us-central1.suga.run ``` The service ID is the short identifier Suga assigns, not the name you gave the service, so renaming a service does not change its generated address. The domain is fixed once the endpoint is created. You can change which port it serves, but not the address itself. Because the address is assigned rather than chosen, avoid copying it into another service by hand. Reference it instead, so it stays correct if you add a custom domain later: ```bash theme={null} API_URL=https://{{api.SUGA_PUBLIC_HOSTNAME}} ``` See [Environment Variables](/configure/environment-variables) for how references work, and [Custom Domains](/configure/custom-domains) to serve on your own domain instead. **Configuration:** Click on the service you want to expose. In the properties panel, open the **Config** tab. In the **Public Networking** section, click **Add** next to **Generated URL**. Specify the target port your application listens on (e.g., 3000, 8080). Public HTTPS traffic on port 443 routes to this port. Click **Apply**. Your service will be accessible at the generated URL. ### TCP Proxy TCP proxy exposes non-HTTP protocols to the internet. **Use Cases:** * Direct database access (PostgreSQL, MySQL) * SSH connections * Custom protocols (MQTT) * Game servers Standard `wss://` WebSockets go through the HTTPS path — see [WebSocket Support](#websocket-support). TCP Proxy is only needed for non-HTTP protocols. **Features:** * Any TCP port * Allocated load balancer port * No automatic TLS (use application-level encryption) **Configuration:** Click on the service to expose. In the properties panel, open the **Config** tab. In the **Public Networking** section, click **+ TCP Proxy**. Enter the port your application listens on (e.g., 5432 for PostgreSQL). Click **Apply**. Note the allocated hostname and port in the **Public Networking** section. Use the hostname and allocated port shown in the UI: ``` psql -h proxy.us-central1.suga.run -p 46345 -U user ``` TCP proxy does not provide TLS encryption by default. Use application-level encryption (like PostgreSQL's SSL mode) or consider keeping the service private. ## Connection Timeouts Suga Cloud applies explicit, predictable timeouts to all public traffic so connection behaviour is consistent across deployments. These limits apply to traffic through public ingress (HTTPS endpoints and TCP Proxy) — private service-to-service connections inside an environment aren't subject to these idle timeouts. | Timeout | Applies To | Value | What It Means | | ---------------------- | -------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Request header timeout | HTTPS endpoints (Free plan only) | 120 seconds | Clients must finish sending HTTP request headers within 120 seconds of connecting. Protects shared edge infrastructure from slow or stalled clients. | | Stream idle timeout | HTTPS endpoints | 5 minutes | An HTTP request, WebSocket, SSE stream, or long-polling response with no traffic in either direction for 5 minutes is closed. | | TCP idle timeout | HTTPS endpoints, TCP Proxy | 15 minutes | A TCP connection with no application data sent in either direction for 15 minutes is closed. | | Dead-peer detection | HTTPS endpoints, TCP Proxy | \~2.5 minutes | Suga Cloud probes idle connections and closes any whose peer has gone away (network partition, crashed client, etc.) within roughly 2.5 minutes. | The stream idle, TCP idle, and dead-peer detection limits apply equally on every plan. The request header timeout applies to Free plan services only. See [Plan Limits](/reference/limits#free-tier-request-headers). ### Keeping Long-Lived Connections Alive For long-lived connections — WebSockets, Server-Sent Events, persistent database connections via TCP Proxy — make sure the client or server emits traffic more often than the relevant idle timeout: * **WebSockets:** send a ping frame every 1–2 minutes (well under the 5 minute stream idle timeout). Most WebSocket libraries can do this automatically. * **Server-Sent Events:** emit a comment line (`: keepalive\n\n`) or heartbeat event every 1–2 minutes. * **TCP Proxy (e.g. databases):** enable the keepalive your client supports, such as PostgreSQL `keepalives_idle`, or TCP-level `SO_KEEPALIVE` on the socket for clients without a protocol-level option. Otherwise expect to reconnect every 15 minutes. Dead-peer detection and the TCP idle timeout are independent. Dead-peer detection only closes connections whose *peer* is gone — it does not reset the idle timer for healthy-but-quiet connections. ## Load Balancing For services with multiple replicas, Suga spreads traffic across replicas automatically. This applies to HTTPS endpoints, TCP proxies, and private service-to-service traffic. The distribution strategy is not configurable, and Suga does not guarantee a particular one, so don't rely on requests landing on a specific replica. Load balancing is automatic. You don't need to configure it manually. ## WebSocket Support WebSockets work automatically with HTTPS endpoints: **Setup:** 1. Configure your application to listen for WebSocket connections 2. Enable HTTPS on the service 3. Deploy 4. Connect using `wss://` (secure WebSocket) Idle WebSockets are closed after 5 minutes. Have your client or server send a ping frame every 1–2 minutes to keep the connection open — see [Connection Timeouts](#connection-timeouts). **Example:** ```javascript theme={null} // Client const ws = new WebSocket('wss://k3f9x2mq7p1a-production-a1b2c3d4.us-central1.suga.run'); // Server (Node.js with ws library) const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 3000 }); wss.on('connection', (ws) => { console.log('Client connected'); ws.send('Welcome!'); }); ``` ## Server-Sent Events Support Server-Sent Events (SSE) work automatically with HTTPS endpoints — no special configuration required. **Setup:** 1. Configure your application to respond with `Content-Type: text/event-stream` 2. Enable HTTPS on the service 3. Deploy 4. Connect using `EventSource` from the client Idle SSE streams are closed after 5 minutes. Emit a comment line (`: keepalive\n\n`) or heartbeat event every 1–2 minutes to keep the connection open. See [Connection Timeouts](#connection-timeouts). **Example:** ```javascript theme={null} // Server (Node.js / Express) app.get('/events', (req, res) => { res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }); const heartbeat = setInterval(() => res.write(': keepalive\n\n'), 90_000); req.on('close', () => clearInterval(heartbeat)); }); // Client const events = new EventSource('https://k3f9x2mq7p1a-production-a1b2c3d4.us-central1.suga.run/events'); events.onmessage = (e) => console.log(e.data); ``` ## Network Isolation Every environment runs inside its own isolated network boundary on Suga Cloud. Services in one environment cannot reach services in another over private networking, and the platform applies a default-deny security posture with explicit allow rules. ### Environment Boundaries **Between Environments:** * Services in different environments (production, staging, dev) cannot communicate privately, even within the same project * Each environment has its own isolated network with its own private DNS * For cross-environment communication, use public networking **Between Projects:** * Services in different projects cannot communicate privately * Use public networking (HTTPS/TCP) for cross-project communication Suga Cloud does not provision a dedicated VPC per project, and there is no cross-environment private routing. Environment isolation is enforced by network policy, not by separate networks. ### Default-Deny Posture Every environment starts with a default-deny policy and only the traffic listed below is permitted. Anything not explicitly allowed is dropped. **Ingress (incoming connections to your services):** | Source | Allowed | | ------------------------------------------------------------------- | ------------------------------------- | | Other services in the same environment | Yes | | Suga Cloud management traffic (TLS, ingress routing, health checks) | Yes | | Services in other environments or projects | No | | The public internet (direct) | No. Must go through a public endpoint | **Egress (outbound connections from your services):** | Destination | Allowed | | ----------------------------------------------------------------------------------------------------- | ------- | | DNS resolution | Yes | | Other services in the same environment | Yes | | Public internet (any external API or service) | Yes | | Private IP ranges outside the environment (RFC 1918: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`) | No | | Cloud provider metadata endpoints | No | Blocking RFC 1918 ranges prevents services from reaching internal infrastructure they shouldn't see, including other tenants' private IPs. Blocking metadata endpoints prevents workloads from harvesting cloud credentials or instance identity from the underlying host. ### Public vs Private * **Private networking** is internal-only and never exposed to the internet. It's the only way services in the same environment talk to each other privately. * **Public networking** (HTTPS endpoints, TCP proxies, custom domains) requires explicit configuration on each service and routes through Suga's managed ingress with automatic TLS for HTTPS. ## Common Patterns ### Web Application Frontend talks to backend, backend talks to database: ```mermaid theme={null} graph LR frontend[Frontend
Public] <-->|HTTPS| api[API
Public] api <-->|Private| postgres[Postgres
Private] ``` **Configuration:** * `frontend`: HTTPS enabled (public) * `api`: HTTPS enabled (public) * `postgres`: No public networking (private only) * `api` connects to `postgres` via `postgres:5432` ### Microservices Multiple services communicate privately, one acts as public gateway: ```mermaid theme={null} graph TD client[Client
Public] <-->|HTTPS| gateway[Gateway
Public] gateway <-->|Private| orders[Orders
Private] gateway <-->|Private| users[Users
Private] gateway <-->|Private| products[Products
Private] ``` **Configuration:** * `gateway`: HTTPS enabled (public) * `users`, `orders`, `products`: No public networking (private only) * Gateway connects to services via private networking ## Common Questions No, HTTPS always uses port 443. You specify your container port (e.g., 3000), and Suga routes port 443 to your container port automatically. No, Suga automatically provisions and renews certificates for all HTTPS endpoints. Traffic from the client to Suga's gateway is encrypted, and TLS terminates at the gateway. Yes, using TCP proxy. However, it's not recommended for security reasons. Keep databases private and access them via your application or a bastion host. Not via private networking. Use public networking (HTTPS/TCP) or deploy related services in the same project. Currently, public endpoints are accessible by anyone. Implement authentication in your application. IP allowlisting is planned for a future release. # Private Docker Registries Source: https://docs.suga.app/configure/private-registries Use images from private registries This guide explains how to use Docker images from private registries on Suga. ## Supported Registries * **Docker Hub** - Private repositories * **GitHub Container Registry (GHCR)** - `ghcr.io` * **Google Container Registry (GCR)** - `gcr.io` and Artifact Registry * **Amazon ECR** - Elastic Container Registry * **Azure Container Registry (ACR)** * **Self-hosted** - Harbor, GitLab, Nexus, etc. ## Adding Registry Credentials Registry credentials are stored per environment, keyed by registry hostname. Enter them once for a registry and every service in that environment pulling from the same host can use them. Environments do not share credentials, so staging and production each need their own. Open the Add palette and choose **Service from Container**, or select an existing service and open its **Config** tab. Enter the full image reference, including the registry host, for example `ghcr.io/username/my-app:v1.2.3`. Suga reads the registry host from this, so there is no separate registry field. Expand **Registry credentials** and fill in: * **Username** - Your username or access key * **Password** - Your password or access token Click **Apply**. Suga authenticates automatically using the stored credentials. ## Registry Configuration | Registry | Host in the image URI | Username | Password | | --------------- | ------------------------------------------ | --------------- | --------------------------------------- | | **Docker Hub** | `docker.io` | Your username | Access token | | **GHCR** | `ghcr.io` | GitHub username | Personal access token (`read:packages`) | | **GCR** | `gcr.io` | `_json_key` | Service account JSON key | | **ECR** | `{account}.dkr.ecr.{region}.amazonaws.com` | `AWS` | `aws ecr get-login-password` output | | **ACR** | `{name}.azurecr.io` | Registry name | Admin password or SP password | | **Self-hosted** | Your registry hostname | Your username | Your password | **ECR tokens expire after 12 hours.** Suga only supports username and password credentials, so there is no way to have it fetch a fresh ECR token for you. Update the password before it expires, or push your images to a registry with long-lived tokens, such as GHCR. ## Image Name Format Always include the full registry in the image name: ``` ghcr.io/username/my-app:latest gcr.io/project-id/my-app:v1.0.0 123456789012.dkr.ecr.us-west-2.amazonaws.com/my-app:latest yourregistry.azurecr.io/my-app:latest ``` Omitting the registry prefix (e.g., `username/my-app`) assumes Docker Hub. ## Image Pull Behavior Suga always pulls the latest version of an image on each deployment. This ensures you get the most recent version even when using the same tag. Using `:latest` in production is not recommended. Use specific version tags (e.g., `v1.2.3`) for reproducible deployments. ## Troubleshooting **Check:** * Registry URL format is correct * Credentials haven't expired * Image name and tag exist * Token has read permissions **Test locally:** `docker login registry-url && docker pull image:tag` Use full image name including registry: ``` ghcr.io/username/image:tag ✓ username/image:tag ✗ (assumes Docker Hub) ``` ECR tokens expire after 12 hours. Regenerate the token with `aws ecr get-login-password` and update the password on the container. If you redeploy often, copy your images to a registry with long-lived tokens instead. Docker Hub limits: 100 pulls/6h (anonymous), 200 pulls/6h (authenticated) Solutions: * Add Docker Hub credentials (increases to 200) * Use GHCR, GCR, or other registry * Upgrade to Docker Hub Pro ## Security Best Practices Grant only read permissions: * Docker Hub: Read-only access token * GitHub: `read:packages` scope * GCR: "Storage Object Viewer" role * ECR: `AmazonEC2ContainerRegistryReadOnly` * ACR: `AcrPull` role Rotate every 90 days, after team member departure, or after suspected compromise. Use `myapp:v1.2.3` instead of `myapp:latest` for reproducible deployments. # Storage Source: https://docs.suga.app/configure/volumes Volumes, databases, and backup strategies This reference covers persistent storage on Suga: volumes for data persistence, database templates, and backup strategies. ## Volumes Volumes provide persistent block storage. Unlike service filesystems (ephemeral), volume data persists across restarts, redeployments, and rollbacks. ### Creating a Volume 1. Add a volume to the canvas 2. Set size (see plan limits below) 3. Drop the volume onto a service 4. Set the mount path 5. Click **Apply** ### Volume Constraints * **Services per volume**: 1 (volumes cannot be shared between services) * **Replicas with volumes**: 1 (required for data consistency) * **Size limits**: vary by plan, see [Plan Limits](/reference/limits#volume-limits) Volume storage also counts toward your organization's overall storage pool. Services with volumes must have exactly 1 replica. Volumes cannot be shared across multiple instances or services. ### Data Persistence **Data survives:** * Container restarts * Redeployments * Service crashes * Rollbacks (data stays current, not rolled back) **Data is lost if:** * Volume is deleted * Environment is deleted Rolling back a deployment does NOT roll back volume data. However, rolling back to a deployment before the volume existed will result in it being deleted. *** ## Database Templates Templates provide pre-configured databases with volumes attached. ### PostgreSQL ```yaml theme={null} Image: postgres:16-alpine Port: 5432 Volume: /var/lib/postgresql/data Environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: [your password] POSTGRES_DB: postgres ``` **Connection from other services:** ``` postgresql://postgres:PASSWORD@postgres:5432/postgres ``` ### Redis ```yaml theme={null} Image: redis:7-alpine Port: 6379 Volume: /data Command: redis-server --appendonly yes --requirepass [password] --maxmemory 200mb --maxmemory-policy allkeys-lru ``` The template caps Redis at 200 MB of data and evicts the least recently used keys when it fills up. Raise `--maxmemory` if you give the service more memory, and change `--maxmemory-policy` to `noeviction` if you are using Redis as a durable store rather than a cache. **Connection:** ``` redis://:PASSWORD@redis:6379 ``` ### MariaDB ```yaml theme={null} Image: mariadb:11 Port: 3306 Volume: /var/lib/mysql Environment: MARIADB_ROOT_PASSWORD: [your password] MARIADB_DATABASE: mydb MARIADB_USER: [application user] MARIADB_PASSWORD: [application user password] ``` `MARIADB_USER` and `MARIADB_PASSWORD` are both required. The image creates that user and grants it access to `MARIADB_DATABASE`. **Connection:** ``` mysql://USER:PASSWORD@mariadb:3306/mydb ``` ### Connecting to Databases Use service names as hostnames for private networking: ```javascript theme={null} // Node.js - PostgreSQL const pool = new Pool({ host: 'postgres', // Service name port: 5432, password: process.env.DB_PASSWORD }); // Node.js - Redis const redis = new Redis({ host: 'redis', port: 6379, password: process.env.REDIS_PASSWORD }); ``` *** ## Volume vs External Storage **Use Volumes when:** * Running your own database * Need direct filesystem access * Storing small uploads or state **Use External Storage (S3, R2) when:** * Files exceed your plan's storage limits * Need to share files across services * Require public CDN access * Want automatic scaling *** ## Common Questions No, each volume can only mount to one service. For shared data, use a database or external object storage. You can increase a volume's size. You cannot decrease it. The underlying storage does not support shrinking, so the canvas blocks a smaller value and the change would be rejected even if it got through. To end up with a smaller volume, create a new one at the size you want and copy the data across. You can only access volume data from within the container. Use database connections or application APIs. # Welcome to Suga Source: https://docs.suga.app/introduction Infrastructure deployment that's both fast and disciplined Suga is under active development, so expect frequent changes as we ship. [Join our Discord](https://suga.app/chat) for support and updates. Deploying infrastructure has meant choosing between two imperfect options: slow-but-safe configuration files, or fast-but-dangerous console clicking. Traditional Infrastructure as Code gives you version control and reproducibility, but deployments take minutes and YAML becomes unmanageable. Cloud consoles let you move quickly, but changes disappear without trace and environments drift apart. Suga rethinks infrastructure deployment from first principles. What if you could deploy in seconds while maintaining full version control? What if every change had an audit trail, environments were instantly reproducible, and you could see your entire architecture at a glance?