# Raff Technologies — Full Content > Cloud infrastructure platform — VMs, S3-compatible object storage, managed Kubernetes, VPC networking, and a one-click app marketplace. AMD EPYC processors, NVMe SSD, unmetered bandwidth. ## Products - Raff VM: High-performance virtual machines built for production workloads. https://rafftechnologies.com/products/raff-vm - Linux VPS Hosting: Deploy Ubuntu, Debian, Rocky Linux, and 6 more distros in 60 seconds. Full root access, NVMe SSD, unmetered bandwidth from $4.99/mo. https://rafftechnologies.com/products/linux-vm - Windows VPS Hosting: Deploy Windows Server 2022 or 2025 in 2 minutes with full RDP access. 6-month evaluation license. From $9.99/mo with 14-day money-back guarantee. https://rafftechnologies.com/products/windows-vm - Block Storage Volumes: NVMe block storage volumes with online resize, snapshots, and volumes that survive VM deletion. 10 GiB to 1 TB. https://rafftechnologies.com/products/volumes - Cloud Security: Cloud security included free: automatic DDoS protection on every public IP, stateful firewalls, isolated VPCs, IAM and audit logs. https://rafftechnologies.com/products/security - Forex VPS: Windows VPS for MetaTrader 4, MT5 and cTrader, with low-latency US networking for Expert Advisors that run around the clock. https://rafftechnologies.com/products/forex-vm - Identity and Access Management (IAM): Identity and access management, free: built-in and custom roles with granular per-action permissions, project-scoped access, API keys, MFA and audit logs. https://rafftechnologies.com/products/iam - Load Balancers: Scalable load balancers for distributing traffic across your services. https://rafftechnologies.com/products/load-balancers - Managed ClickHouse: Columnar OLAP analytics hosting with flat pricing. https://rafftechnologies.com/products/managed-databases/clickhouse - Managed Databases: Fully managed database services for production workloads. https://rafftechnologies.com/products/managed-databases - Managed Kafka: Apache Kafka with flat per-broker pricing and schema registry. https://rafftechnologies.com/products/managed-databases/kafka - Managed Kubernetes: Production-ready Kubernetes clusters powered by OneKE. https://rafftechnologies.com/products/kubernetes - Managed Valkey: Redis-compatible in-memory caching, sessions and queues. https://rafftechnologies.com/products/managed-databases/valkey - MySQL Hosting: Managed MySQL 8 with automatic failover and daily backups. https://rafftechnologies.com/products/managed-databases/mysql - Object Storage: S3-compatible object storage on NVMe. $7/month includes 100 GB and 1 TB egress; no per-request fees. https://rafftechnologies.com/products/object-storage - PostgreSQL Hosting: Managed PostgreSQL with pgvector, HA and point-in-time recovery. https://rafftechnologies.com/products/managed-databases/postgresql - Raff Apps: Push-to-deploy PaaS on Raff's own cloud. Visual service canvas, managed Postgres/MySQL/Valkey, $0 egress, spend cap on by default, no per-seat pricing. The Railway, Render and Heroku alternative. https://rafftechnologies.com/products/app-platform - Raff Functions: Serverless functions billed on two meters: memory and active CPU. Free requests, free egress, no 15-minute cap. https://rafftechnologies.com/products/serverless-functions - Server Backups & Snapshots: Automated incremental VM backups with schedules, snapshots and a free storage pool of 50 GB plus 10–15% of each VM disk. https://rafftechnologies.com/products/data-protection - Site-to-Site VPN: Site-to-site VPN from your office or another cloud into your Raff VPC: WireGuard or IPsec (IKEv2), up to 10 tunnels per gateway, unmetered tunnel traffic. https://rafftechnologies.com/products/site-to-site-vpn - Virtual Private Cloud (VPC): Free virtual private cloud networking: isolated VPCs with security groups, peering, PrivateLink and site-to-site VPN. Private traffic unmetered. https://rafftechnologies.com/products/vpc ## Pricing Full pricing at https://rafftechnologies.com/pricing - VMs start at $8.49/mo (1 vCPU, 1 GB RAM, 25 GB NVMe) - All plans include unmetered bandwidth - Hourly billing with monthly invoicing - 14-day money-back guarantee ## Blog Articles ### Cloudflare VM in 2026: Virtual Machines, Containers & VPS URL: https://rafftechnologies.com/blog/cloudflare-vs-vps-why-developers-still-need-a-server Published: 2026-03-10T00:00:00.000Z Description: Cloudflare VM in 2026: Virtual Machines, Containers & VPS People searching for **Cloudflare VM** usually want a simple answer: can you rent a normal virtual machine from Cloudflare the way you can rent an EC2 instance, DigitalOcean Droplet, or Raff VM? The answer in 2026 is **not exactly**. Cloudflare does **not** sell a traditional general-purpose virtual machine product where you choose a fixed VM size, boot a persistent Linux or Windows operating system, SSH or RDP into it, and manage it like a conventional cloud server. But Cloudflare's compute platform has expanded significantly: **Workers** provides serverless edge compute, while **Cloudflare Containers** can now run container images with full Linux-like environments on the Workers platform. That makes the modern comparison more nuanced than “Cloudflare cannot run servers.” Cloudflare can now run much broader workloads, but its Containers product still has a different operating model from a traditional VPS or VM. ## Cloudflare VM: quick answer | Question | Answer | |---|---| | Does Cloudflare offer traditional virtual machines? | No, not as a general-purpose VM product with a fixed persistent OS instance | | Can Cloudflare run backend code? | Yes, through Workers and related developer-platform services | | Can Cloudflare run container images? | Yes. Cloudflare Containers is generally available on the Workers Paid plan | | Is Cloudflare Containers the same as a VPS? | No. Containers are orchestrated through Workers, start on demand, can scale to zero, and use usage-based resource billing | | Can you still put Cloudflare in front of a normal VPS? | Yes, and that remains a common architecture | | Is there a Cloudflare VM price? | No traditional VM price exists; Workers and Containers use their own pricing models | If you specifically want a normal VPS behind Cloudflare, see our [Cloudflare VPS Hosting guide](/blog/host-app-on-vps-with-cloudflare). This page focuses on the **Cloudflare VM question** and on when Containers or Workers can replace a conventional VM. ## Does Cloudflare have virtual machines? Cloudflare operates a huge global infrastructure fleet internally, but that is different from exposing a public general-purpose VM service to customers. A conventional cloud VM normally gives you: - a persistent guest operating system; - root or administrator access; - a fixed CPU/RAM/storage shape; - long-running background services; - your own package manager and system services; - predictable server lifecycle under your control; - SSH for Linux or RDP for Windows; - attached or local storage options; - arbitrary software stacks. Cloudflare's public compute platform is designed differently. **Workers** runs application code without provisioning servers. **Cloudflare Containers** extends that model by allowing applications packaged as container images to run with more CPU, memory, disk, filesystems, runtimes, and Linux-oriented tooling than Workers alone. So the accurate 2026 answer is: > Cloudflare offers serverless compute and serverless containers, but not a traditional customer-managed VM product. ## Cloudflare Containers changed the old “Cloudflare vs VPS” answer Older comparisons often said Cloudflare could not run Docker containers or full Linux environments. That is now outdated. Cloudflare Containers became generally available in April 2026. Cloudflare documents support for workloads including: - applications packaged as container images; - resource-intensive applications; - software that needs a full filesystem; - applications that require a specific runtime; - CLI tools and broader Linux-like environments; - images from Docker Hub and supported registries. Cloudflare also supports SSH access for debugging live containers. That means some workloads that previously required a VPS can now run on Cloudflare's platform without a traditional VM. However, Containers are still **not simply “Cloudflare VMs.”** They are part of the Workers platform and are controlled by Worker code. Container instances start when needed and can go to sleep after inactivity. That usage-driven lifecycle is different from paying for a VM that stays allocated until you shut it down. ## Cloudflare Containers vs VM | Area | Cloudflare Containers | Traditional VM / VPS | |---|---|---| | Deployment unit | Container image + Worker integration | Full virtual machine | | Operating model | Serverless / orchestrated | Customer-managed server | | OS control | Linux-like container environment | Full guest OS control | | Windows Server | No traditional Windows VM product | Available from Windows VM providers | | Lifecycle | Can start on demand and scale to zero | Usually remains running until stopped | | Billing | Resource usage | Commonly hourly or monthly VM allocation | | SSH | Supported for live container debugging | Standard administration path on Linux | | systemd / full machine management | Not a normal VM model | Yes | | Fixed public VM IP | Not the conventional model | Common | | Docker image support | Yes | Yes, if you install Docker | | Multiple arbitrary system services | Possible only within platform constraints | Normal VM use case | | Best fit | Containerized, elastic application workloads | Full infrastructure control and persistent server workloads | The question is therefore not “can Cloudflare run Docker?” anymore. It can. The better question is: **does your workload fit Cloudflare's container lifecycle and platform model, or do you need a conventional server that you control directly?** ## Cloudflare VM pricing: what do you actually pay? There is no traditional **Cloudflare VM pricing** table because Cloudflare does not sell fixed general-purpose VM instances. Cloudflare Containers is available on the **Workers Paid plan**. As of August 2026, Cloudflare lists a $5/month Workers Paid plan with included monthly container resources: - 25 GiB-hours of memory; - 375 vCPU-minutes; - 200 GB-hours of disk. Above the included usage, Cloudflare currently bills Containers at usage-based rates for memory, active CPU, and provisioned disk. Cloudflare's published additional rates are: | Resource | Additional rate | |---|---:| | Memory | $0.0000025 per GiB-second | | CPU | $0.000020 per vCPU-second | | Disk | $0.00000007 per GB-second | Cloudflare says container charges begin when an instance receives a request or is manually started and stop after the instance goes to sleep. CPU is billed on active usage rather than simply on provisioned wall-clock time. That can be attractive for bursty applications. A traditional VM can be easier to predict when the workload is continuously running and you want one fixed monthly infrastructure bill. Always check Cloudflare's current Containers pricing page before budgeting because platform pricing and included allowances can change. ## Workers vs VM Cloudflare Workers is an even more abstracted compute model than Containers. Workers is a strong fit when you want: - API endpoints; - request/response logic; - authentication middleware; - lightweight backend logic; - edge personalization; - routing and transformations; - integrations with Cloudflare storage and developer services; - globally distributed execution without managing servers. A traditional VM is better when the application needs: - direct operating-system administration; - conventional daemon management; - custom kernel-level behavior; - a Windows Server environment; - software that expects a persistent machine; - arbitrary networking and long-lived infrastructure services; - a traditional database server you manage directly; - server software whose vendor explicitly expects a VM or dedicated host. Cloudflare Containers fills some of the space between these two models. ## Cloudflare Containers vs VPS A VPS gives you a virtual server. Cloudflare Containers gives you a managed container execution platform. Choose **Cloudflare Containers** when: - your application is already containerized; - you want instances to scale up and down automatically; - you do not want to patch and maintain a guest operating system; - usage is bursty enough that scale-to-zero economics are useful; - your architecture already uses Workers or other Cloudflare services; - the application fits Cloudflare's current container limits and lifecycle. Choose a **VPS or VM** when: - you need persistent machine-level control; - you need Linux system administration as part of the workload; - you need Windows Server; - you run several tightly coupled services on one machine; - you need direct access to system packages, networking, firewalling, or service management; - a vendor application assumes a conventional server; - you want one always-on server with fixed resources and straightforward monthly pricing. Neither model is universally better. They solve different infrastructure problems. ## When Cloudflare can replace a VM Cloudflare can replace a traditional VM when the application maps cleanly to the platform. Examples include: - stateless APIs built for Workers; - edge middleware; - frontend applications; - event-driven services; - containerized web applications that can scale to zero; - agent or sandbox workloads designed for Cloudflare's runtime; - workloads that rely heavily on Cloudflare's distributed edge and storage services. In those cases, avoiding a VM can reduce server maintenance. ## When you still need a VM A conventional VM remains the simpler fit for many workloads. Examples include: - Windows Server and RDP workloads; - IIS-hosted applications that require Windows; - self-managed PostgreSQL, MySQL, MongoDB, or SQL Server; - Docker Compose stacks with several persistent services; - VPN servers; - control panels; - legacy business applications; - monitoring systems that expect machine-level access; - long-running worker processes with conventional system-service management; - software that requires root-level host configuration. A VM is also easier when your team already operates Linux servers and does not need serverless orchestration. ## Cloudflare + VM remains a strong architecture Using Cloudflare does not require replacing your server. A common production design remains: ```text Users ↓ Cloudflare DNS / Proxy / CDN / WAF / TLS ↓ Linux or Windows VM ↓ Reverse proxy / application ↓ Database and internal services ``` Cloudflare handles the public edge while the VM handles the application environment. This is useful when you want Cloudflare's DNS, CDN, DDoS protection, TLS, caching, and security features but still need a conventional operating system. For the detailed architecture and setup path, read [Cloudflare VPS Hosting: What It Is, Pricing & How It Works](/blog/host-app-on-vps-with-cloudflare). ## Do you need both Cloudflare and a VPS? Often, yes. Cloudflare and a VPS are not direct substitutes when the workload needs a real server. The VPS or VM can provide: - Linux or Windows; - CPU and RAM reserved for your server; - Docker; - Nginx or Caddy; - application processes; - databases; - scheduled jobs; - private networking; - full filesystem and OS control. Cloudflare can provide the public-facing layer: - DNS; - reverse proxying; - CDN; - TLS; - DDoS protection; - WAF and security controls; - caching; - edge logic. This layered model is especially practical for SaaS applications, APIs, dashboards, WordPress, business software, and self-hosted developer tools. ## Cloudflare VM vs Raff VM Raff and Cloudflare are not equivalent products in this comparison. Cloudflare is primarily providing edge and serverless platform services. Raff VMs are conventional cloud virtual machines. A Raff VM is a better fit when you need: - full Linux root access or Windows Server administrator access; - a persistent VM; - Docker or Docker Compose under your control; - system packages and long-running services; - self-managed databases; - a predictable VM resource shape; - direct server-level networking and firewall management. Cloudflare can still sit in front of that Raff VM. This means the choice does not have to be **Cloudflare or Raff**. For many workloads, the architecture is **Cloudflare + Raff VM**. ## Cloudflare VM FAQs ### Does Cloudflare offer virtual machines? Cloudflare does not offer a traditional general-purpose VM product comparable to EC2, Droplets, or a standard VPS. It offers Workers and Cloudflare Containers, which provide different serverless compute models. ### Does Cloudflare have a VPS? Cloudflare does not sell a conventional VPS with a persistent guest operating system and root access. You can use Cloudflare in front of a VPS from another provider. ### Can Cloudflare run Docker containers? Yes. Cloudflare Containers can deploy container images and is generally available on the Workers Paid plan. This is different from renting a traditional VM and installing Docker yourself. ### How much does a Cloudflare VM cost? There is no Cloudflare VM price because Cloudflare does not sell fixed general-purpose VM instances. Containers and Workers use platform-specific pricing instead. ### Is Cloudflare Containers cheaper than a VPS? It depends on utilization. Containers can scale to zero and bill active resources, which can be efficient for bursty workloads. An always-on VPS can be simpler and more predictable for continuously running services. ### Can Cloudflare replace AWS EC2? Cloudflare Workers and Containers can replace EC2 for some application architectures, but they are not drop-in EC2 equivalents. Workloads requiring full VM control, Windows Server, or conventional host administration still need a VM or another infrastructure model. ### Can I use Cloudflare with a virtual machine? Yes. Point your DNS to the VM, proxy supported web traffic through Cloudflare, configure TLS correctly, and keep the VM responsible for the application and operating-system layer. ## Conclusion The old idea that “Cloudflare cannot run containers, so you always need a VPS” is no longer accurate in 2026. Cloudflare now offers Workers and generally available Containers that can run much broader application workloads without a traditional VM. But Cloudflare still does not sell a conventional general-purpose virtual machine with the same lifecycle and administration model as EC2, a Droplet, or a Raff VM. Choose Cloudflare-native compute when the application fits its serverless model. Choose a VPS or VM when you need persistent server control, Windows Server, traditional system administration, or software that expects a normal machine. And for many production applications, use both: **Cloudflare at the edge and a VM as the origin**. ## Sources - Cloudflare Developers — [Cloudflare Containers](https://developers.cloudflare.com/containers/) - Cloudflare Developers — [Cloudflare Containers pricing](https://developers.cloudflare.com/containers/pricing/) - Cloudflare Changelog — [Containers and Sandboxes are generally available](https://developers.cloudflare.com/changelog/post/2026-04-13-containers-sandbox-ga/) - Cloudflare — [Plans and pricing](https://www.cloudflare.com/plans/) - Sources verified: 2026-08-28 --- ### Cloudflare VPS Hosting: What It Is, Pricing & How It Works URL: https://rafftechnologies.com/blog/host-app-on-vps-with-cloudflare Published: 2026-03-11T00:00:00.000Z Description: Cloudflare VPS Hosting: What It Is, Pricing & How It Works People searching for **Cloudflare VPS** are usually asking one of two questions: does Cloudflare sell a traditional VPS, or how do you combine Cloudflare with a VPS you already run? The short answer is: **Cloudflare does not provide a traditional virtual private server product with root access, a persistent operating system, arbitrary daemons, and a fixed VM shape.** Cloudflare provides edge networking, security, CDN, DNS, Workers, Pages, and other developer-platform services. If your application needs a normal Linux or Windows server, you still use a VPS or cloud VM from a compute provider and place Cloudflare in front of it. A typical Cloudflare + VPS architecture looks like this: ```text Users ↓ Cloudflare DNS / Proxy / TLS / CDN / Security ↓ VPS public IP ↓ Nginx or Caddy ↓ Application on a private local port ``` That combination is what people often mean by **Cloudflare VPS hosting**. ## Cloudflare VPS: quick answer | Question | Answer | |---|---| | Does Cloudflare sell a traditional VPS? | No, not in the conventional VM-with-root-access sense | | Can Cloudflare host applications? | Yes, through products such as Workers and Pages, but those are not traditional VPS instances | | Can you use Cloudflare with any VPS? | Usually yes, if you control DNS and the application is reachable over supported web protocols | | Does Cloudflare replace Nginx or your app server? | No; your VPS still runs the operating system, runtime, database clients, workers, and reverse proxy | | Is there “Cloudflare VPS pricing”? | There is no single Cloudflare VPS plan; your cost is your VPS plus whichever Cloudflare plan/products you use | | Best fit | A VPS for compute + Cloudflare for the public edge | If you already know you want to configure the stack, use our dedicated [step-by-step Cloudflare + VPS tutorial](/learn/tutorials/host-app-on-vps-with-cloudflare). This page focuses on the **architecture, pricing model, and buying decision** so the two pages do not compete for the same intent. ## Does Cloudflare offer VPS hosting? Not as a traditional VPS provider. A normal VPS gives you a persistent virtual machine with features such as: - root or administrator access; - a full Linux or Windows operating system; - long-running processes; - custom packages; - Docker and container runtimes; - background workers; - databases; - arbitrary TCP services; - persistent local or attached storage. Cloudflare's developer platform can run application code and host sites, but its operating model is different from renting a conventional VM. That distinction is important because a developer who needs to install PostgreSQL, run Docker Compose, host a custom daemon, use systemd, or maintain a long-running application process is usually looking for a VPS rather than an edge runtime. ## What does “Cloudflare VPS hosting” actually mean? In practice, **Cloudflare VPS hosting** means using Cloudflare as the public-facing layer in front of a virtual server hosted somewhere else. The VPS owns the compute layer: - application runtime; - Nginx or Caddy; - containers; - background jobs; - local services; - database connections; - operating-system configuration. Cloudflare owns the edge layer: - authoritative DNS; - proxied web traffic; - TLS at the edge; - CDN and caching; - DDoS mitigation; - WAF and security controls, depending on plan; - rate limiting and other edge features, depending on configuration. This separation is useful because you can keep full server control while using Cloudflare's network for the public entry point. ## Cloudflare VPS pricing: what do you actually pay? There is no single **Cloudflare VPS price** because Cloudflare is not selling the VM in this architecture. Your monthly cost has two layers: ```text Total monthly cost = VPS / cloud VM cost + Cloudflare plan and optional product costs ``` Cloudflare has a Free plan for many core website features, while paid plans and usage-based developer products add their own pricing dimensions. Your VPS is billed by the infrastructure provider separately. For example, a small application might use: - one Linux VPS; - Cloudflare Free for DNS/proxy/TLS; - Nginx on the VPS; - no paid Cloudflare add-ons. A larger application could add paid WAF features, Workers usage, R2, load balancing, or other Cloudflare services. The important comparison is therefore not “Cloudflare VPS vs another VPS provider.” It is usually **“which VPS should I put behind Cloudflare, and what Cloudflare services do I actually need?”** ## Why use Cloudflare with a VPS? ### 1. Keep the origin architecture simple Your application can remain on a normal Linux VM while Cloudflare handles the public DNS and proxy layer. That is attractive for small teams because you do not need to redesign the application around an edge runtime just to gain CDN, TLS, and DDoS-protection benefits. ### 2. Hide the origin IP from normal proxied DNS responses When an A, AAAA, or CNAME web record is proxied, users normally resolve Cloudflare addresses rather than the origin address. This does not magically make the origin impossible to discover. Old DNS records, direct services, email records, certificates, application leaks, and other configuration can still reveal it. Treat origin protection as a firewall and architecture problem, not only a DNS setting. ### 3. Add a global edge in front of one VPS region A VPS may run in one datacenter while Cloudflare operates a distributed edge network. Static/cacheable content can benefit from edge delivery even though dynamic requests still return to the origin server when they are not served from cache. ### 4. Separate public traffic from application ports A clean architecture exposes only the reverse proxy publicly: | Port | Service | Public? | |---:|---|---| | 22 | SSH | Restrict where possible | | 80 | HTTP / redirect | Yes | | 443 | HTTPS | Yes | | 3000 | Node.js app | No | | 5432 | PostgreSQL | No | | 3306 | MySQL | No | The app can listen on `127.0.0.1:3000`, while Nginx receives public traffic on 80/443. ## Cloudflare + VPS vs Cloudflare Workers A common source of confusion is whether Workers removes the need for a VPS. Sometimes it does. Sometimes it does not. Choose a Cloudflare-native runtime when your application fits that execution model and you want to avoid operating a full server. Choose a VPS when you need things such as: - a persistent operating system; - custom system packages; - Docker Compose; - long-running worker processes; - custom network services; - self-hosted databases; - filesystem-level control; - software that expects a conventional server environment. Many production systems use both: Workers or other edge logic for selected functions, plus a VPS or cloud VM for the main application and stateful services. ## Cloudflare + VPS vs Cloudflare Pages Cloudflare Pages is well suited to frontend and static-site workflows, with server-side capabilities available through the broader Cloudflare developer platform. A VPS is a better fit when the deployment requires full OS control or when the application stack does not map naturally to a managed edge platform. If all you are hosting is a static frontend, a VPS may be unnecessary. If you need a normal server, Cloudflare Pages is not a drop-in replacement for one. ## What VPS should you use with Cloudflare? Cloudflare itself does not require a special “Cloudflare VPS.” The server should be chosen around the workload. For a small API, dashboard, SaaS MVP, or Node.js application, look at: - enough RAM for the runtime and peaks; - sufficient CPU for normal and burst load; - fast storage; - predictable bandwidth policy; - backups and snapshots; - firewall controls; - a region close to the application's users or data dependencies; - an upgrade path as the workload grows. A simple starting point for many small applications is 2 vCPU with 2–4 GB RAM, but application requirements should drive the final size. On Raff, Linux VMs provide full root access, NVMe storage, firewall controls, private networking, backups/snapshots, and unmetered VM bandwidth. You can use a Raff VM as the origin while Cloudflare remains the public edge. ## A recommended Cloudflare VPS architecture For a single-server application, keep the first version straightforward: ```text Internet ↓ Cloudflare proxied DNS ↓ HTTPS Nginx / Caddy on VPS ↓ Application on localhost ↓ Database or external managed database ``` The responsibilities should be clear. **Cloudflare:** - DNS - proxying - edge TLS - caching where appropriate - security rules **VPS:** - operating system - application runtime - reverse proxy - process management - application logs - local firewall - backups for server-side state Do not expose every backend service just because Cloudflare is in front of the website. ## Full (strict) TLS is the production default For a normal VPS origin, the preferred request path is: ```text Browser → HTTPS → Cloudflare → HTTPS → VPS ``` Cloudflare's **Full (strict)** mode validates the certificate presented by the origin. The VPS can use a publicly trusted certificate such as Let's Encrypt or an appropriate Cloudflare Origin CA certificate when traffic is designed to remain behind Cloudflare. Avoid treating Flexible SSL as the standard production configuration. It can leave the Cloudflare-to-origin connection on HTTP and can create redirect problems when the origin is also trying to enforce HTTPS. ## Should you restrict ports 80 and 443 to Cloudflare IPs? This can reduce direct access to the origin, but it must be implemented carefully. If you restrict web traffic to Cloudflare's published IP ranges: - maintain the allowlist when Cloudflare updates it; - keep your certificate-renewal method in mind; - have an emergency access path; - test health checks and monitoring; - do not accidentally lock yourself out of required origin traffic. For many small deployments, start with a correct app binding, firewall, HTTPS, SSH restrictions, and proxied DNS. Add Cloudflare-only origin filtering when the operational process is ready to maintain it. ## Can Cloudflare protect a VPS from DDoS attacks? Cloudflare can protect **proxied supported web traffic** before it reaches the VPS. That is one of the major reasons to put Cloudflare in front of a public website or API. But Cloudflare cannot protect a service that bypasses the proxy simply because the domain also uses Cloudflare. Examples of origin exposure include: - public SSH; - a database port exposed to the internet; - a game server or other unsupported protocol connected directly to the origin; - users connecting directly to the VPS IP; - unproxied DNS records. Secure those services at the VPS and network layer. ## Does Cloudflare make VPS bandwidth free? No. Cloudflare may serve cached responses from its edge, which can reduce traffic reaching your origin. But dynamic and uncached traffic can still reach the VPS, and your VPS provider's bandwidth policy still applies. If your VM provider meters egress, model that separately. Raff's current VM plans use unmetered VM bandwidth, which can simplify cost forecasting for an origin behind Cloudflare. ## When Cloudflare + VPS is a good fit This architecture is especially useful for: - SaaS MVPs; - APIs; - dashboards; - customer portals; - WordPress or PHP applications; - Node.js, Python, Go, Java, and .NET applications; - Docker Compose deployments; - self-hosted developer tools; - small business websites with backend services; - MSP-managed customer applications. It works well when the team wants normal server control without giving up Cloudflare's DNS and edge capabilities. ## When you may not need a VPS A VPS is unnecessary if the application fits completely inside a managed hosting or edge platform and you do not need server-level control. Examples include: - a static marketing site; - a simple frontend deployed to a managed platform; - an edge-native application built entirely around Workers-compatible services; - a small site where server administration would add more work than value. Do not buy a VPS only because the term appears in a tutorial. Use it when the workload actually needs a server. ## Cloudflare VPS setup: high-level checklist If you decide to combine the two, the deployment sequence is: 1. Create the VPS and secure SSH. 2. Install the application runtime. 3. Bind the application to localhost/private networking. 4. Install Nginx or Caddy as the reverse proxy. 5. Point Cloudflare DNS to the VPS public IP. 6. Enable proxying on public web records. 7. Install an origin certificate. 8. Set Cloudflare SSL/TLS to Full (strict). 9. Keep database and application-runtime ports private. 10. Test HTTPS, reboot behavior, backups, logs, and rollback. For every command and verification step, continue with [Host Your App on a VPS with Cloudflare: Step-by-Step Tutorial](/learn/tutorials/host-app-on-vps-with-cloudflare). ## Cloudflare VPS FAQs ### Does Cloudflare have a VPS? Cloudflare does not offer a traditional general-purpose VPS with a persistent operating system and root access. Its developer platform provides application-hosting and edge-computing services with a different operating model. ### What is Cloudflare VPS hosting? The phrase usually describes a VPS from a compute provider placed behind Cloudflare DNS, proxying, TLS, CDN, and security services. ### How much does Cloudflare VPS cost? There is no single Cloudflare VPS price. You pay your VPS provider for compute and separately pay Cloudflare if you use a paid plan or usage-based Cloudflare products. Many small setups can start with a VPS plus Cloudflare's Free plan. ### Can I connect Cloudflare to a VPS? Yes. Point the relevant DNS record to the VPS, enable Cloudflare proxying for supported web traffic, configure HTTPS on the origin, and use Full (strict) TLS for production. ### Can Cloudflare replace a VPS? Cloudflare can replace a VPS for some edge-native or managed-hosting use cases. It does not replace a conventional server when you need full OS control, Docker, arbitrary packages, persistent system services, or other traditional VM capabilities. ### Is Cloudflare good for VPS hosting? Cloudflare and VPS hosting complement each other well. The VPS runs the application while Cloudflare handles the public edge. The combination is especially useful for teams that want full server control plus DNS, CDN, TLS, and edge security. ## Conclusion **Cloudflare VPS** is best understood as an architecture, not a Cloudflare VM product. Cloudflare handles the public edge. A VPS provider supplies the actual server. Together they create a simple pattern for developers who need full compute control while still benefiting from Cloudflare's DNS, proxy, TLS, caching, and security features. If your workload needs a traditional server, choose the VPS based on CPU, RAM, storage, bandwidth, backups, support, and region. Then place Cloudflare in front of it. If you want to build the configuration now, follow the [Cloudflare + VPS step-by-step tutorial](/learn/tutorials/host-app-on-vps-with-cloudflare). If you are deciding whether you need a server at all, read [Cloudflare vs VPS: When Your App Needs a Server](/blog/cloudflare-vs-vps-why-developers-still-need-a-server). For a Raff origin server, see [Raff Cloud VMs](/products/raff-vm) and [current VM pricing](/pricing). --- ### Should You Run Kubernetes on a VPS in 2026? URL: https://rafftechnologies.com/blog/should-i-run-kubernetes-on-a-vps Published: 2026-03-12T00:00:00.000Z Description: Should You Run Kubernetes on a VPS in 2026? Kubernetes on a VPS makes sense when you need real container orchestration, control over your infrastructure, and predictable VM-level costs — but it is usually the wrong first step for a simple application. At Raff Technologies, we see Kubernetes as an upgrade path, not a badge of seriousness. Start with the simplest system that keeps your product reliable, then move to Kubernetes when the operational value is greater than the operational burden. Kubernetes on a VPS means running your Kubernetes nodes on virtual private servers instead of using a managed Kubernetes service. That gives you control over the operating system, networking, storage, upgrades, and cluster configuration. It also means your team owns the failure modes: node health, certificates, ingress, backups, persistent volumes, monitoring, security patches, and recovery. That trade-off is the heart of the decision. A VPS-based Kubernetes cluster can be efficient, flexible, and surprisingly capable. It can also become a small team’s most expensive “cheap” infrastructure choice if it turns every deployment into a cluster maintenance session. ## The Short Answer: Yes, But Not Too Early You should run Kubernetes on a VPS if your application has multiple services, needs orchestration across more than one machine, and your team is comfortable operating infrastructure. You should not run Kubernetes on a VPS just because Kubernetes is popular. This is where many teams lose time. They begin with a simple web app, one database, one background worker, and maybe a reverse proxy. Then they add Kubernetes before they have a deployment problem that Kubernetes actually solves. The result is not “cloud-native.” It is usually one developer debugging YAML, ingress, DNS, certificates, storage classes, and node pressure instead of shipping product. Our practical rule is this: if a single [Linux VPS](/products/linux-vm) with Docker Compose, Nginx, backups, and monitoring can run your workload reliably, stay there. If you are coordinating many services, need repeatable deployments across nodes, and want a production-like orchestration layer, Kubernetes becomes reasonable. ## What Running Kubernetes on a VPS Actually Means Running Kubernetes on a VPS means each node in your cluster is a virtual machine. A small setup might be one VPS running K3s for learning, development, or a lightweight internal tool. A more realistic production-style setup might use three VPS nodes, private networking, external backups, proper monitoring, and a clear storage strategy. That sounds simple until you list what you now own: * Node provisioning and operating system updates * Kubernetes installation and upgrades * Container runtime behavior * Ingress and TLS certificates * Cluster networking and firewall rules * Persistent storage and backup recovery * Monitoring, logging, and alerting * Security hardening and access control * Disaster recovery when a node fails This is not a reason to avoid Kubernetes. It is a reason to be honest about it. Kubernetes is excellent at orchestrating containers. It is not a replacement for infrastructure operations. ## The Real Decision Is Not VPS vs Kubernetes The real decision is not “Should I use a VPS or Kubernetes?” It is “How much operational complexity does my application justify right now?” For many small teams, the best path looks like this: | Stage | Best fit | Why | |---|---|---| | One app, one database, one worker | Single VPS + Docker Compose | Simple, cheap, easy to debug | | Several containers, still one server | Larger VPS + Docker Compose | More capacity without cluster overhead | | Multiple services needing orchestration | K3s on VPS nodes | Lightweight Kubernetes with lower overhead | | Mission-critical production platform | Managed Kubernetes or well-designed HA cluster | Better resilience and operational maturity | The mistake is skipping the early stages because Kubernetes feels more professional. Professional infrastructure is not the most complex infrastructure you can build. Professional infrastructure is the one your team can understand, maintain, and recover under pressure. ## When Kubernetes on a VPS Is a Good Idea Kubernetes on a VPS is a good idea when you have a real orchestration problem. That usually means you are running multiple services that need independent deployment, restart behavior, service discovery, or horizontal scaling. For example, a SaaS product with an API, frontend, background workers, internal admin tools, scheduled jobs, and several supporting services may benefit from a cluster model. It is also a good fit when your team wants to learn Kubernetes in an environment that behaves more like production than a laptop. Local tools are useful, but they hide parts of the operational picture. A VPS-based cluster forces you to think about networking, public IPs, firewall rules, storage, monitoring, and recovery. Kubernetes on a VPS can also make sense for cost-conscious teams. You can build a small cluster without paying for a large managed platform. On Raff, for example, a realistic lightweight K3s starting point would be a CPU-Optimized VM with 2 vCPU, 4 GB RAM, and 80 GB NVMe SSD at $27.99/month. A three-node starter cluster using that same VM size would be $83.97/month before optional snapshots, backups, external storage, or load balancing. For a team that understands Kubernetes, that can be a reasonable trade-off. ## When Kubernetes on a VPS Is the Wrong Move Kubernetes on a VPS is the wrong move when you are using it to solve a problem you do not have yet. If your application is still simple, Docker Compose is often enough. A single VM can run a frontend, backend, database, Redis, and Nginx with a clear backup plan. That architecture may not be fashionable, but it is understandable. A small team can SSH into the machine, inspect logs, restart services, restore a backup, and keep moving. It is also the wrong move if your team does not want to own infrastructure operations. Self-managed Kubernetes is not “set and forget.” Certificates expire. Nodes need patches. Pods get evicted. Storage behaves differently than you expect. Ingress controllers need maintenance. A small misconfiguration can create large debugging sessions. The most dangerous setup is a one-node “production” Kubernetes cluster that people assume is highly available. It is not. If the node dies, the workloads die with it. Kubernetes can restart pods, but it cannot restart a failed physical or virtual machine unless you have additional infrastructure around it. ## K3s Is Usually the Right Starting Point If you decide to run Kubernetes on VPS infrastructure, start with K3s unless you have a specific reason not to. K3s is a lightweight Kubernetes distribution designed to reduce operational overhead while keeping the Kubernetes API familiar. It packages many useful components by default and is widely used for edge, development, homelab, CI, and resource-constrained environments. For VPS users, that matters because the control plane should not consume the same resources your application needs. This does not mean K3s makes resource planning optional. The official K3s requirements are baseline requirements for K3s and its packaged components; they do not include the CPU and memory your workloads consume. In plain English: do not size your VPS only for Kubernetes. Size it for Kubernetes plus your application. A practical starting point is: | Use case | Suggested setup | |---|---| | Learning Kubernetes | 1 VPS, K3s, no production data | | Internal tool or staging | 1 larger VPS, K3s, backups, monitoring | | Small production workload | 2–3 VPS nodes, K3s, private networking, external backup plan | | Serious production platform | HA control plane, worker separation, load balancing, tested recovery | If you are using full kubeadm-based Kubernetes, plan more carefully. Production high availability usually requires multiple control-plane machines, an odd number of etcd members, reliable networking, and a load balancer in front of the API server. That is no longer “just run Kubernetes on a VPS.” That is a real platform project. ## The Cost Comparison That Matters Kubernetes does not only cost money. It costs attention. A single Raff CPU-Optimized VM at $27.99/month can run a small Docker Compose deployment with clear operations. A three-node K3s setup using the same VM size starts at $83.97/month. The price difference is not the only cost. You also add upgrade planning, cluster monitoring, ingress design, persistent volume decisions, and more failure modes. That does not make Kubernetes expensive. It makes Kubernetes honest. If Kubernetes helps your team deploy faster, isolate services, recover workloads, and standardize operations, the extra cost is justified. If it only adds a cluster around a simple app, you are paying for complexity without receiving the benefit. This is why we prefer decision-based infrastructure planning. Start with the deployment model that fits the stage of your product. Then upgrade when the product demands it. ## What About Managed Kubernetes? Managed Kubernetes exists because many teams want the Kubernetes API without owning every piece of the control plane. Raff’s [Kubernetes product](/products/kubernetes) is designed for teams that want managed container orchestration without starting from raw VM assembly. That path makes sense when your team wants Kubernetes as a platform, but does not want to spend its time maintaining the platform itself. Until then, a VPS-based K3s cluster is useful for learning, staging, internal tools, and cost-sensitive workloads. It gives you control. It teaches you the real moving parts. It can run real applications. But once uptime, scaling, multi-node resilience, and team workflows become critical, managed Kubernetes becomes more attractive. ## A Practical Decision Framework Use this framework before you choose Kubernetes on a VPS. Choose Docker Compose on a VPS if: * You run one application or a small group of containers * You do not need multi-node orchestration * You want the fastest path to production * Your team is small and prefers simple operations * You can handle restarts, backups, and deployments with straightforward scripts Choose K3s on VPS nodes if: * You want to learn Kubernetes properly * You run multiple services with independent deployments * You need service discovery, ingress, and orchestration * You accept responsibility for upgrades and cluster health * You want lower raw infrastructure cost than many managed options Choose managed Kubernetes if: * Your team needs Kubernetes but not control-plane maintenance * Reliability and recovery matter more than raw VM cost * You need autoscaling, monitoring, logging, and upgrade workflows * You are building a platform for multiple developers or teams * You want to spend less time operating the cluster itself The right answer depends on your stage. A startup validating a product should not copy the infrastructure pattern of a mature platform team. A mature platform team should not run mission-critical workloads on a casual one-node experiment. ## What This Means for You If you are deciding today, start with the smallest architecture that gives you reliable deployment and recovery. For many teams, that means launching a [Linux VM on Raff](/products/linux-vm), running Docker Compose, adding backups, and keeping the architecture simple. You can see the current VM options on the [pricing page](/pricing), then scale the VM or move into K3s when the workload becomes more complex. If you already know you need Kubernetes, treat VPS-based Kubernetes as a self-managed platform. Choose the VM size based on both cluster overhead and application requirements. Use private networking where possible. Plan backups before you deploy stateful workloads. Do not call a one-node cluster highly available. My recommendation is direct: run Kubernetes on a VPS when it solves a coordination problem, not when it only makes the architecture look more advanced. Start simple, move deliberately, and let your infrastructure complexity follow your product complexity — not the other way around. --- ### Why Backup Is a Sales Promise for MSPs, Not a Checkbox URL: https://rafftechnologies.com/blog/why-backup-is-a-sales-promise-for-msps Published: 2026-04-14T00:00:00.000Z Description: Why Backup Is a Sales Promise for MSPs, Not a Checkbox Most MSPs do not get blamed because a backup job existed. They get blamed because a recovery promise failed. That is the real reason I do not think backup should be treated as a checkbox service. For an MSP, backup is not only a technical control. It is a sales promise, a trust promise, and in the worst moments, a reputation promise. At Raff Technologies, that distinction matters because infrastructure decisions change what an MSP can confidently sell, what it can defend in front of a client, and what it can recover when something has already gone wrong. A backup is only useful if the client can get back to a working state inside an acceptable time window, with acceptable data loss, and without chaos. That is why I think MSPs make a mistake when they package backup as if it were only about scheduled jobs or storage usage. Clients do not buy “successful backup completion.” They buy confidence that their systems, files, and databases can come back when it matters. This is also why I think backup should be discussed alongside restore discipline, snapshots, object storage, and recovery design. If you sell backup without a credible recovery story, you are not really selling resilience. You are selling a dashboard status. ## The Client Does Not Buy the Backup Job This is the first mindset shift I would make if I were building an MSP offer today. Your client does not wake up wanting incremental schedules, retention policies, or storage tiers. They want a simpler answer to a harder question: “If something goes wrong, can you get us back?” That is the product. The technical stack behind it matters, of course. But the commercial value is not the backup file itself. The value is the confidence that a recovery path exists, is understood, and has enough operational discipline behind it that your team can execute under pressure. That is why I think backup is a sales promise. It sits in the proposal. It influences whether a client signs. It affects whether they trust you with production systems. And when an incident happens, it becomes the promise they judge most harshly. This is also where a lot of MSP packaging goes wrong. “Daily backups included” sounds fine in a pricing table. But it says almost nothing about recovery quality. Daily backups do not tell the client: * how fast restore starts * what data-loss window is realistic * whether the backup is isolated enough to matter * whether the team has tested the recovery path * whether a bad change replicated everywhere before anyone noticed Those are the questions that decide whether backup feels like protection or theater. ## Backup Is Really About Defensibility I think this is the most underrated part of managed backup services. Backup is not only about whether your system can recover. It is also about whether your team can defend its design after an incident. That means the infrastructure has to make sense when someone starts asking uncomfortable questions: Where was the backup stored? Was it on the same server? How recent was it? Was it tested? Was there a snapshot before the risky change? How long was the recovery supposed to take? Who owned the runbook? If an MSP cannot answer those questions clearly, then the service was never really mature enough to sell with confidence. That is one reason I like the separation Raff already makes across [Linux Virtual Machines](/products/linux-vm), [Data Protection](/products/data-protection), and [Object Storage](/products/object-storage). It encourages a cleaner conversation about what belongs on the runtime system, what belongs in backup policy, and what should live off-server as part of a more durable recovery design. To me, that separation matters commercially as much as technically. It gives an MSP a more defensible story. ## Snapshots, Backups, and Object Storage Should Not Be Sold as the Same Thing This is another place where I think many MSP offers get blurry too quickly. A snapshot is not the same thing as a backup. And neither is the same thing as object storage. A snapshot is usually the fastest tool for rollback around risky changes. It is perfect for “we are about to update, migrate, patch, or reconfigure something and want a point-in-time safety net.” That makes it valuable operationally, especially before admin work. A backup is broader recovery protection. It is what supports retention, longer rollback windows, and restoration after bigger incidents. That is the system clients usually think they are buying when they hear the word “backup.” Object storage solves a different part of the problem again. It gives you a cleaner place for exports, archives, longer-lived copies, and backup designs that do not pretend everything should remain tied to the same VM disk forever. Raff’s own object storage direction already reflects this kind of thinking: storage should not only exist, it should support practical operations and cleaner service design. :contentReference[oaicite:3]{index=3} That is why I would never bundle these three things into one vague sentence like “your data is protected.” That sentence may sell once. It will not defend you later. A better MSP position is more honest: * snapshots help you roll back quickly * backups help you recover after bigger problems * object storage helps you keep recovery data in a cleaner, more durable place outside the core server path That is a service promise a serious client can understand. ## The Real Product Is Restore Discipline This is where I think the entire conversation becomes more useful. If you want to know whether an MSP actually has a backup service, do not start by asking whether backup jobs run. Ask whether restore discipline exists. Can the team restore to a clean target? Can it estimate recovery time honestly? Can it validate the recovered state? Can it explain what gets restored first? Can it prove the backups are not only present but usable? That is the difference between backup as a checkbox and backup as an operational product. At Raff, I would frame this as a design question before a tooling question. Build the infrastructure so recovery is practical, then build the service package so the promise is clear. That means a simple server layer, well-defined snapshots, real backup policy, and an off-server storage path where appropriate. It also means not pretending a green status light is the same thing as readiness. This is why I think the pillar guide [Cloud Server Backup Strategies: Snapshots, RPO, and Recovery Planning](/learn/guides/cloud-server-backup-strategies) is the right center of gravity for this cluster. It gets closer to the real decision: what kind of recovery posture are you actually building? Then the sibling pieces become clearer: [Cloud Snapshots vs Backups: What’s the Difference?](/learn/guides/snapshots-vs-backups-cloud-server) for recovery-layer clarity, and [S3-Compatible Object Storage Use Cases for Developers](/learn/guides/s3-compatible-object-storage-use-cases-for-developers) for where backup-related storage strategy gets cleaner. ## Cheap Backup Is Often Expensive for an MSP This is the commercial part many providers still avoid saying directly. Cheap backup is often expensive for the MSP. Not because storage itself costs more. Because weak backup design creates labor, support drag, and trust damage. An MSP loses money when: * restores take too long * backup scope is misunderstood * retention is unclear * recovery steps are manual and inconsistent * client expectations were sold too loosely * the infrastructure forces the team into ticket-heavy cleanup This is why I do not like selling backup purely as a low-cost add-on. The cheaper the promise sounds, the more likely the client assumes it is universal and complete. Then the first real incident reveals the missing qualifiers. A better model is to package backup around outcome language: recovery confidence, restore speed, scope clarity, retention visibility, and pre-change rollback safety. That is also where predictable infrastructure matters. Raff’s pricing model and infrastructure building blocks make it easier to price around service outcomes rather than burying backup inside vague cost assumptions. The current CPU-Optimized entry tier starts at **$9.99/month** for **1 vCPU, 1 GB RAM, and 25 GB NVMe SSD**, and Tier 2 starts at **$13.99/month** for **1 vCPU, 2 GB RAM, and 50 GB NVMe SSD**. That gives an MSP a realistic low-cost place to standardize small client environments or isolated recovery tests without jumping immediately into oversized infrastructure decisions. :contentReference[oaicite:4]{index=4} ## The MSP Opportunity Is Bigger Than “Backup Included” What I find interesting is that managed backup and disaster recovery remain one of the strongest service lanes for MSPs, even as the threat environment gets worse and more identity-driven. That means clients need stronger answers, not broader marketing language. :contentReference[oaicite:5]{index=5} So the opportunity is not just to say: “we include backup.” The opportunity is to say: “we have a defined recovery posture, and we can explain it.” That changes the conversation from feature checklist selling to trust-based selling. It also helps MSPs differentiate without pretending to be a giant enterprise platform. A smaller provider can still win if its recovery story is simpler, clearer, and more believable than a bigger competitor’s bundle of vague promises. That is why I think this matters for Raff as well. MSPs are not only buying compute. They are buying an infrastructure base they can package into a service promise of their own. The more that infrastructure supports clear recovery design, the easier it becomes for them to sell with confidence. ## What This Means for You If you run an MSP, I would stop asking whether your package “includes backups.” I would ask four better questions: 1. Can we explain our recovery promise in plain English? 2. Can we separate snapshots, backups, and off-server storage clearly? 3. Can we test restores in a way we would defend in front of a client? 4. Can our infrastructure support that promise without margin-killing complexity? That is the level where backup becomes a real service. If you are building that kind of MSP offer on Raff, I would start with a simple [Linux VM](/products/linux-vm), define the core recovery posture using [Cloud Server Backup Strategies: Snapshots, RPO, and Recovery Planning](/learn/guides/cloud-server-backup-strategies), separate rollback from recovery with [Cloud Snapshots vs Backups: What’s the Difference?](/learn/guides/snapshots-vs-backups-cloud-server), and use [Object Storage](/products/object-storage) or the current [pricing](/pricing) page to shape a cleaner service package around retention and off-server copies. Because in the end, clients do not stay with an MSP because a backup job ran last night. They stay because when something breaks, the MSP can bring them back. And that is not a checkbox. That is the sale. --- ### Identity Is the New Front Door — What MSPs Should Change First URL: https://rafftechnologies.com/blog/dentity-is-the-new-front-door-for-msps Published: 2026-04-14T00:00:00.000Z Description: Identity Is the New Front Door — What MSPs Should Change First The first thing I would change in a small MSP environment today is not the SIEM, the backup SKU, or the dashboard stack. I would reduce the number of identity-controlled admin paths exposed to the public internet. That sounds simple, but it changes almost everything. At Raff Technologies, we spend a lot of time thinking about how infrastructure should be arranged so that a mistake, a stolen session, or a compromised credential does not immediately become an incident with a wide blast radius. For MSPs, that question matters even more, because one admin identity rarely touches just one system. It often touches several clients, multiple control panels, backup tools, remote access paths, and internal documentation systems. Identity security is no longer only about passwords or MFA checkboxes. It is the control layer that decides who can reach what, from where, and with how much privilege. If that layer is too broad, too exposed, or too fragmented, your environment becomes harder to defend even when every individual tool looks “secure enough” on paper. ## More Attacks Begin With Valid Access, Not Broken Locks One of the most important mindset shifts for MSPs is this: many modern attacks do not begin with an attacker “breaking in” through a dramatic exploit. They begin with access that looks valid enough to move forward. That access might come from a phished session, a weak remote admin path, a stale account, a poorly scoped privileged role, or an admin panel that should never have been internet-facing in the first place. Once an attacker is operating through identity, the question is no longer “Did the firewall block the packet?” It becomes “What can this identity touch now?” That is why I think “identity is the new front door” is not just a catchy line. It is a design problem. A common mistake here is treating identity as a separate security layer instead of treating it as part of network architecture. In practice, identity and exposure are tied together. If a privileged path is publicly reachable, identity abuse becomes far more dangerous. If that same path is reachable only through a private network segment with narrow firewall rules and fewer entry points, the operational risk changes immediately. ## The Real MSP Problem Is Too Many Exposed Admin Paths If I were auditing a typical small MSP environment, I would not start by asking which security products are installed. I would start by listing every admin path that is still publicly reachable. That usually includes things like: * SSH on client servers * RDP on Windows workloads * database admin interfaces * backup consoles * control panel logins * remote management tools * monitoring dashboards * web apps with hidden but public `/admin` routes Individually, each one may have a justification. Together, they often create a messy access surface that depends too heavily on users always authenticating correctly and attackers never getting a foothold. That is too much trust in the public edge. A cleaner design is to separate **customer-facing traffic** from **management traffic** early. Public services can stay public where needed. Administrative paths should move behind stricter boundaries. This is where I think many MSP environments drift into avoidable risk. They grow by adding tools faster than they standardize access patterns. A portal gets exposed because it is convenient. A remote admin path stays open because a migration was rushed. A shared operational habit becomes permanent because it “still works.” Then one compromised identity inherits a much larger map than anyone intended. ## What I Would Change First If the goal is to reduce identity-driven risk quickly, I would change four things before I bought another product. ### 1. Separate Public Traffic From Management Traffic Do not keep SSH, RDP, database access, and internal dashboards in the same exposure model as the public application. If a path exists only for operators, treat it like an operator path. That means moving it off the public lane where possible and making it reachable only from a narrower administrative boundary. Raff already has good foundational reading for this in [Private Networking in Cloud: Public vs Private Traffic](/learn/guides/private-networking-public-vs-private-traffic) and [Understanding Private Cloud Networks: VPC Design and Best Practices](/learn/guides/understanding-private-cloud-networks). A common mistake here is leaving a service public “temporarily” because firewall rules are in place. Temporary public management paths have a habit of becoming permanent. ### 2. Reduce the Number of Publicly Reachable Admin Interfaces This is the fastest cleanup with the clearest payoff. If an admin interface does not need to be internet-facing, remove it from the public path. That includes control surfaces people forget about because they are not part of the main application: internal Grafana instances, backup interfaces, phpMyAdmin, custom dashboards, direct database listeners, file manager panels, and default service ports. The fewer privileged surfaces a stolen identity can reach directly, the better. ### 3. Standardize How Admin Access Works MSPs often inherit inconsistent access patterns across clients. One server uses passwords, another uses SSH keys, another still has an open management port restricted only by IP, and a fourth depends on tribal knowledge inside the team. That inconsistency becomes operational debt very quickly. I would standardize admin access in the same order every time: * key-based access where applicable * minimal exposed ports * clear host naming and access ownership * narrow firewall rules * documented admin path expectations * fast removal of stale accounts and exceptions If your team needs a refresher on the basics, [How to Set Up SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04) and [How to Secure an Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server) are exactly the kind of foundation I would want in the cluster. ### 4. Treat Firewall Design as Part of Identity Design This is one point I think gets overlooked. Firewall rules are not only network policy. They shape what a compromised identity can attempt next. If your firewall still allows broad admin reachability, identity abuse has room to move. If your firewall policy is narrow and intentional, the same compromised session has fewer useful paths available. That is why I would review identity and firewall design together, not separately. Raff’s own guide [Firewall Best Practices for Cloud Servers](/learn/guides/firewall-best-practices-cloud-servers) fits naturally here because firewall discipline is one of the simplest ways to reduce what a valid-but-abused identity can touch. ## Private Networking Changes the Identity Problem This is the part I would want MSP operators to take seriously. Private networking does not “solve identity” on its own. But it changes the shape of the problem in a very practical way. Instead of trusting public reachability plus authentication to carry the whole burden, you reduce exposure first and let identity operate inside a narrower, better-defined environment. That is a much better place to defend from. On a small cloud layout, private networking helps you keep databases, internal services, admin utilities, and east-west traffic off the public edge. That means a compromised admin credential has fewer immediate paths if the attacker is not already inside the right network boundary. It also makes your diagrams cleaner, your runbooks clearer, and your client explanations easier to defend. From a design perspective, that is usually a better first move than adding more security tooling to an already overexposed layout. I have seen teams do the reverse. They add one more alerting layer, one more monitoring product, one more agent, one more console, but they still leave too many sensitive entry points reachable from the public side. That is expensive complexity without enough exposure reduction. ## Tool Sprawl Makes Identity Harder to Defend There is another reason this topic matters for MSPs: the more fragmented the access model becomes, the harder it is to know which identity actually has meaningful control. This is not just about convenience. It is about visibility. If one engineer signs into the backup console one way, the hypervisor another way, the remote support tool a third way, and the client application environment a fourth way, your team ends up with too many places where privilege exists and too many places where cleanup gets missed. That increases risk in quiet ways: * old accounts survive too long * admin rights stay broader than they should * exception paths never get removed * operators stop trusting the map of who can reach what For MSPs, this gets worse because environments are repeated across clients, but never repeated perfectly. Small inconsistencies multiply. That is why I think the first architectural win is not “better identity technology” in the abstract. It is fewer exposed decisions. Fewer public admin paths. Fewer special cases. Fewer control surfaces that depend on memory instead of design. ## What This Means for You If you run an MSP, I would start with one question: **Which privileged paths in our environment are still publicly reachable for convenience rather than necessity?** That question is much more useful than asking whether you “have identity security.” If the answer includes SSH, RDP, database access, backup portals, or internal dashboards, I would fix exposure first. Then I would tighten admin access patterns. Then I would standardize firewall behavior. Then I would review account scope and stale privileges. That order matters. If you want to build that way on Raff, start with a simple [Linux VM](/products/linux-vm), use [Private Cloud Networks](/products/private-cloud-networks) to move management traffic off the public edge, and keep your cost model clean through [Raff pricing](/pricing). A small isolated admin, bastion, or utility environment can start on a CPU-Optimized Tier 1 VM at **$9.99/month** for **1 vCPU, 1 GB RAM, and 25 GB NVMe SSD**. If you want more room for tooling, logs, or light internal services, Tier 2 starts at **$13.99/month** for **1 vCPU, 2 GB RAM, and 50 GB NVMe SSD**. Those numbers matter because access cleanup should not require overbuilding. It should be practical enough that you actually do it. If you want a clean next reading path, I would pair this post with [Private Networking in Cloud: Public vs Private Traffic](/learn/guides/private-networking-public-vs-private-traffic), [Understanding Private Cloud Networks: VPC Design and Best Practices](/learn/guides/understanding-private-cloud-networks), [Firewall Best Practices for Cloud Servers](/learn/guides/firewall-best-practices-cloud-servers), and [How to Secure an Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). Because right now, the most useful change for many MSPs is not buying another security layer. It is making the front door smaller. --- ### Why Microsoft Licensing Matters When Choosing a Windows VM Provider URL: https://rafftechnologies.com/blog/why-microsoft-licensing-matters-windows-vm-provider Published: 2026-05-09T00:00:00.000Z Description: Why Microsoft Licensing Matters When Choosing a Windows VM Provider Microsoft licensing should be part of the Windows VM decision before you launch, not after the server is already running. That may sound like a small detail, but it is not. When a business chooses a Windows VM provider, it usually compares CPU, RAM, storage, bandwidth, support, deployment speed, and monthly price. Those things matter. But if the workload depends on Microsoft software, licensing clarity matters just as much. At Raff Technologies, this became even more important after Raff LLC became a Microsoft SPLA Partner. Through our Microsoft Service Provider License Agreement, Raff can provide hosted Microsoft software licensing through SPLA where applicable. A Windows VM is not only a virtual machine with Windows installed. It is a licensed Microsoft software environment running in a hosted cloud setting. That changes the buying decision. ## The Hidden Question Behind Every Windows VM Most Windows VM buyers start with a practical need. They need to run a business application. They need Remote Desktop access. They need to test software on Windows Server. They need to host a legacy application. They need a stable Windows environment that can be accessed from anywhere. Those are all valid reasons to use a hosted Windows VM. But behind each use case is a licensing question: Who is responsible for the Microsoft license? That question should be answered before the workload becomes important. A provider may offer a Windows server, but the customer still needs to understand whether that server is using an evaluation license, provider-supplied SPLA licensing, bring-your-own-license, or another valid licensing path. If the provider cannot explain that clearly, the customer inherits uncertainty. And uncertainty is not a good foundation for business infrastructure. ## Why Licensing Is Part of Infrastructure Quality Licensing may not look like a product feature at first. You cannot see it in the same way you see a dashboard, VM size, storage plan, or login screen. But for Windows workloads, licensing clarity is part of infrastructure quality. A properly sized VM with unclear licensing is still risky. A fast server with vague Microsoft software rights is still incomplete. A cheap Windows VPS can become expensive if the customer later discovers that the workload was not licensed correctly for production use. That is why Windows VM buyers should treat licensing as a trust signal. A serious provider should be able to explain: * Which Windows Server versions are available. * Whether the default license is evaluation, SPLA, or BYOL. * Whether the workload is suitable for production. * What happens after the evaluation period ends. * Whether Remote Desktop Services creates additional licensing needs. * Whether SQL Server or Microsoft 365 Apps introduce separate licensing questions. * What documentation or confirmation the customer should keep. This is not paperwork for the sake of paperwork. It is operational clarity. ## The Three Common Windows VM Licensing Paths Most hosted Windows VM decisions come down to three practical licensing paths. | Licensing path | Best for | Production-ready? | Who handles licensing? | |---|---|---:|---| | Evaluation license | Testing, demos, learning, short-term trials | No | Microsoft evaluation terms | | SPLA through provider | Hosted production workloads | Yes, where applicable | Service provider | | BYOL | Customers with eligible Microsoft licenses | Yes, if eligible | Customer | These paths are not interchangeable. An evaluation license can be useful when you are testing a workload or building a proof of concept. It gives you time to confirm whether the application works before committing to a production licensing path. SPLA is often the practical path when the provider supplies the eligible Microsoft software license for a hosted service. BYOL can work when the customer already owns eligible Microsoft licenses and has the right usage rights, such as Software Assurance or License Mobility where required. The important point is simple: Owning a Microsoft license does not automatically mean you can use it in every hosted cloud scenario. That is why BYOL should be checked carefully. For a deeper explanation of the three paths on Raff, read our guide: [Windows Server Licensing on Raff: Evaluation, SPLA, and BYOL Explained](/windows-server/windows-licensing). ## Why SPLA Matters The Microsoft Services Provider License Agreement, or SPLA, exists for hosted software service scenarios. Microsoft describes SPLA as a program for service providers and software companies that want to license eligible Microsoft products to provide software services and hosted applications to end customers. In practical terms, SPLA gives a cloud or hosting provider a structured way to provide eligible Microsoft software licensing for hosted customer workloads. For a Windows VM customer, that matters because it moves the licensing conversation from vague to structured. Instead of asking: “Is this Windows server licensed somehow?” the customer can ask: “Is this workload covered through the provider’s SPLA agreement, or do I need another licensing path?” That is a better conversation. It gives the customer a clearer way to evaluate the provider. It also shows whether the provider is treating Microsoft workloads responsibly. Raff LLC is now a Microsoft SPLA Partner, and we explained why that matters in our announcement: [Raff Is Now a Microsoft SPLA Partner](/blog/raff-microsoft-spla-partner). ## Why We Took This Seriously at Raff One lesson I have learned while building Raff is that customers do not only buy infrastructure. They buy confidence. A developer may start by comparing server specs. A founder may care about monthly cost. A freelancer may need fast deployment. A business may care about support and uptime. But when Windows workloads are involved, licensing becomes part of the trust equation. That is why Raff becoming a Microsoft SPLA Partner matters. It gives us a clearer framework for providing hosted Microsoft software services through SPLA where applicable. It also helps us support Windows VM customers more responsibly as Raff grows. This is not about using the biggest possible partnership language. It is about being precise. Raff LLC is a Microsoft SPLA Partner. Raff is licensed to host Microsoft software through its SPLA agreement where applicable. Microsoft software licensing can be provided through Raff’s SPLA agreement for eligible hosted workloads. Those are strong statements without overstating the relationship. And that is exactly how trust should be built. ## What Buyers Should Watch For When choosing a Windows VM provider, I would not start with the lowest monthly price. Start with the licensing model. A very cheap Windows VM can look attractive, but if the provider cannot explain the Microsoft license path clearly, the risk may be pushed onto you. Before choosing a provider, ask these questions: * Is the Windows Server license included, evaluation-based, SPLA-based, or BYOL? * Is the workload allowed for production use? * What happens after the evaluation period ends? * Are Windows licenses billed separately? * Can the provider support SPLA licensing? * Can I bring my own Microsoft license? * Do I need RDS CALs for multiple Remote Desktop users? * Does SQL Server introduce a separate licensing requirement? * Can the provider give written licensing clarification if needed? These questions are not only for enterprise customers. They matter for small businesses too. A small business running accounting software, ERP software, custom Windows applications, or Remote Desktop workflows may not have an internal licensing team. That makes provider clarity even more important. ## Windows VM Pricing Is Not Only the VM Price Windows VM pricing can be confusing because the VM and the Microsoft license may be separate. The VM price covers compute resources such as CPU, RAM, storage, bandwidth, and infrastructure features. The Microsoft software license may be billed separately depending on the provider and licensing path. This distinction matters. A customer comparing Windows VM providers should not only ask: “What is the server price?” They should ask: “What is the full monthly cost with the Windows license included?” That is the number that matters for planning. On Raff, Windows VPS plans start from $10.99/month, and each Windows VM can start with a 6-month evaluation license for non-production testing. For production workloads, customers should choose the right licensing path before relying on the server. Pricing clarity is not just a finance detail. It affects whether a customer can trust the platform enough to run real workloads on it. You can review current plans on the [Raff pricing page](/pricing), then compare your licensing path using the [Windows Server Licensing on Raff](/windows-server/windows-licensing) guide. ## Remote Desktop Changes the Conversation Many customers choose Windows VMs because they need Remote Desktop access. That makes sense. RDP is one of the most practical reasons to use a hosted Windows server. But Remote Desktop licensing has its own rules. A basic Windows Server setup usually allows limited administrative access. That is not the same as building a multi-user Remote Desktop environment for a team. If multiple users will connect regularly, RDS Client Access Licenses may be required. This is where many buyers get surprised. They assume that because the VM has Windows Server, every Remote Desktop scenario is automatically covered. That is not always true. If your team needs shared remote access, ask the provider how RDS CAL licensing works before deployment. The simplest way to think about it is this: A Windows VM can give you the server. A licensing plan determines what kind of access and usage is allowed. Those two things need to match. ## SQL Server and Office Need Separate Attention Windows Server licensing does not automatically solve every Microsoft software licensing question. SQL Server has its own licensing model. Microsoft 365 Apps and Office also have specific requirements, especially in shared or hosted desktop scenarios. That means a Windows VM provider should not treat “Microsoft licensing” as one generic answer. A customer may need Windows Server only. Another customer may need SQL Server. Another may need Remote Desktop Services. Another may want Microsoft 365 Apps in a shared environment. Each scenario can create different licensing requirements. This is why clear provider guidance matters. The better provider does not simply say, “Yes, we support Windows.” The better provider helps you understand what kind of Windows workload you are actually running. ## A Practical Decision Framework Use this simple framework before choosing a Windows VM provider. | Your situation | What to check first | |---|---| | You are testing software on Windows Server | Confirm the evaluation license is enough and keep the workload non-production. | | You are running business software | Confirm whether SPLA or eligible BYOL is needed before production. | | You need more than two RDP users | Review RDS CAL requirements before sizing the server. | | You need SQL Server | Check SQL Server edition, licensing model, and backup requirements separately. | | You already own Microsoft licenses | Confirm BYOL eligibility, Software Assurance, and License Mobility requirements. | | You want the provider to supply licensing | Ask whether SPLA licensing is available for your workload. | | You care about audit posture | Ask for written clarification of the licensing path. | This table is not a substitute for legal or licensing advice. But it is a better starting point than comparing Windows VM prices without understanding what those prices include. ## How Raff Approaches Windows VM Licensing Raff’s approach is to make the licensing path visible. For Windows VMs, the practical paths are: * Evaluation licensing for non-production testing and learning. * SPLA licensing through Raff for eligible hosted production workloads. * BYOL for customers with eligible Microsoft licenses and the right usage rights. This gives customers a way to start, test, and then move into the correct production path. For example, a developer can start with a Windows Server evaluation environment to test an application. If the project becomes production, the customer can move into a proper licensing path instead of pretending the evaluation environment was enough. That matters because testing and production are not the same thing. A lab workload can tolerate uncertainty. A business workload should not. You can explore Raff’s Windows VM product here: [Raff Windows VMs](/products/windows-vm). ## Infrastructure Still Matters Licensing is critical, but it is not the only decision. A properly licensed Windows VM still needs the right infrastructure behind it. For production workloads, buyers should also consider: * VM sizing * storage performance * backup strategy * private networking * firewall rules * support responsiveness * recovery planning * upgrade path * total monthly cost This is where the full provider decision becomes clearer. A Windows VM provider should not only give you a Microsoft license path. It should also give you infrastructure that can support the workload responsibly. For example, a Windows business application may need automated backups, restore points, and a recovery plan. Raff provides data protection features such as backups and snapshots, which you can review here: [Raff data protection](/products/data-protection). If your workload involves multiple servers or internal services, private networking can also matter. You can review that here: [Raff private cloud networks](/products/private-cloud-networks). Licensing answers the question: “Are we allowed to run this?” Infrastructure answers the question: “Can we run this reliably?” You need both. ## Provider Trust Is Built Before the First Login A customer’s trust in a Windows VM provider begins before they connect with RDP. It begins when they read the pricing page. It begins when they ask how licensing works. It begins when the provider explains limitations clearly. It begins when the provider is willing to say, “This path is right for testing, but not for production.” That kind of honesty matters. It may slow down a sale in the short term, but it builds a better customer relationship in the long term. At Raff, we want customers to understand what they are using. That includes server resources, pricing, backups, networking, support, and licensing. Especially licensing. Because when a business puts real work on a Windows VM, “probably fine” is not good enough. ## When a Windows VM Provider Is a Good Fit A Windows VM provider is a good fit when the workload needs more than a generic server. Look for a provider that can support: * Windows Server versions your software actually supports. * Full administrator access. * RDP access from different devices. * Clear VM sizing and pricing. * Backups and snapshots. * Networking and firewall controls. * A clear Microsoft licensing path. * SPLA or BYOL guidance where applicable. * Support that understands Windows workloads. Raff Windows VMs support Windows Server 2019, 2022, and 2025, with full administrator access and RDP. For businesses running Windows applications, that combination matters because the server is not just a test machine. It can become part of daily operations. The provider should be ready for that responsibility. If you are still comparing Windows and Linux workloads, you can also review the broader [Raff VM options](/products/raff-vm) before choosing the right environment. ## Red Flags to Avoid A Windows VM provider does not need to make licensing sound complicated. But it should be able to answer basic licensing questions clearly. Watch out for these red flags: * The provider cannot explain whether the Windows license is evaluation, SPLA, or BYOL. * The provider says “license included” without explaining what license path is being used. * The provider treats production and testing as if they are the same. * The provider ignores RDS CALs when multiple users need Remote Desktop. * The provider says BYOL is always allowed without checking eligibility. * The provider cannot explain SQL Server or Microsoft 365 Apps licensing separately. * The provider avoids giving written clarification for business workloads. None of these automatically mean a provider is bad. But they do mean you should slow down and ask more questions. For Microsoft workloads, vague answers create real risk. ## What This Means for You If you are choosing a Windows VM provider, do not treat Microsoft licensing as a footnote. Ask about it early. If you are testing, an evaluation license may be enough. If you are running production workloads, you need a proper licensing path. If you already own Microsoft licenses, check whether BYOL is actually eligible. If you need Remote Desktop for more than administrative access, review RDS CAL requirements. If you need SQL Server, review SQL Server licensing separately. If you want the provider to handle licensing for eligible hosted Microsoft workloads, ask whether SPLA is available. For Raff customers, the important point is simple: Raff LLC is a Microsoft SPLA Partner, licensed to provide hosted Microsoft software services through SPLA where applicable. That gives Windows VM customers a clearer foundation when evaluating Raff for business workloads. Start with the workload. Then choose the license path. Then choose the VM size. That order will save confusion later. ## Final Thought Windows VM hosting is not only about launching a server. It is about running a licensed Microsoft software environment in a hosted cloud setting. That means the provider’s licensing posture matters. The cheapest Windows VM is not always the safest choice. The most powerful VM is not always the right choice either. The right choice is the provider that gives you the performance, access, support, pricing clarity, and licensing path your workload needs. That is what Raff is working to provide. Fast infrastructure. Simple deployment. Reliable operations. And now, a stronger Microsoft licensing foundation through SPLA. --- ### The Real Cost of Running n8n in the Cloud vs SaaS (2026) URL: https://rafftechnologies.com/blog/real-cost-n8n-cloud-vs-saas Published: 2026-03-29T00:00:00.000Z Description: The Real Cost of Running n8n in the Cloud vs SaaS (2026) ## The Cheapest n8n Option on Day One Is Not Always the Cheapest in Month Three If you are evaluating n8n in 2026, the real pricing question is not just “What does n8n cost?” It is “Which cost model gets more expensive as my workflows become important?” n8n is a workflow automation platform that lets you connect apps, APIs, databases, webhooks, and AI tools through visual, node-based workflows. You can use n8n as a hosted service, or you can run it yourself on infrastructure you control. That sounds like a simple convenience-versus-control decision. In practice, it is a cost-model decision. That is exactly why this topic matters to us at Raff. We built a dedicated n8n VM offer because some teams want the freedom of self-hosting without turning deployment into a side project. Once automation becomes part of operations, the conversation changes. The question stops being “Can we automate this?” and becomes “What happens to our cost, control, and risk when this workflow starts running all day?” That is the lens I want to use here. In this post, “cloud” means running self-hosted n8n on your own cloud VM. “SaaS” means using n8n’s hosted plans. Both can work. But they behave very differently once your automations stop being experiments and start becoming part of how your team operates. ## The First Mistake Is Comparing Only the Subscription Price Most people start with the obvious numbers. On n8n’s current pricing page, the hosted Starter plan is listed at 20€ per month billed annually and includes 2.5K workflow executions. The hosted Pro plan is listed at 50€ per month billed annually. n8n also makes it clear that its pricing is based on monthly workflow executions, not per-step billing. That is more understandable than many automation tools, but it is still only one layer of cost. If you self-host n8n, the software itself can be free to run in Community Edition. Your cost moves away from an execution-based subscription and into infrastructure: the VM, storage, backups, updates, SSL, monitoring, and the time required to keep the instance healthy. That is why “self-hosted is free” is not a serious cost answer. It removes one pricing model and replaces it with another. ## What You Are Really Paying For in Each Model The cleanest way to think about the decision is this: * SaaS pricing charges you for managed convenience and platform ownership. * Self-hosted cloud pricing charges you for infrastructure and operational responsibility. That sounds obvious, but it changes how you should evaluate cost. With SaaS, you are paying to avoid infrastructure work. You do not provision a server. You do not handle patching the host. You do not deal with reverse proxies, TLS termination, backup jobs, or resource sizing on day one. You get a smoother start, which has real value. With self-hosting, you are paying for a machine, not a usage meter. That changes the economics quickly once workflow count, data volume, webhook traffic, or internal integrations grow. It also changes the control boundary. The workflows run on infrastructure you choose, with networking, storage, access, and recovery options you define. The right question is not “Which one is cheaper?” The right question is “Which cost model fits the way my automations will behave over the next 6 to 12 months?” ## Where SaaS Usually Wins SaaS is often the right answer earlier than self-hosting advocates like to admit. If you are still validating whether n8n is useful for your team, the hosted option can be the smarter financial choice even if the long-term unit economics are worse. That is because it removes the operational delay between interest and value. You do not need to think about server sizing. You do not need to think about backups on day one. You do not need to explain to a teammate why automation broke because the VM ran out of memory or because an update was skipped. For a solo operator, non-technical team, or early proof of concept, that convenience matters. It is not fake value. It is real time saved. SaaS is especially attractive when: * your workflow volume is still low * your integrations are mostly external SaaS apps * you do not need special networking or internal database access * speed to first automation matters more than infrastructure ownership * your team does not want to operate another service yet In those situations, the subscription is buying focus. ## Where Self-Hosted Cloud Starts to Win The economics change when automation becomes operational rather than experimental. This is the inflection point that matters. Once workflows become part of lead handling, support routing, reporting, internal ops, engineering notifications, AI enrichment, or backend orchestration, execution volume usually stops being neat and predictable. Usage grows unevenly. Teams add more triggers. Someone connects a database. Someone adds retries. Someone builds a second workflow that depends on the first one. Suddenly the automation layer is no longer a side tool. That is where running n8n on your own cloud VM starts making more sense. On Raff’s n8n product page, the positioning is explicit: your n8n instance is self-hosted, under your control, with no execution limits added by the platform. Raff also highlights 400+ integrations, custom node support, and full data ownership. That is a materially different operating model from paying for hosted workflow execution under a plan threshold. The other part of the equation is price discipline. Raff’s n8n page currently shows snapshots and backups at $0.06 per GB per month, with the first three backups per VM included free. For teams that are already technical, that is often easier to reason about than a subscription tied to execution thresholds. That does not mean it is always cheaper in total. It means the bill behaves differently. ## The Real Cost of Self-Hosting Is Not the VM. It Is Ownership This is where people get sloppy. If you only compare a SaaS fee to a VM fee, the self-hosted side can look like an automatic win. That is incomplete. The real self-hosting cost includes: * provisioning and initial setup * software updates * backup policy * SSL and domain setup * monitoring and alerting * recovery planning * whoever gets called when something breaks If nobody on your team can own those things comfortably, a cheap VM is not actually cheap. It is deferred operational work. That is why the self-hosted decision is strongest for technical teams, agencies, startups with a builder mindset, and operators who already run adjacent infrastructure. If your team already lives comfortably with Linux VMs, reverse proxies, containers, and backup routines, the marginal cost of running n8n is much lower. If you do not, the hidden cost is not money first. It is interruption. So the honest framing is this: self-hosted n8n is often cheaper on infrastructure, but only cheaper in total if your team can absorb the ownership model without creating drag. ## A More Useful Cost Comparison Here is the practical version of the decision. | Scenario | Hosted n8n SaaS | Self-Hosted n8n on a Cloud VM | |---|---|---| | Early proof of concept | Usually better | Usually unnecessary | | Low workflow volume, non-technical owner | Better fit | Adds avoidable ops work | | Internal tools with database/API access | Limited by hosted model assumptions | Usually stronger fit | | Growing execution volume | Subscription pressure increases | Infrastructure cost stays easier to model | | Sensitive data or internal systems | Less control | More control | | Teams already comfortable with VMs | Convenience still nice | Often better long-term economics | | Custom nodes or deeper environment control | Limited | Stronger fit | That is the real cost table, even more than the sticker prices. A team running five light workflows may rationally prefer the hosted option because the avoided setup time is worth more than the savings. A team running always-on internal automations tied to APIs, queues, databases, and business operations may prefer a VM-based model because the infrastructure cost is steadier while workflow volume grows. ## Why This Matters More in 2026 Automation in 2026 is not just “if this, then that.” Teams are using n8n for AI-assisted workflows, webhook processing, lead qualification, content operations, support handoffs, internal notifications, data sync, and backend task chaining. That means more automations are becoming high-frequency, business-critical, and harder to move once they are embedded into daily operations. When that happens, the pricing model matters more than it did during experimentation. n8n’s current pricing already reflects this reality. The company emphasizes that it charges for full workflow executions, not individual steps. That makes the product more predictable than many step-based automation tools. But predictability at the platform level is still different from predictability at the infrastructure level. A subscription threshold asks, “How much did you run?” A VM model asks, “How much environment do you need?” Those are not the same question. For technical teams, the second question often becomes easier to manage over time. ## Where Raff Fits in This Decision Raff is not trying to turn this into an ideological argument about self-hosting. The real goal is to make the self-hosted option practical enough that you can choose it when it genuinely fits. That is why the n8n product exists as a dedicated offer instead of forcing customers to assemble every piece from scratch. The platform is designed around the idea that some teams want the control of self-hosting without turning setup into a side project. Fast provisioning, NVMe storage, AMD EPYC infrastructure, predictable VM pricing, and low-friction backup options all matter more when the service you are running becomes part of your daily operations. The business pattern behind this is simple. Teams usually do not move toward self-hosting because they love infrastructure. They move because they want fewer pricing surprises, more control over data, cleaner integration with internal systems, or a deployment model that still makes sense once automation becomes central to the business. That is the actual decision. ## What I Would Recommend If you are deciding today, I would use this framework. Choose hosted n8n SaaS if: * you want the fastest possible start * your workflow count is still modest * you do not want infrastructure ownership yet * your automations live mostly in external SaaS tools Choose self-hosted n8n on a cloud VM if: * your workflows are becoming operationally important * you need database, webhook, or internal service access on your terms * you want more stable long-term economics than execution-based pricing * your team is already comfortable operating cloud infrastructure And if you are in the middle, do not force a philosophical decision too early. Start with the model that reduces friction now, but choose a platform path that does not trap you when usage grows. That is why I think the best n8n cost conversation is not about “free vs paid.” It is about which ownership model matches the stage your team is actually in. ## What This Means for You If you are evaluating n8n today, do not stop at the subscription page. Map your likely workflow behavior over the next six months. Estimate how often triggers will fire, whether those automations will touch internal systems, and whether your team wants to own the environment or outsource it. Then compare that to infrastructure cost, not just software cost. If you want a practical path to the self-hosted side, start with Raff’s [n8n VM product](/products/n8n-vm) and compare it against the broader [pricing page](/pricing). Those two pages tell you the most important part of the story: how the ownership model changes once your automations stop being experiments and start becoming infrastructure. From where I sit, that is the real pricing conversation. Not whether n8n can automate your work. Whether the cost model still makes sense when the automation starts working. --- ### Getting Started with Raff: Launch Your First VM in 5 Minutes URL: https://rafftechnologies.com/blog/getting-started-with-raff-launch-your-first-vm-in-5-minutes Published: 2025-05-07T00:00:00.000Z Description: Getting Started with Raff: Launch Your First VM in 5 Minutes Cloud infrastructure only feels complicated when the first step is heavier than it needs to be. That is something we think about a lot at Raff. Most people starting with cloud do not need a lecture on distributed systems before they can launch a server. They need a clear way to go from “I need a machine for this project” to “my VM is live and ready” without losing an afternoon to setup friction. That is exactly why we made this process simple. On Raff, you can launch a VM quickly, choose an operating system you already know, and start working without being forced into a giant platform learning curve. If you are new to cloud servers, this is the place to start. ## Why your first VM should feel simple A virtual machine is a software-defined server that gives you dedicated resources and a clean operating system environment in the cloud. For a developer, student, founder, or small team, that means you can work on a project without depending entirely on your local machine. Your first VM does not need to be perfect. It needs to be useful. In practical terms, a first VM usually helps you do one of these things: * create a clean development environment * test a web app outside your laptop * host a small service or internal tool * learn Linux and server basics in a real environment * run workloads that feel too heavy or messy on your personal computer That is the right mindset for getting started. You are not building the final architecture for a billion-request platform. You are creating a reliable place to work, test, and learn. ## Why we built this experience the way we did When small teams first move into cloud infrastructure, they usually make one of two mistakes. The first mistake is overthinking everything. They try to solve scale, security, cost optimization, automation, staging, and production architecture all at once before they even launch one machine. The second mistake is underestimating how valuable a clean environment can be. They keep piling tools, dependencies, containers, and test data onto a local machine until everything starts to feel slower, harder to reproduce, and more fragile than it should. We built Raff to sit in the healthy middle. Start quickly, keep control, and add complexity only when your work actually needs it. That is why the first-VM experience matters. It sets the tone for how a team will use infrastructure going forward. If the first launch is easy to understand, teams make better decisions later about resizing, backups, snapshots, and production readiness. ## Step one is knowing what you actually need Before you launch anything, ask one simple question: What is this VM for? That single question makes the rest of the process easier. If you are building or learning, a lightweight Linux VM is usually the right place to begin. If you need a stable environment for web development, automation, scripting, or general backend work, Linux gives you the most flexibility. Raff publicly supports multiple Linux distributions including Ubuntu, Debian, Fedora, CentOS Stream, AlmaLinux, Rocky Linux, Alpine, OpenSUSE, and FreeBSD, with Linux VMs positioned as deployable in under 60 seconds. If you rely on Windows-specific software, .NET workflows, or graphical tools tied to the Windows ecosystem, then a Windows VM can make more sense. Raff’s FAQ also confirms support for both major Linux distributions and Windows Server. For most first-time users, though, Linux is the better start because it is lighter, widely documented, and fits the majority of modern development and hosting workflows. ## What launching your first VM looks like The process should feel straightforward. You sign up, choose the kind of VM you want, pick an operating system, decide on a size, name the machine, and launch it. That is the mental model. Everything else is refinement. The mistake some providers make is turning this into a giant configuration exercise. Too many optional decisions too early can make a simple task feel like infrastructure architecture. For a first VM, that is unnecessary friction. The better experience is this: ### 1. Start with the workload, not the specs Do not start by staring at CPU and RAM tables with no context. Start with the job you want the machine to do. If your goal is terminal-based development, lightweight app hosting, or learning Linux, you do not need to begin with an oversized machine. If your goal is heavier testing, multiple services, or staging a more demanding application, you can step up to a larger configuration. The good news is that you are not locked in forever. Raff’s FAQ states that you can resize your VM later, which is exactly how smaller teams should think about infrastructure: start with a sane baseline, then adjust once the workload becomes real. ### 2. Choose an operating system you already understand The fastest setup is usually the one that matches your current comfort zone. If you already use Ubuntu locally, pick Ubuntu. If your team prefers Debian, choose Debian. If you have a specific distro requirement for a project, use that as your starting point. The goal is not to prove you can run a more obscure operating system. The goal is to get productive quickly. Raff’s Linux VM product page highlights Ubuntu, Debian, Fedora, Rocky Linux, AlmaLinux, Alpine, OpenSUSE, and FreeBSD among the supported choices, which gives you plenty of room to match the VM to your workflow instead of forcing your workflow to match the VM. ### 3. Name the machine like it will matter later This sounds small, but it saves confusion. A VM named `test` is forgettable. A VM named `portfolio-site-ubuntu`, `django-staging`, or `ml-lab-01` is far easier to manage later when you have more than one machine. Naming becomes even more important once you start taking snapshots, adding backups, or creating separate development and staging systems. ### 4. Launch and verify the basics immediately Your first few minutes after launch matter. Once the VM is provisioned, check the essentials right away: * confirm the machine is running * confirm you can access it * confirm the OS is what you selected * confirm networking works * confirm you know how you will log in again later Raff publicly states that Linux VMs deploy in under 60 seconds, and the FAQ says VMs deploy in about 60 seconds on average including OS installation and network configuration. That is fast enough that the real bottleneck is usually not the platform. It is deciding what you want the VM to do next. ## What to do in your first 15 minutes after launch This is where a lot of first-time users either build momentum or lose it. You do not need to do everything. You just need to do the right first few things. ### Update the machine If you launched a Linux VM, update the package index and apply available updates. Even when the image is current, this is a good habit because it gives you a clean starting point. ### Create a purpose for the server Do one useful thing immediately. Install Docker. Clone a project. Set up a web server. Create a small API. Add your SSH key. The first practical action is important because it turns the VM from “a server that exists” into “a tool that is already helping me.” ### Decide whether this is disposable or persistent Some first VMs are experiments. Others become the starting point for something longer-lived. That distinction matters. If it is disposable, move fast and learn. If it is persistent, think about backups, naming, access, and documentation right away. Raff’s pricing page makes this easier because snapshots and backups are built into the platform model rather than treated like an afterthought. Snapshots are listed at $0.06 per GB per month, and backups are also $0.06 per GB per month, with the first three backups per VM included free. That matters because the earlier you build recovery habits, the safer your workflow becomes. ## Common first-use cases that make sense on Raff A first VM should solve a real problem, not just satisfy curiosity. Here are some of the most practical starting use cases. ### A clean development box If your local machine is crowded with dependencies, containers, SDKs, and experiments from multiple projects, a cloud VM gives you a cleaner workspace. That is especially helpful when you want to separate client work, personal projects, and experimental stacks. ### A lightweight staging environment Many small teams wait too long before creating a staging environment because they assume it will be expensive or complicated. In reality, one modest VM is often enough to validate release workflows, test environment variables, and preview changes outside local development. ### A hosted side project or MVP A first VM is often the cheapest serious place to host a small application. If you are validating an idea, a VM gives you control over the OS, runtime, packages, networking, and deployment process. ### A learning lab This is one of the most underrated uses. If you want to learn Linux, Docker, Nginx, firewalls, SSH, or deployment basics, nothing teaches faster than having a real server to work with. The risk feels lower when the environment is clearly separated from your personal machine. ## Where teams usually overcomplicate the first launch This part matters because overcomplication is expensive. The first VM is where some teams start introducing too much process too early. They debate environments before they have users. They choose a larger machine because it feels safer. They create a long provisioning checklist before they know which parts they actually need. My advice is simpler. Launch one machine with a clear purpose. Use it. Learn from it. Then improve the next decision. That is a more practical cloud habit than trying to design your forever-architecture in week one. Raff’s product positioning supports that kind of approach. Pricing starts at $4.99 per month, the platform emphasizes transparent pricing, unmetered bandwidth, fast deployment, and 24/7 support, and Linux VMs are marketed as quick to deploy with full root access. Those are exactly the traits that make “start small, then iterate” a realistic strategy instead of a risky one. ## A better way to think about your first VM Do not think of your first VM as infrastructure you must get perfectly right. Think of it as a working base. A place to code. A place to test. A place to host. A place to learn. A place to separate one project from the chaos of everything else. Once you treat it that way, the first launch becomes less intimidating. You stop asking, “What is the perfect setup?” and start asking, “What is the next useful setup?” That shift is important. It is how small teams move from hesitation into momentum. ## What This Means for You If you are just getting started with cloud infrastructure, your first goal should not be mastering every cloud concept at once. Your goal should be getting one useful VM online quickly, understanding what it is for, and creating enough confidence to keep going. That is the practical value of a first VM on Raff. You can start with an operating system you already know, launch quickly, resize later if needed, and build better habits around access, backups, and deployment as your workload grows. If you are ready to turn this into action, start with [Raff pricing](/pricing), explore [Linux VM options](/products/linux-vm), and then make your first decision as simple as possible: choose the machine that helps you do your next piece of work today. --- ### Inside a Good Linux VM Base Image: What We Check Before It Goes Live URL: https://rafftechnologies.com/blog/inside-a-good-linux-vm-base-image Published: 2026-04-21T00:00:00.000Z Description: Inside a Good Linux VM Base Image: What We Check Before It Goes Live A good Linux VM base image is not just a bootable operating system. It is a starting state you can trust under automation, at scale, and under pressure. At Raff Technologies, that means we do not judge an image by whether it launches once. We judge it by whether package state is current, boot behavior is predictable, SSH defaults are sane, cloud-init is boring, disk expansion works cleanly, and rollback is possible when something changes underneath it. That sounds strict, but base images deserve that level of suspicion. Every small mistake in a base image gets multiplied. One weak SSH default becomes hundreds of weak SSH defaults. One cloud-init edge case becomes a noisy support pattern. One package that should have been refreshed becomes an avoidable patching problem on day one. This post is about the checks I care about before a Linux VM base image goes live. Not the marketing version. The operator version. > **Editor note:** Add one real Aybars-tested sentence in the first two sections before publishing. This topic needs a Category B first-hand signal from actual image validation, not a generic “we tested it” line. ## The Image Has to Be Safe Before It Is Convenient The easiest mistake with base images is to treat them like a shortcut. They are not. A base image is an opinionated operating environment that decides what every new VM inherits before the user touches anything. That is why image quality matters more than it first appears. The base image decides package age, boot defaults, service posture, initialization behavior, partition expectations, and early access paths. If those defaults are clean, the VM feels reliable immediately. If they are messy, the VM feels “mostly fine” until the first reboot, resize, or access issue exposes the cracks. I think that is the right frame for this topic. A good base image reduces future cleanup. A bad one quietly creates it. ## Package Freshness Is More Than Running Updates Once Package freshness is the first thing people mention, but I think it gets simplified too often. A fresh image is not just an image that ran `apt upgrade` or `dnf update` at some point. A fresh image is an image whose package state is recent enough that the user is not starting their VM by paying off hidden maintenance debt. Those are not the same thing. What I care about here is whether the image is shipping with a package set that still makes sense for first boot. Security updates matter, but so does consistency. If you publish an image with stale packages, the user’s first interaction becomes a remediation session. That is a bad first five minutes. The trick is that freshness has to be balanced against repeatability. You want current packages, but you also want to know what changed between image revisions. Otherwise the image feels current but not stable. A practical base image check should answer three questions: * Are the core packages recent enough to avoid obvious day-one patch debt? * Did anything important change compared to the previous image revision? * Would a user be surprised by what needs updating immediately after first boot? That last question matters more than most teams expect. Users do not evaluate freshness as an abstract security idea. They evaluate it as friction. ## systemd Sanity Is Really a Boot Predictability Check When I say I check systemd sanity, I do not mean “systemd exists and the machine boots.” I mean the machine boots in a way that makes sense. This is one of the most overlooked parts of image QA because the image may look fine under a quick launch test. Then later someone notices a service waiting on the wrong dependency, a unit starting too early, or a login path that behaves differently on the second reboot than it did on the first. A clean image should be boring at boot time. That is the goal. I usually think about systemd sanity in layers: * Does the image reach the expected target cleanly? * Are there failed or degraded units that should not be there? * Do cloud-specific services start in the right order? * Does the image behave the same on the first boot, second boot, and after a clean reboot? * Is there anything enabled by default that makes sense for a developer laptop image but not for a cloud VM image? A lot of Linux image problems are not catastrophic. They are ambiguous. The machine boots, but not confidently. For a base image, that is still a problem. A VM should not require interpretation after first boot. ## SSH Defaults Tell You Whether the Image Respects Reality SSH defaults are one of the clearest signals of whether a base image was built for the real world or only for internal convenience. A good image should make secure access straightforward without forcing the user into recovery mode on day one. A bad image usually fails in one of two directions: it is too permissive by default, or it becomes unnecessarily fragile the moment the user tries to harden it. That is why I look at SSH defaults as part of the image contract. I want to know: * what the default login path is * whether the image behaves cleanly with key-based access * whether root access is exposed in a way we are comfortable shipping * whether first-boot access and recovery still make sense if the user changes SSH behavior later This matters even more on a cloud platform because remote access is not theoretical. It is the first support boundary the user touches. At Raff, that question sits next to platform capabilities too. The fact that Linux VMs ship with web console access, snapshots, private networking, and other recovery-friendly infrastructure features changes how strict you can be with defaults, because the user still needs a safe path back if normal access goes sideways. That makes image design less about convenience and more about responsible starting assumptions. ## cloud-init Should Be Invisible When It Works cloud-init is one of those components people only notice when it misbehaves. That is exactly why it matters. A Linux VM base image in a cloud environment needs cloud-init to be predictable, not clever. Hostname assignment, SSH key injection, user creation, metadata handling, networking, and first-boot scripts all become part of the VM’s lived experience through cloud-init. If that behavior is inconsistent, the image stops feeling production-ready very quickly. What I want from cloud-init is simple: it should do the expected thing once, do it clearly, and get out of the way. A few questions usually reveal whether the image is ready: * Does first boot behave differently from subsequent boots in a way the user can understand? * Does the image pick up metadata cleanly? * Are SSH keys and user data processed as expected? * Are cloud-init logs useful when something fails? * Does the image reset the right state before publishing so the new VM does not inherit the wrong identity or cached behavior? That last one is a classic base-image trap. An image can pass a superficial launch test while still carrying state that should never have survived the image pipeline. A good cloud image is not just configured. It is de-personalized correctly. ## Disk Growth Has to Work Without Drama Disk growth is one of those things that looks obvious until it is not. Everyone expects a VM to handle more storage cleanly. Fewer people check whether the image actually expands partitions and filesystems in a way that feels safe and predictable when the disk changes after launch. That is why I do not treat disk growth as a nice extra. I treat it as part of image readiness. A base image should answer these questions before it goes live: * Does the root disk expand correctly when the VM launches with a larger volume? * Does the filesystem reflect the added space without awkward manual recovery? * Does the image handle common cloud expansion behavior without leaving the user in a half-grown state? * If expansion fails, does it fail clearly enough for someone to fix without guessing? This is especially important on a platform like Raff where VM usage can start small and grow later. General Purpose plans begin at $4.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe SSD, while CPU-Optimized tiers begin at $9.99/month and scale upward depending on performance needs. That makes clean growth behavior part of the real user journey, not an edge case. An image that behaves badly when storage changes is not just technically incomplete. It is commercially awkward. ## Rollback Readiness Starts Before the Image Ships Rollback is often discussed as a platform feature, but I think it also belongs in image quality. A base image should not only be launchable. It should be survivable. That means understanding what happens if the image revision introduces a problem, if a package change creates boot regressions, or if a first-boot workflow behaves differently than expected. This is where snapshots, backups, revision discipline, and recovery paths stop being separate infrastructure topics and become part of image publishing maturity. I do not think every image team needs a dramatic rollback story. I do think every image team needs to answer these questions honestly: * Can we identify what changed between this image and the previous one? * Can we pull the image back out of circulation quickly? * Can a user recover a broken VM with the platform tools available? * Did we test the rollback path, or only talk about it? That is where image publishing becomes operator work instead of packaging work. ## What Actually Blocks Release for Me There are some issues I would treat as immediate stop signs. If package state is stale enough that first boot begins with preventable cleanup, I would block release. If the image boots with unclear service behavior, degraded units, or confusing startup order, I would block release. If SSH access works only under a narrow happy path, I would block release. If cloud-init still carries the wrong state, behaves inconsistently, or makes first boot hard to reason about, I would block release. If disk expansion works only in demos but not under real resize conditions, I would block release. And if the team cannot explain how to recover from an image-level mistake, I would block release too. That may sound like a harsh standard, but base images are upstream from too many other things to grade them generously. A shortcut here becomes support work later. ## What This Means for You If you launch Linux VMs regularly, the quality of the base image matters more than most people think. It affects patching, boot behavior, SSH access, provisioning, storage growth, and recovery before you install the first application. That is one reason I like thinking about base images as operational products rather than technical artifacts. A good image removes uncertainty from the first hour of a VM’s life. A bad one hides uncertainty inside it. If you are evaluating infrastructure, look beyond whether a VM can launch quickly. Ask what the base image is inheriting, what the platform gives you when something goes wrong, and whether growth and rollback are part of the design. On Raff, that conversation naturally connects to [Linux VMs](/products/linux-vm), [snapshots and backups](/products/data-protection), and the [web console](/blog/access-your-vm-anywhere-with-our-new-vnc-console), because image quality is only as useful as the recovery and scaling model around it. That is the standard I would use before publishing a Linux VM base image: not “it boots,” but “it stays predictable after first contact.” --- ### What Enterprise Buyers Really Notice About Startup Infrastructure URL: https://rafftechnologies.com/blog/what-enterprise-buyers-really-notice-about-startup-infrastructure Published: 2026-04-19T00:00:00.000Z Description: What Enterprise Buyers Really Notice About Startup Infrastructure ## Enterprise Buyers Do Not Buy the Most Complicated Stack Enterprise buyers rarely reject a startup because the infrastructure is too simple. They usually hesitate because the infrastructure story feels risky. At Raff Technologies, what I keep seeing is that larger buyers are not looking for the most fashionable architecture. They are looking for signs that your team understands risk, access, recovery, and operational discipline. That is the real shift founders need to understand. Enterprise-ready infrastructure is not infrastructure with the most tools. It is infrastructure that can answer predictable trust questions without hesitation. When a buyer asks who can access production, how environments are separated, where backups live, or what happens when a server fails, they are not making small talk. They are measuring whether your company is safe to depend on. This is where many startup teams misread the room. They assume enterprise buyers care most about scale diagrams, Kubernetes screenshots, or a long vendor list. Those things can matter later. But early on, buyers are usually reading for confidence. They want to know whether your infrastructure is understandable, controlled, and recoverable. ## What They Notice First Is Risk, Not Sophistication The first infrastructure questions in an enterprise conversation are usually not about how advanced your platform is. They are about how predictable it is. A buyer wants to know whether production access is limited, whether environments are separated, whether critical services are exposed only where necessary, and whether your team can recover from failure without improvising. Those questions sound operational, but they are commercial. If the answers feel vague, trust drops. And once trust drops, the sales cycle gets slower, legal gets louder, and procurement starts asking harder questions. This is why a clean setup often beats a flashy one. A startup that can clearly explain its production environment, access model, backup policy, and monitoring approach usually feels more credible than a startup with a sprawling architecture nobody can describe in plain English. In other words, enterprise buyers are not rewarding technical theater. They are rewarding operational clarity. ## The Signals That Quietly Build Confidence There are a few signals that matter far more than founders expect. The first is **environment separation**. Buyers want to hear that development, staging, and production are not all mixed together. They do not need a huge platform team behind it. They need evidence that experiments happen away from customer-facing systems. The second is **access discipline**. If everyone on the team can SSH into production whenever they want, that may feel fast internally, but externally it sounds fragile. Mature teams can explain who has access, how access is granted, and how it is removed. The third is **recovery discipline**. A buyer may never ask for your exact backup policy on the first call, but they will absolutely notice whether your answers sound rehearsed or invented on the spot. “We have backups” is not reassuring. “We know what is backed up, how often it runs, and how we would restore it” is reassuring. The fourth is **network boundaries**. Not everything should be public by default. Buyers may not use the phrase “attack surface,” but they definitely react to whether your infrastructure exposes only what it needs to expose. The fifth is **operational explainability**. This one matters more than people admit. If your team cannot explain the current setup without opening five dashboards and arguing in real time, the buyer notices. Enterprise customers are not only evaluating your product. They are evaluating whether your company behaves like a reliable operator. ## What Buyers Really Mean When They Say “Maturity” Founders often hear the word “maturity” and translate it into “we need more tooling.” I think that is usually the wrong translation. In enterprise buying, maturity usually means: * your team has clear boundaries between environments * production access is controlled * secrets are handled deliberately * backups and recovery are real, not theoretical * monitoring exists before the incident, not after it * the infrastructure can be explained by a human in normal language That is a much more practical standard than most teams imagine. It also means many startups are closer than they think. A lean setup can look mature if it is intentional. A messy setup can look immature even if it is expensive. This is one reason I like straightforward infrastructure foundations. A startup does not need ten layers of abstraction to look credible. It needs a setup that supports discipline. A [Linux Virtual Machine](/products/linux-vm), a defined network boundary, a backup plan, and limited production access often do more for enterprise trust than another month spent adding fashionable complexity. ## The Signals That Quietly Kill Confidence There are also a few patterns that almost always create doubt. One is **shared credentials**. Another is **production being used as a testing environment**. Another is **public exposure everywhere because it was faster during the first build**. Buyers may not always call these out directly, but they feel them in the conversation. The same is true when teams cannot answer basic operational questions. If someone asks how you would restore service after a bad deployment and the answer is effectively “we would figure it out,” that tells the buyer more than you think. It tells them the system may work today, but the company has not yet built dependable operating habits around it. This is also where overspending creates a false sense of progress. You can absolutely buy more infrastructure than you can operate well. You can also buy enterprise optics without building enterprise discipline. Buyers are usually better at spotting that than founders expect. ## Why Simplicity Is Still an Advantage One of the biggest mistakes startups make is assuming they need to imitate large companies too early. Big companies often have complex infrastructure because they have complex constraints: many teams, legacy systems, geographic spread, compliance requirements, internal platform layers, and years of accumulated decisions. Early-stage companies usually do not have those conditions yet. Copying the shape of enterprise infrastructure without having enterprise infrastructure needs often creates cost and confusion before it creates trust. In my view, buyers are usually more comfortable with a simple architecture that is well run than an advanced architecture that is poorly understood. That is also why predictable infrastructure products matter. If your team can launch on a clean [Linux Virtual Machine](/products/linux-vm), isolate services with [Private Cloud Networks](/products/private-cloud-networks), protect recovery with [Data Protection](/products/data-protection), and tighten exposure with clearly defined [Security features](/products/security), you already have a stronger enterprise story than many founders realize. A lean environment does not need to be expensive either. On Raff, a General Purpose VM with **2 vCPU, 4 GB DDR5 RAM, and 80 GB NVMe storage costs $13.99/month**, while a CPU-Optimized VM at the same **2 vCPU, 4 GB RAM, and 80 GB NVMe SSD costs $27.99/month** when you need more predictable compute behavior. The important part is not the price alone. It is that the setup stays understandable as you grow. ## What Founders Should Fix Earlier If you want to look more enterprise-ready without overbuilding, I would start with four things. First, separate environments clearly. Even a modest staging environment changes the conversation because it shows you do not treat production as a sandbox. Second, define access before someone asks. Know who can reach production, who approves changes, and how credentials are handled. You do not need a giant IAM project to do this better than most early teams. Third, decide your recovery story while the system is still small. Backups, snapshots, rollback paths, and deployment discipline are cheaper to organize early than to retrofit under pressure. Fourth, keep the architecture explainable. If a buyer asks how your application is deployed, where the data lives, what is public, and how you recover from failure, the answer should be understandable in minutes. That last point is underrated. Clear explanations reduce perceived risk. Reduced perceived risk shortens sales friction. In B2B infrastructure conversations, clarity is not just technical hygiene. It is sales leverage. ## The Real Enterprise Readiness Test A useful question for any founder is this: if a serious enterprise prospect asked me five operational questions tomorrow, would my team answer calmly or defensively? That question gets to the heart of it. Enterprise buyers are not looking for perfection. They know startups are still building. What they want is evidence that the company makes deliberate infrastructure decisions. They want to see that the system is not being held together by habit, memory, and luck. If your infrastructure can be explained, access can be justified, recovery can be described, and risks have visible boundaries, you already look more mature than a lot of startup teams competing for the same buyer attention. ## What This Means for You If you sell to larger customers, infrastructure should stop being an internal-only topic. It directly affects sales confidence. You do not need to become an enterprise infrastructure company overnight. You need to remove the obvious trust gaps first. Start with environment separation, access control, recovery, network boundaries, and operational clarity. Then make those decisions visible enough that a buyer can understand them. That is why I think infrastructure simplicity is still a competitive advantage when it is paired with discipline. A startup that runs on understandable systems, clear boundaries, and predictable pricing is often easier to trust than one hiding behind complexity. If your current setup feels more improvised than intentional, fix the basics before you add more layers. Review your production boundaries, access model, backup posture, and exposure points. Then look at whether your current platform still supports that cleanly on the operational side and on the cost side. A quick pass through your [pricing](/pricing), core VM setup, and network/security foundation is often a better next move than another architectural detour. ## Final Thought The infrastructure that wins enterprise trust is usually less dramatic than founders expect. It is not the stack with the most moving parts. It is the one that makes risk feel contained. That is the part worth remembering. Enterprise buyers are not only asking whether your product works. They are asking whether your company can be trusted when things go wrong. And most of the time, they answer that question by looking at the boring parts first. --- ### Small Enterprise Teams Need Cloud VMs, Not Red Tape URL: https://rafftechnologies.com/blog/why-small-enterprise-teams-gain-the-most-from-cloud-v-ms Published: 2025-09-22T00:00:00.000Z Description: Small Enterprise Teams Need Cloud VMs, Not Red Tape Small enterprise teams often gain more from cloud VMs than large enterprise departments because they feel infrastructure friction immediately. When a team of 3 to 10 people is trying to launch an internal tool, test a workflow, host a small application, or support a client project, waiting weeks for procurement, approvals, and shared infrastructure access can kill momentum. At Raff Technologies, this is one of the clearest use cases for focused cloud infrastructure. A small enterprise team does not always need a giant cloud architecture. It often needs a reliable VM, clear pricing, fast provisioning, backups, snapshots, private networking, and enough control to move without turning every project into an IT ticket. That is the real point of cloud VMs for smaller enterprise teams: they create a practical middle ground between slow enterprise infrastructure and risky shadow IT. The team gets speed and autonomy, while the organization keeps the workload on infrastructure that can be secured, documented, and scaled. ## Enterprise Teams Are Not All the Same Size When people say “enterprise,” they usually imagine huge departments, formal IT roadmaps, centralized procurement, and large infrastructure teams. That picture is incomplete. Inside many enterprise companies, real work often happens in smaller groups: * A data team building an internal dashboard * A product team testing a new customer workflow * A regional office running a local application * A support team automating repetitive tasks * A development team creating a staging environment * A business unit testing a proof of concept * A training team needing temporary Linux or Windows environments * A project team supporting one client implementation These teams may sit inside large organizations, but they operate with small-team urgency. They need infrastructure that moves at project speed, not committee speed. That is why cloud VMs are so useful. They give small enterprise teams a direct path to compute without forcing them to wait for a full platform decision. ## The Problem Is Usually Not Lack of Infrastructure Large companies usually have infrastructure. That is not the problem. The problem is access. A small team may technically have access to enterprise IT, but the path can be slow: * Submit a request * Wait for approval * Clarify the workload * Wait for budget confirmation * Wait for security review * Wait for provisioning * Wait for networking * Wait for credentials * Wait for change windows For major production systems, that process may be necessary. But for a short-term test, internal dashboard, developer environment, prototype, or isolated workload, it can be too heavy. Small teams do not always need more infrastructure. They need a faster path to the right amount of infrastructure. That distinction matters. ## Cloud VMs Give Small Teams a Clean Starting Point A cloud VM gives a small enterprise team something very practical: a clean server they can control. That server can become: * A development environment * A staging server * A test database host * A lightweight production app * A client demo environment * A remote desktop * A training lab * A backup target * An automation runner * A monitoring node * A proof-of-concept environment The value is not only compute power. The value is separation. A project does not need to run on someone’s laptop. A test does not need to pollute a shared server. A temporary workload does not need to become permanent infrastructure. A team can create an environment for the job, document it, secure it, and remove it when it is no longer needed. That is exactly where a [Raff Linux VM](/products/linux-vm) or [Raff Windows VM](/products/windows-vm) can fit into enterprise workflows without forcing a heavy platform migration. ## The Best Use Cases Are Practical, Not Theoretical The strongest cloud VM use cases for small enterprise teams are usually boring in the best way. They are not always giant AI clusters or complex distributed systems. They are the everyday blockers that slow teams down. A team needs a Linux box to test an API. A developer needs a clean Ubuntu server for a client build. A business unit needs a Windows environment for a specific tool. A support team needs a small internal dashboard. A QA team needs a staging server that can be rebuilt. A manager needs a demo environment for next week. A junior developer needs a safe place to learn server setup. These are not “enterprise transformation” projects. They are practical infrastructure needs. And practical infrastructure should not require unnecessary ceremony. If your team is still deciding which VM size fits the workload, start with [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) before overbuying resources. ## Cloud VMs Reduce Shadow IT Risk When small teams cannot get infrastructure through official channels quickly enough, they often improvise. That is where shadow IT begins. Someone uses a personal cloud account. Someone runs a service on a laptop. Someone creates an unmanaged server. Someone stores credentials in the wrong place. Someone forgets who owns the environment. The intention is usually not bad. The team just needs to move. But unmanaged infrastructure creates risk. It becomes harder to secure, monitor, back up, document, and retire. A better model is to give small teams a sanctioned, simple way to launch cloud VMs with clear ownership and guardrails. That gives them speed without losing control. This is where Raff can be useful for enterprise-adjacent teams. The platform keeps the VM model straightforward while still supporting important infrastructure basics such as SSH access, web console access, snapshots, backups, firewall management, and private networking. For teams thinking about secure internal connectivity, [Private Cloud Networks](/products/private-cloud-networks) are a natural next layer after the first VM. ## Small Teams Need Cost Clarity More Than Complex Discounts Enterprise cloud pricing can become difficult to explain, especially when teams only need a few simple workloads. A small team may not have time to forecast dozens of resource categories. They need to know what a server costs, what storage costs, and what happens when the workload grows. This is why cloud VMs are attractive. They give teams a more understandable unit of infrastructure. On Raff, CPU-Optimized VMs start at $9.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe SSD. General Purpose VMs start at $4.99/month for the same 1 vCPU, 1 GB RAM, and 25 GB NVMe SSD on shared vCPU. That makes it easier for small teams to start with a real server without committing to a large enterprise architecture. Cost clarity helps teams move faster because the decision becomes easier to approve. If the workload grows, the team can resize, split roles, or add more VMs later. If the project ends, the team can shut it down instead of leaving unused hardware or forgotten infrastructure behind. You can compare current plans on the [Raff pricing page](/pricing). ## Speed Matters Because Small Teams Have Less Slack Large teams can sometimes absorb slow infrastructure processes. A delay is annoying, but there may be another team, another sprint, or another parallel workstream. Small teams feel delays immediately. If a 5-person team loses three days waiting for a test environment, the impact is visible. The developer waits. The product manager waits. The customer demo waits. The experiment waits. That is why fast provisioning is not just convenience. It is productivity. A VM that can be launched quickly gives the team a place to work now. They can test the idea, validate the setup, and decide whether the workload deserves more investment. This is the same reason cloud VMs are useful for development workflows. The related Raff article [Why More Modern Dev Workflows Start in the Cloud, Not on a Laptop](/blog/why-cloud-v-ms-beat-local-machines-for-modern-dev-workflows) explains why project environments increasingly belong in reproducible cloud infrastructure rather than only on personal machines. ## Cloud VMs Help Teams Stay Focused Small enterprise teams rarely want to become infrastructure teams. They want to ship the internal tool, complete the client project, support the business unit, test the workflow, or launch the demo. The infrastructure should support that goal without becoming the main project. That is why VM simplicity matters. A clean VM model gives teams enough control without forcing them into a maze of services they do not need yet. A good starting point often looks like this: * One VM for the app or tool * Firewall rules for access control * Backups or snapshots for recovery * Private networking if the VM needs to communicate with internal services * Clear ownership inside the team * A documented shutdown or handoff plan That setup is not glamorous, but it works. For many internal projects, that is exactly the point. ## When One VM Is Enough A single VM is often enough when the workload is small, isolated, and easy to understand. Use one VM when: * The project is early * Traffic is low * The workload is internal * Downtime is acceptable * The database is small * The team needs speed more than high availability * The environment is temporary * The project is a proof of concept A single VM gives the team simplicity. There is one server to configure, monitor, secure, and document. That simplicity is valuable, especially when the project is still being validated. If the workload later becomes more important, the team can evolve the architecture. Raff’s [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) explains when to split app, database, worker, and cache roles across multiple VMs. ## When Small Teams Should Add More Structure Small teams should add more infrastructure structure when the workload becomes important enough to justify it. That usually happens when: * More users depend on the service * The database needs stronger protection * Downtime becomes expensive * Backups need formal retention * Background jobs affect app performance * Multiple people need access * Compliance or security review becomes necessary * The project moves from experiment to production At that point, the team may need a separate database, better backup planning, a load balancer, private networking, monitoring, or a more formal deployment process. The key is sequencing. Do not start with enterprise complexity if the workload is still a prototype. But do not keep prototype infrastructure after the workload becomes important. For scaling decisions, [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) is a useful companion guide. ## The Business Case Is Autonomy With Guardrails The real business case for cloud VMs inside small enterprise teams is autonomy with guardrails. Autonomy means the team can move without waiting for every small infrastructure action. Guardrails mean the organization still has a sensible operating model: known infrastructure, documented access, clear billing, recoverable environments, and a path to scale. That balance matters. Too much centralization slows small teams down. Too much freedom creates unmanaged risk. A focused cloud VM platform gives teams a practical middle ground. This is why Raff’s positioning matters for these teams. The platform is not trying to recreate every hyperscaler service. It gives teams the core cloud infrastructure they need first: VMs, storage, networking, backups, snapshots, and simple scaling paths. That is often enough to turn an idea into a working environment. ## What This Means for Small Enterprise Teams If you are part of a small team inside a larger company, the cloud VM question is not only technical. It is operational. Ask yourself: * How long does it take us to get a usable server? * Are we using personal or unmanaged accounts to move faster? * Can we explain the cost of a small workload clearly? * Can we rebuild the environment if something breaks? * Do we know who owns each server? * Are backups and snapshots part of the plan? * Can this project scale if it becomes important? * Can we shut it down cleanly if it does not? If the answer to those questions is unclear, your team may not need a huge new platform. You may need a simpler infrastructure path. Start with the smallest useful setup. Launch the VM. Secure it. Document it. Add backups. Then scale only when the workload proves it deserves more. ## Why Raff Fits This Use Case Raff fits small enterprise teams because the platform is built around practical cloud infrastructure rather than enterprise cloud complexity. A team can start with a [Raff VM](/products/raff-vm), use [Linux VMs](/products/linux-vm) or [Windows VMs](/products/windows-vm) depending on the workload, compare pricing clearly on `/pricing`, and add infrastructure layers only when needed. For internal tools, staging environments, prototypes, demos, and lightweight production workloads, that is often the right model. It gives the team speed without forcing them to buy more cloud than they need. And if the project grows, Raff gives them room to move: resize resources, add storage, use snapshots, separate workloads, or connect services through private networking. ## Final Thoughts Small enterprise teams gain the most from cloud VMs because they sit in the gap between corporate process and startup-style urgency. They need infrastructure that is fast enough for real work, simple enough for lean teams, and structured enough to avoid shadow IT. Cloud VMs solve that gap well. They give teams clean environments, flexible compute, clearer costs, and a path from experiment to production without making every small project feel like a full enterprise platform rollout. For Raff, this is one of the clearest use cases: helping small teams inside larger organizations move faster while keeping infrastructure understandable, secure, and ready to grow. If your team is ready to test that model, start with a [Raff Linux VM](/products/linux-vm), compare plans on the [pricing page](/pricing), and use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) to avoid overprovisioning from day one. --- ### What Is Ubuntu? Beginner’s Guide to Cloud Linux (2026) URL: https://rafftechnologies.com/blog/what-is-ubuntu-cloud-linux-guide Published: 2025-09-04T00:00:00.000Z Description: What Is Ubuntu? Beginner’s Guide to Cloud Linux (2026) Ubuntu is one of the most practical Linux distributions for beginners because it gives you a friendly starting point, strong documentation, a huge software ecosystem, and a clear path from learning Linux to running real cloud servers. For Raff Technologies users, Ubuntu is often the first operating system I recommend when someone wants to deploy a clean Linux VM and understand how cloud infrastructure actually works. Ubuntu is a Debian-based Linux distribution maintained by Canonical. In simple terms, it is an operating system you can install on laptops, desktops, servers, and cloud VMs. Developers use it because it is predictable, well documented, widely supported, and compatible with the tools most modern projects need. I like Ubuntu for beginner cloud work because it removes unnecessary friction. When I test server setups, Ubuntu gives me a clean baseline: `apt` works as expected, common packages are easy to install, and most tutorials for Docker, Node.js, Python, PostgreSQL, Nginx, and security hardening assume Ubuntu or another Debian-based system. ## Why Ubuntu Became So Popular Ubuntu became popular because it made Linux feel less intimidating. Before Ubuntu, many Linux distributions were powerful but harder for beginners to approach. Ubuntu helped change that by focusing on usability, predictable releases, simple installation, and a strong community. That made Linux more accessible to students, developers, businesses, and people who wanted an alternative to Windows or macOS. The name “Ubuntu” comes from an African philosophy often translated around the idea of “humanity to others.” That fits the project’s open-source direction: a system that anyone can use, study, modify, and share. For beginners, the important point is not only history. The important point is that Ubuntu became a default learning path. If you want to learn Linux commands, server administration, package management, SSH, Docker, or web hosting, Ubuntu gives you one of the clearest starting points. ## Ubuntu Desktop vs Ubuntu Server Ubuntu comes in different editions, but beginners usually need to understand two: Ubuntu Desktop and Ubuntu Server. Ubuntu Desktop is designed for personal computers. It includes a graphical interface, browser, file manager, desktop applications, and the familiar experience most people expect from a laptop or workstation operating system. Ubuntu Server is designed for servers and cloud infrastructure. It usually does not include a desktop interface. Instead, you manage it through SSH, terminal commands, configuration files, and services. For Raff users, Ubuntu Server is the important one. When you deploy a [Raff Linux VM](/products/linux-vm), you are usually creating a server environment for apps, APIs, websites, databases, self-hosted tools, automation, or learning. That distinction matters. A beginner may learn Linux on Ubuntu Desktop, but most real cloud work happens on Ubuntu Server. ## Why Developers Like Ubuntu Developers like Ubuntu because it works well with the tools they already use. A fresh Ubuntu server can quickly become a working environment for: * Node.js applications * Python backends * PHP websites * Docker containers * Nginx or Apache web servers * PostgreSQL or MySQL databases * Redis caches * Git repositories * CI/CD runners * Self-hosted apps * Monitoring tools * Automation scripts The `apt` package manager is one of Ubuntu’s biggest strengths. You can install, update, and remove software using consistent commands. That makes Ubuntu easier to document and easier to support in tutorials. For example, if you want to start with JavaScript backend development, Raff already has a tutorial for [installing Node.js on Ubuntu 24.04](/learn/tutorials/install-nodejs-ubuntu-24-04). If you want containers, start with [installing Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04). Ubuntu is popular because it helps beginners move from “I want to learn Linux” to “I deployed something real.” ## Why Ubuntu Works So Well on Cloud VMs Ubuntu is one of the strongest operating systems for cloud VMs because it is lightweight enough for servers, familiar enough for beginners, and supported broadly across cloud environments. A cloud VM needs to be predictable. It should boot cleanly, accept SSH access, handle package updates, run services reliably, and support automation. Ubuntu Server fits that model well. This is why Ubuntu is common in tutorials, hosting guides, DevOps examples, and self-hosting documentation. When someone says “deploy this app on a VPS,” the example is often written for Ubuntu. On Raff, Ubuntu is useful because you can start with a clean VM, install only what the workload needs, and grow from there. You are not forced into a complex platform before you understand the basics. A good beginner path looks like this: * Deploy an Ubuntu VM * Connect over SSH * Create a non-root user * Configure firewall rules * Install the software you need * Run one application * Add backups or snapshots when the environment matters * Resize or split infrastructure later if the workload grows That path teaches real infrastructure without overwhelming the user too early. ## Why Ubuntu 24.04 LTS Is the Best Starting Point Ubuntu 24.04 LTS is the best starting point for most new cloud VM projects in 2026. LTS means Long-Term Support. That matters because beginners and production teams both need stability. You do not want your first server to depend on a short-lived release that forces upgrades before you understand the system. Ubuntu 24.04 LTS gives you a modern package base, broad compatibility, and a long support window. It is new enough for current developer tools, but stable enough to use as a serious server foundation. Use Ubuntu 24.04 LTS when you are: * Learning Linux server administration * Deploying a new web app * Setting up Docker * Running a backend API * Testing PostgreSQL, MySQL, or Redis * Building a staging environment * Creating a self-hosted tool * Writing repeatable setup instructions Ubuntu 22.04 LTS can still make sense for older workloads that were already tested on that release. But for new projects, Ubuntu 24.04 LTS is usually the cleaner default. ## Ubuntu Is Beginner-Friendly, But Still Real Infrastructure Ubuntu is beginner-friendly, but it is not a toy environment. That is important. When you learn Ubuntu on a cloud VM, you are learning real server skills: * SSH access * Users and permissions * Package management * Firewall rules * System services * Logs * Updates * Web server configuration * Process management * Storage layout * Backups and recovery Those skills transfer directly to production environments. This is why Ubuntu is valuable for students and early-career developers. You can start with simple commands, then gradually learn how real infrastructure behaves. A beginner might first learn: ```bash sudo apt update sudo apt upgrade sudo systemctl status nginx ``` Those commands may look small, but they are the foundation of real server work. They teach you how Linux updates packages, manages services, and exposes system state. That is the difference between reading about cloud and actually using it. ## The First Things to Do on a Fresh Ubuntu VM A fresh Ubuntu VM should not go straight into production. It needs a basic security baseline first. Before installing your main application, you should: * Connect with SSH * Create a non-root user * Use SSH key authentication where possible * Configure a firewall * Allow only the ports you need * Apply package updates * Enable automatic security updates if appropriate * Document what the server is for * Add backups or snapshots for important workloads This is where many beginners make the same mistake: they deploy the server, install the app, and forget the basics. The better path is to secure the server first. Raff has a dedicated tutorial for this: [Secure Your Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). Read that before exposing any serious workload to the internet. A common beginner mistake is opening too many ports because something did not work on the first try. Do not do that. Open only what the workload actually needs. ## Ubuntu and Docker Ubuntu is one of the easiest Linux distributions for learning Docker. Docker lets you run applications in containers, which makes it easier to package software with its dependencies. Instead of installing every dependency directly on the system, you run the app in a container with a defined environment. For beginners, Docker can feel like another layer at first. But on Ubuntu, the learning path is well documented and practical. A typical beginner progression is: * Learn basic Ubuntu commands * Install Docker * Run your first container * Learn Docker Compose * Deploy one self-hosted app * Add a reverse proxy * Secure the service with HTTPS * Back up persistent data That progression is useful because it teaches both Linux and modern deployment patterns. If you want to follow that path on Raff, start with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04). From there, you can move into real self-hosted tools like n8n, Uptime Kuma, Gitea, or Portainer. ## Ubuntu and Cloud Automation Ubuntu also works well for cloud automation because it supports cloud-init, shell scripts, package automation, and repeatable provisioning. Cloud-init is especially important. It helps configure cloud instances during first boot: users, SSH keys, packages, hostnames, scripts, and other startup tasks. That makes Ubuntu useful when you want repeatable VM setup instead of manually configuring every server. For beginners, this may sound advanced. But the concept is simple: instead of clicking and typing the same setup steps every time, you define the first-boot behavior once and reuse it. That is how teams move from manual server setup to more reliable infrastructure. If you want to understand the options, read Raff’s guide to [VM provisioning models with cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click). ## Ubuntu Is Not Always the Right Choice Ubuntu is a strong default, but it is not always the right operating system. Choose Debian when you want a more minimal and conservative Linux base. Choose Rocky Linux or AlmaLinux when you need a RHEL-compatible environment. Choose Fedora when you want newer packages and do not need a long production support window. Choose Windows Server when your workload depends on Microsoft technologies such as IIS, Remote Desktop, Windows-only applications, or the .NET Framework. The operating system should match the workload. For most beginners learning Linux and cloud VMs, Ubuntu is the right starting point because it gives you the best mix of ease, documentation, stability, and practical server use. ## Choosing the Right Raff VM for Ubuntu Ubuntu itself is not usually the expensive part. The real decision is how much CPU, RAM, and storage your workload needs. A small learning server does not need the same resources as a production app. A Docker host does not need the same resources as a database server. A Node.js app does not behave the same way as a CI runner. For light learning, testing, and simple tools, a smaller VM may be enough. For production services, databases, CI/CD, or heavier Docker workloads, you should choose more resources and consider dedicated CPU. On Raff, General Purpose VMs start at $4.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe SSD. CPU-Optimized VMs start at $9.99/month for the same 1 vCPU, 1 GB RAM, and 25 GB NVMe SSD with a dedicated vCPU. If you are unsure, read [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) before deploying. You can also compare current options on the [Raff pricing page](/pricing). The safest beginner move is to start small, measure the workload, and resize when you have evidence. ## What This Means for You If you are new to Linux, Ubuntu is one of the best places to begin. It is approachable enough for beginners, useful enough for developers, and serious enough for real cloud servers. You can learn basic commands today and use the same operating system tomorrow to deploy a web app, database, Docker stack, or self-hosted tool. The practical path is simple: * Start with Ubuntu 24.04 LTS * Deploy it on a cloud VM * Secure the server * Install one useful workload * Document what you did * Rebuild or resize when you need to * Add more infrastructure only when the workload asks for it That is how you learn cloud infrastructure without getting lost. Ubuntu gives you the operating system foundation. A Raff VM gives you the cloud environment to practice and deploy on. ## Final Thoughts Ubuntu remains popular because it solves beginner and developer problems at the same time. It is easy enough to learn, stable enough to trust, and flexible enough to run real workloads. That combination is why Ubuntu continues to be one of the first Linux distributions people meet — and one of the operating systems they keep using after they become more experienced. For your next step, deploy a [Raff Linux VM](/products/linux-vm), secure it with [Ubuntu initial server setup](/learn/tutorials/secure-ubuntu-24-04-server), then install a practical workload such as [Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) or [Node.js on Ubuntu 24.04](/learn/tutorials/install-nodejs-ubuntu-24-04). Start small. Learn the server. Then build something real. --- ### The 48-Hour MVP Stack: Simple Infrastructure That Ships URL: https://rafftechnologies.com/blog/48-hour-mvp-stack-simple-infrastructure Published: 2026-03-30T00:00:00.000Z Description: The 48-Hour MVP Stack: Simple Infrastructure That Ships A 48-hour MVP infrastructure stack is a minimal cloud setup that helps teams launch and validate a product within two days using simple compute, managed data services, and lightweight operational tooling. At Raff Technologies, we see this pattern often: early teams lose momentum not because their idea is weak, but because their infrastructure becomes heavier than the product itself. Before the first real user arrives, they are already debating Kubernetes, multi-service deployments, complex CI/CD flows, and cloud architectures designed for traffic they do not yet have. That is usually the wrong first battle. If your MVP needs a DevOps team before it has users, the stack is probably too complicated. Raff Technologies supports 10K+ deployed VMs, 3,000+ customers, and cloud servers that can be deployed in seconds, which gives us a practical view into what early teams actually need when they are trying to ship quickly. This guide explains what a 48-hour MVP infrastructure stack should include, what it should avoid, and how to decide when your product has earned the next layer of complexity. ![Diagram showing a 48-hour MVP stack with users, domain and SSL, a single VM application, managed PostgreSQL, optional object storage, and basic monitoring.](https://raff-images.s3.raffusercloud.com/48_hour_mvp_stack_diagram_png_e5dd4c1cbd.png) *Suggested placement: after the opening block. This visual introduces the whole MVP stack before the reader enters the detailed explanation.* ## The real MVP infrastructure problem is not scale Most MVPs do not fail because the first version was hosted on infrastructure that was too simple. They fail because the team spends too much time building around imaginary scale instead of real usage. At the MVP stage, your primary risk is usually not that the product receives millions of requests overnight. Your primary risk is that you do not launch fast enough to learn whether users care. That changes the infrastructure decision completely. A mature product optimizes for resilience, redundancy, automation, separation of concerns, compliance, and predictable scaling. An MVP optimizes for speed, clarity, and reversibility. Those are different jobs. A simple stack lets one developer understand the whole system. They know where the app runs, where the logs are, where the database lives, how deployment works, and what to check when something breaks. That clarity matters more than architectural elegance when the product is still trying to prove demand. The question is not: > What stack would look impressive to another engineer? The better question is: > What stack gives us the best chance of launching this week and learning from real users? That question usually leads to a smaller, better infrastructure plan. ## What a 48-hour MVP stack should include A practical 48-hour MVP stack should include only the infrastructure required to make the product usable, reachable, and maintainable. For most web-based MVPs, that means: * One application runtime * One primary database * A real domain * SSL * Basic deployment * Basic monitoring * Backups or snapshots * Optional object storage if the product handles files That is enough for a surprising number of early products. The stack can support a SaaS dashboard, a marketplace prototype, an internal tool, a developer product, a content platform, an API service, or a customer portal. What matters is not the exact framework. The framework could be Next.js, Django, Laravel, Rails, Node.js, FastAPI, Go, or something else your team already understands. The more important decision is the operational shape. A good MVP stack should be easy to answer in one sentence: > One app, on simple compute, connected to a managed database, secured with SSL, deployed from Git, monitored enough to catch obvious failures. That sentence is boring. That is the point. Boring infrastructure is often excellent MVP infrastructure because it leaves your attention for the product, users, pricing, onboarding, positioning, and feedback loops. ## The decision framework for choosing your MVP stack The right MVP stack depends on what you need to prove. If you are still validating demand, choose the simplest stack that gets the product in front of users. If you already have traction and a team that can manage more operational layers, a managed platform or more modular architecture may make sense. If you are already operating at scale, microservices can become reasonable. But most MVPs are not there yet. The table below gives a practical decision framework. | Stack type | Setup speed | Complexity | Cost | Scalability | Best fit | | ---------------------- | ----------: | ---------: | -----: | ----------: | ------------------------------------------------------------- | | Single VM stack | Fast | Low | Low | Moderate | MVPs, early SaaS, founder-led products | | Managed platform stack | Medium-fast | Medium | Medium | High | Teams with early traction and limited infrastructure appetite | | Microservices stack | Slow | High | High | Very high | Scale-stage products with multiple engineering teams | A single VM stack is usually the best choice when speed matters more than distributed architecture. It gives you a clear place to run the app, a simple path to deploy updates, and fewer moving parts to debug. A managed platform can be useful when your team wants less server ownership and is comfortable paying more for abstraction. It can reduce some operational burden, but it may also hide details that become important when debugging performance, networking, or cost. A microservices stack should usually wait. It becomes useful when separate teams own separate domains, deployment independence matters, and the product has real operational pressure. Before that, it often creates more coordination cost than value. Use this rule: > If your product has fewer than 10 active users, fewer than 10 engineers, and no proven traffic bottleneck, microservices are probably premature. That does not mean microservices are bad. It means timing matters. ### Choose a single VM stack if Choose a single VM stack if you need to launch quickly, keep costs low, and understand the full environment without involving a dedicated infrastructure team. This is usually the right option when: * You are pre-product-market fit * You need to launch in days, not weeks * The team is small * One developer should be able to debug the whole system * You are running a web app, API, dashboard, internal tool, or early SaaS product * Your current scaling needs are unknown A single VM does not mean careless infrastructure. It means focused infrastructure. You can still use version control, SSL, backups, monitoring, Docker, firewalls, and clean deployment practices. The difference is that everything remains understandable. ![which_mvp_stack_to_choose.png.png](https://raff-images.s3.raffusercloud.com/which_mvp_stack_to_choose_png_61c2121bc1.png) ### Choose a managed platform if Choose a managed platform if you want to avoid server management and are willing to accept more platform constraints. This can work well when: * You have early users * You value convenience over low-level control * Your team does not want to manage operating system updates * Your app fits the platform’s deployment model cleanly * You are comfortable with pricing that may rise as usage grows Managed platforms can be excellent for some teams. The risk is that they sometimes make the first launch easy but later make cost control, migration, or advanced configuration harder. For an MVP, that trade-off may still be worth it. ### Avoid microservices if Avoid microservices if the product does not yet have clear service boundaries, multiple engineering teams, or real scaling pain. Microservices add overhead in several places: * More repositories or packages * More deployments * More internal networking * More logs * More secrets * More failure modes * More coordination * More local development complexity For a mature platform, that overhead may be worth it. For a young MVP, it usually is not. A distributed system is harder to debug than a simple one. If the product itself is still changing every day, the infrastructure should not be the most rigid part of the company. *Suggested placement: after the decision framework table. This visual reinforces why the single VM stack is usually the best fit for a fast MVP launch.* ## The core components of a simple MVP stack A good MVP stack is not random. It is deliberately small. Each part should have a clear job. If a component does not help the product launch, support users, or reduce real operational risk, it probably does not belong in the first version. ### Application compute The compute layer is where your application runs. For a 48-hour MVP, a Linux VM is often the most direct option. It gives you a dedicated server environment, full root access, predictable resources, and enough flexibility to run common frameworks, APIs, background workers, reverse proxies, and Docker-based setups. This is one reason VMs remain underrated for early-stage products. They are easy to reason about. You know where the app is. You know how to restart it. You know where the logs live. You know what resources are attached to it. You can SSH into the machine, inspect the system, and fix issues directly. That level of visibility is valuable when speed matters. A single VM can run: * A web application * An API server * A reverse proxy such as Nginx or Caddy * Background workers * Docker Compose * A small Redis instance * Lightweight internal tools * A staging environment The goal is not to put everything on one machine forever. The goal is to avoid splitting things before splitting solves a real problem. ### Database For most MVPs, the database should be boring and reliable. PostgreSQL is usually the default choice because it is mature, widely supported, flexible, and familiar to most engineering teams. Whether you use managed PostgreSQL or a carefully maintained database setup, the key principle is the same: do not let database operations become the product. At the MVP stage, you do not want your best hours going into backup scripts, replication design, database tuning, or emergency maintenance unless your product specifically requires that depth. A managed database reduces operational burden. It lets the team focus on schema design, data quality, and product behavior instead of database administration. If managed PostgreSQL is available in your chosen environment, use it. If not, keep the database setup conservative, documented, backed up, and easy to migrate later. ### Domain and SSL A real domain and SSL are not optional for a serious MVP. They are basic technically, but important psychologically. A real domain makes the product easier to share, easier to test, easier to support, and easier for users to trust. Early products already ask users to tolerate some rough edges. Do not make the product feel temporary before the user even signs in. For most MVPs, a simple setup is enough: * Domain connected to the app * HTTPS enabled * Redirects configured correctly * Basic DNS records documented * No unnecessary CDN or edge complexity unless the product needs it A domain and SSL layer gives the product a minimum level of credibility. That matters when asking early users, investors, teammates, or pilot customers to take the product seriously. ### Deployment flow Deployment should be boring. A simple MVP deployment flow might look like this: * Code lives in GitHub * Changes are merged into the main branch * Basic tests or checks run * The app builds * The server pulls or receives the new version * The process restarts cleanly * Logs can be reviewed if something breaks That is enough to start. You do not need an enterprise CI/CD platform on day one. You need a repeatable deployment flow that the team trusts. If Docker makes deployment more consistent, use it. If Docker becomes another layer your team has to fight, skip it until it earns its place. The tool is not the point. Reliable shipping is the point. ### Monitoring MVP monitoring should answer simple questions: * Is the app up? * Is it responding? * Is it failing? * Are CPU, memory, or disk usage becoming dangerous? * Can someone see logs quickly? * Will the team know if something important breaks? That is enough for the first version. A wall of dashboards does not make an MVP more responsible. Useful visibility does. Start with uptime checks, basic server metrics, error visibility, and logs that a normal developer can understand. Add deeper observability when the product has enough users or revenue to justify it. ### Backups and snapshots Backups are not advanced infrastructure. They are basic survival. Even an MVP needs a way to recover from mistakes. Early teams often move quickly, change schemas, run scripts, test migrations, and experiment with product logic. That speed is useful, but it increases the chance of accidental data loss. A practical MVP backup plan should include: * Database backups * VM snapshots before risky changes * Clear restore expectations * Basic documentation on where backups live * Periodic restore testing when the product becomes business-critical The key is not to build an elaborate disaster recovery system on day one. The key is to avoid having no recovery path at all. ### Object storage Object storage should be added only when the product actually needs it. If users upload files, images, documents, generated assets, exports, or media, object storage makes sense. If the product does not handle files, adding object storage “just in case” creates another service to configure and monitor. A useful rule is: > Store application state in the database. Store user files and large static assets in object storage. Do not add object storage until the product has a real file-storage need. This keeps the initial stack clean while leaving a clear path to expand later. ## Best practices for 48-hour MVP infrastructure The best MVP infrastructure is not the smallest possible stack. It is the smallest responsible stack. That distinction matters. A careless stack creates future pain. A disciplined stack avoids unnecessary complexity while still giving the product a stable foundation. ### Keep the architecture flat Keep the application as close together as possible until the product proves why it should be split. A flat architecture reduces coordination cost. There are fewer network calls, fewer deployment paths, fewer logs, fewer secrets, and fewer places for bugs to hide. This does not mean writing messy code. You can still structure the application cleanly internally. The point is to avoid operational separation before the business has earned it. ### Use tools your team already understands For a 48-hour MVP, familiarity beats novelty. If your team knows Laravel, use Laravel. If your team knows Django, use Django. If your team is fastest with Next.js, use Next.js. The framework choice matters less than the team’s ability to build, deploy, debug, and improve the product quickly. A technically superior tool that slows the team down is usually the wrong MVP choice. The best stack is often the one your team can operate calmly under pressure. ### Make debugging obvious A good MVP stack should make debugging easy. When something breaks, the team should know where to look first. That means logs should be accessible, deployment history should be understandable, and the relationship between components should be simple. If a user reports a problem, you should be able to ask: * Is the app running? * Did the last deployment cause this? * Is the database reachable? * Are environment variables correct? * Are errors appearing in logs? * Is the server under resource pressure? If answering those questions requires searching across five tools and three services, the stack may be too complex for the stage. ### Delay orchestration until it solves a real problem Kubernetes is powerful, but it is rarely the right first move for a 48-hour MVP. The problem is not Kubernetes itself. The problem is operational timing. Kubernetes introduces clusters, manifests, services, ingress, secrets, resource requests, monitoring, deployment strategies, and operational concepts that must be understood and maintained. That investment can be justified when the product needs it. It is much harder to justify before users arrive. Use orchestration when the product has enough scale, team structure, or reliability requirements to make the overhead worthwhile. Until then, keep deployment simpler. ### Treat infrastructure changes as product decisions Infrastructure decisions affect product speed. Every new tool changes how fast the team can deploy, debug, hire, onboard, document, and recover. That means infrastructure decisions should not be made only on technical preference. Before adding a new component, ask: * What user problem does this help solve? * What operational problem does this remove? * What new maintenance does this introduce? * Who will own it? * Can we launch without it? * Can we add it later without major damage? If the answer is unclear, wait. ## What not to use in the first 48 hours A good MVP stack is defined as much by what it excludes as what it includes. The early version should avoid tools that create operational weight before the product proves it needs them. ### Do not start with Kubernetes by default Kubernetes is excellent for certain production workloads, but it is not automatically excellent for MVPs. At the MVP stage, Kubernetes often adds more decisions than it removes. You need to think about cluster setup, ingress, container registries, secrets, scaling policies, deployment patterns, resource limits, and monitoring before the product has proven demand. That can be a poor trade. If your MVP can run on a single VM with a simple deployment process, start there. You can move to orchestration later when the product has earned the shift. ### Do not split into microservices too early Most MVPs do not have a service-boundary problem. They have a focus problem. Splitting a young product into services can make the team feel more “scalable,” but it also creates more deployment work, more integration work, and more debugging complexity. Worse, the boundaries are often wrong because the product is still changing. Good service boundaries emerge from real usage, real domain understanding, and real team ownership. Guessing them too early usually creates rework. ### Do not add tools for imagined future needs A tool that might be useful later is not automatically useful now. Object storage, queues, service meshes, distributed tracing, event buses, orchestration, and multiple environments can all be valuable. But each one should earn its place. At the MVP stage, “we might need this later” is not enough. The better question is: > Does this help us launch, validate, recover, or serve users right now? If not, document it as a future option and move on. ## When to add more infrastructure Simple infrastructure does not mean staying simple forever. Healthy products evolve. They begin with a clear foundation, then add complexity when growth makes the trade worthwhile. The mistake is not adding complexity. The mistake is adding it before there is evidence. Add more infrastructure when one of these conditions becomes true: * Users are growing and performance bottlenecks are measurable * Deployments are becoming risky or too frequent for the current setup * The team has grown and ownership boundaries are becoming clearer * Background jobs need to be separated from request handling * File storage, caching, queues, or search become core product needs * Security or compliance requirements demand stronger separation * Downtime risk becomes more expensive than infrastructure complexity * The cost of staying simple becomes higher than the cost of evolving That is what “complexity should be earned” means. A growing product may eventually need load balancing, separate services, caching, object storage, queues, staging environments, infrastructure as code, or orchestration. But those should come from pressure, not fear. Fear says: > We might need this someday, so let’s build it now. Discipline says: > We know what would trigger this upgrade, and we will add it when that trigger appears. The second approach is usually healthier. ![Roadmap showing MVP infrastructure evolving from a single VM and managed PostgreSQL to validation, optimization, and scale-stage infrastructure.](https://raff-images.s3.raffusercloud.com/tech_roadmap_for_scalable_growth_png_4863bcb0fd.png) *Suggested placement: after the “When to add more infrastructure” section. This visual explains the growth path from simple MVP infrastructure to scalable infrastructure.* ## How this applies on Raff Technologies Raff Technologies is designed around a simple idea: cloud infrastructure should be fast, understandable, and reliable without forcing early teams into unnecessary complexity. That philosophy fits the 48-hour MVP stack well. For teams building an MVP, a Raff Linux VM gives you a straightforward place to run the first version of the product. You can deploy common Linux distributions, use full root access, connect over SSH, install the runtime your application needs, configure a reverse proxy, and run the app in an environment your team can understand. Raff Linux VPS plans start at $4.99/month, support 9 Linux distributions, and can be deployed in under 60 seconds. That matters for MVPs because infrastructure setup should not consume the week you planned to spend building and validating the product. A simple Raff-based MVP stack might look like this: * Raff Linux VM for the application runtime * PostgreSQL for relational data * Domain and SSL for trust * Basic monitoring for uptime and resource usage * Snapshots or backups before risky changes * Object storage only if the product handles files or generated assets The decision rationale is simple: early teams need infrastructure that preserves momentum. At Raff, we see that small teams often move faster when they can understand the whole system without waiting on infrastructure specialists. A single VM gives enough control to deploy real software, enough flexibility to evolve, and enough simplicity to keep the team focused on users rather than cloud architecture. If your decision framework points toward a single VM stack, Raff is a practical place to start because it gives you the core compute layer without forcing a complex platform model on day one. ## Common mistakes when building MVP infrastructure Even simple stacks can become messy if the team does not make deliberate choices. The most common mistake is treating the MVP as a smaller version of a future enterprise platform. That mindset leads to too many services, too many tools, and too many assumptions before the product has evidence. Another mistake is ignoring recovery. Some founders hear “simple infrastructure” and interpret it as “no operational discipline.” That is dangerous. Simple infrastructure still needs backups, SSL, access control, and basic monitoring. A third mistake is spreading the stack across too many providers too early. It can feel flexible, but it often creates more account management, more billing complexity, more networking questions, and more failure points. Early teams usually benefit from fewer surfaces to manage. The final mistake is optimizing for what looks impressive rather than what ships. A 48-hour MVP stack should not be judged by how sophisticated the diagram looks. It should be judged by whether the product gets into users’ hands quickly, reliably, and with enough operational clarity to improve it. ## Conclusion A 48-hour MVP stack is not about choosing weak infrastructure. It is about choosing infrastructure that matches the stage of the product. Before product-market fit, the best infrastructure decision is often the one that helps you launch, learn, and iterate with the least operational drag. For many teams, that means a single VM, a reliable database, SSL, basic monitoring, and a clear recovery path. You can always add complexity later. In fact, you should — when users, revenue, team size, or operational pressure justify it. If you are building your first MVP and want a simple place to run it, start with a Raff Linux VM, keep the stack understandable, and add each new layer only when the product earns it. --- ### Why Cheap Cloud Often Costs MSPs More Than They Expect URL: https://rafftechnologies.com/blog/why-cheap-cloud-often-costs-msps-more Published: 2026-04-17T00:00:00.000Z Description: Why Cheap Cloud Often Costs MSPs More Than They Expect Cheap cloud is often expensive for MSPs. Not because the monthly VM price is high. Because the total cost of delivering service around that VM gets worse. The cheaper the infrastructure looks on paper, the more often MSPs end up paying through labor, billing confusion, reactive support, and awkward client conversations. At Raff Technologies, that distinction matters a lot because MSPs do not really buy infrastructure the way a solo developer does. They buy something they have to package, explain, defend, and operate repeatedly across multiple clients. That is why I think many MSPs evaluate cloud pricing too narrowly. They compare the advertised server number and stop there. But a cloud platform is not only a line item. It is an operating model. If the platform introduces billing ambiguity, bandwidth anxiety, slow provisioning, or too much manual work, the invoice may look cheap while the service margin quietly erodes. We have thought about this carefully at Raff Technologies. One reason we include unmetered bandwidth on every plan is that bandwidth overage billing creates the wrong behavior: teams become more hesitant, more defensive, and less confident about scaling or testing because they are designing around invoice uncertainty instead of actual workload needs. That is not only a developer problem. For MSPs, it becomes a packaging problem. When the underlying cost model is unpredictable, your service promise becomes harder to price cleanly too. That logic already shows up in Raff’s public positioning around unmetered bandwidth, transparent pricing, and simple VM economics. It is also why I think “cheap cloud” can be one of the most expensive decisions an MSP makes. ## The Sticker Price Is Not the Operating Cost This is the first thing I would want any MSP owner to separate clearly. A low VM price is not the same thing as a low delivery cost. If the platform is slow to provision, awkward to explain, difficult to standardize, or full of cost conditions your team has to remember, the infrastructure stops being “cheap” the moment service delivery begins. That is especially true for MSPs because they do not feel cloud cost only once. They feel it again and again in onboarding, templating, support, billing, recovery work, and client-facing expectation management. That is why I do not think MSPs should ask only: “How much is the server?” They should ask: “How much repeat work will this platform create around the server?” That second question is usually more expensive. ## Hidden Labor Is Where Cheap Cloud Starts to Fail In my view, hidden labor is the biggest reason cheap cloud hurts MSPs. A platform can undercut everyone on entry price and still cost more in real operations if your team has to keep solving the same avoidable problems: * explaining unclear invoices * tracking bandwidth assumptions * cleaning up inconsistent deployments * waiting too long for environments to be ready * manually checking what is or is not included * answering client questions that should never have existed in the first place This is where “cheap” turns into drag. MSPs win when they can repeat clean delivery. They lose margin when every client stack becomes a small exception. If provisioning is slow, billing is vague, or the platform requires too much interpretation, the team spends more time managing friction and less time delivering value. That is why I think the real comparison is not cheap cloud versus expensive cloud. It is cheap-looking cloud versus low-friction cloud. Those are very different things. ## Unclear Billing Is a Margin Problem, Not Just an Annoyance I think this is the most underestimated part of the whole conversation. Unclear cloud billing does not just frustrate technical buyers. It damages packaging. An MSP needs to turn infrastructure into a service that clients can understand. That means the pricing underneath matters. If the base cost changes unpredictably, or if bandwidth, snapshots, traffic behavior, or usage edge cases create surprise charges, the MSP has two bad options: either absorb the uncertainty, or pass it on and make the client relationship harder. Neither is attractive. This is why transparent pricing matters much more in MSP environments than in one-off developer experiments. A developer might tolerate a slightly confusing invoice once. An MSP has to build a repeatable service model on top of it. If the cloud provider’s bill is hard to interpret, the MSP’s own pricing becomes harder to defend. Raff’s public pricing and product pages are strong on exactly this point: published VM tiers, unlimited bandwidth, and straightforward entry pricing starting from **$4.99/month** on the public pricing page. That is not just a positioning line. It changes how easily a provider can package, quote, and standardize a service. For MSPs, pricing clarity is operational clarity. ([pricing](/pricing), [Raff VM](/products/raff-vm)) ## Bandwidth Surprises Change Behavior in the Worst Way This is one of the easiest cloud costs to underestimate and one of the worst for MSP confidence. Bandwidth pricing changes behavior before it even changes the bill. Teams test less confidently. They plan more defensively. They hesitate before launching something public. They worry that a successful month will cost more than expected. That is a bad mindset for any infrastructure team. It is even worse for an MSP, because your client is paying you for confidence, not hesitation. If every growth event, traffic spike, file delivery pattern, or client success story might trigger an uncomfortable cost discussion, the platform is quietly undermining your service model. That is why I think unmetered bandwidth is more than a feature bullet. It is a commercial simplifier. Raff’s current public product pages explicitly position **unlimited bandwidth** across the VM offering, and Raff has already made the public argument that bandwidth overage billing encourages the wrong operating behavior. I think that point is especially true for MSPs. Predictable transfer economics make it easier to quote, easier to sell, and easier to support. :contentReference[oaicite:3]{index=3} ## Slow Provisioning Is More Expensive Than People Admit A slow provisioning flow is one of those costs that rarely shows up in cloud comparison charts, but MSPs feel it immediately. The more clients you manage, the more expensive delay becomes. If standing up a clean environment takes too long, if standard builds do not feel repeatable, or if new workloads require too much manual work before they are usable, then your platform is consuming one of the most valuable things an MSP has: team attention. This is why fast deployment matters more than it looks. It affects: * onboarding speed * migration turnaround * recovery readiness * how quickly you can spin up a replacement environment * how confidently you can standardize templates across clients Raff’s public product and pricing pages currently position VM deployment as happening in **seconds** and, on the Linux product page, **under 60 seconds**. That kind of speed matters because it helps MSPs preserve momentum during onboarding, support, and recovery situations instead of turning basic infrastructure creation into a ticket queue. :contentReference[oaicite:4]{index=4} A cheap VM that takes too much organizational effort to turn into a working client environment is not actually cheap. ## Cheap Cloud Gets Worse When You Sell Backup and Recovery This is where the problem becomes more serious. An MSP is not only selling compute. It is often selling support, continuity, backup confidence, and some version of operational trust. The more unclear the underlying infrastructure becomes, the harder it is to sell those promises cleanly. If your team already has to explain variable billing, interpret transfer costs, and work around slow provisioning, then backup and recovery design become harder to package too. You cannot build a clean service promise on top of a messy cost foundation. This is why I think MSPs should evaluate cloud platforms based on how well they support standardization around: * predictable monthly quoting * fast repeat deployments * low-friction backup posture * simple upgrade paths * fewer support-triggering surprises That is also why this topic fits naturally into Raff’s broader backup and recovery content. If you are packaging managed services, the next useful reads are [Cloud Server Backup Strategies: Snapshots, RPO, and Recovery Planning](/learn/guides/cloud-server-backup-strategies) and [High Availability vs Disaster Recovery: What Small Teams Actually Need](/learn/guides/high-availability-vs-disaster-recovery-small-teams). Cheap infrastructure is not helpful if it makes recoverability harder to price and operate. ## What Good Cloud Economics Actually Look Like for MSPs For MSPs, good cloud economics usually look less dramatic than people expect. It is not about chasing the lowest visible price. It is about reducing the number of expensive unknowns. That means the better platform is often the one that gives you: * predictable billing * fewer edge-case charges * repeatable deployments * cleaner internal packaging * fast spin-up for new and replacement environments * lower support burden around infrastructure basics This is exactly where a simpler cloud model becomes valuable. Raff’s public pricing currently starts at **$4.99/month**, includes **NVMe storage**, and positions **unlimited bandwidth**, fast deployment, and a **14-day money-back guarantee**. That combination is useful because it lowers both technical and commercial friction. The point is not that every MSP should buy the absolute cheapest VM. The point is that a provider with simpler economics can make the MSP’s own business model healthier. :contentReference[oaicite:5]{index=5} ## What This Means for You If you run an MSP, I would stop asking only: “Which cloud is cheaper?” I would ask: “Which cloud is cheaper to operate repeatedly across clients?” That is the more useful question. If the platform introduces billing confusion, bandwidth anxiety, slow provisioning, or too much manual work, your margin will feel that before your finance sheet does. Cheap cloud becomes expensive the moment your team has to keep compensating for it. If you are evaluating that trade-off right now, start with [Raff pricing](/pricing), look at [Raff VM](/products/raff-vm) as the base infrastructure layer, and then review whether your service packaging around backup, recovery, and client onboarding would get simpler or harder on top of it. In my view, that is the real economics test. Because MSPs do not win by buying the lowest advertised VM. They win by delivering infrastructure with the least unnecessary friction. --- ### Best VPS for Cloud-Native DevOps Teams in 2026 URL: https://rafftechnologies.com/blog/best-vps-cloud-native-devops-2026 Published: 2026-02-22T00:00:00.000Z Description: Best VPS for Cloud-Native DevOps Teams in 2026 The best VPS for cloud-native DevOps teams is a high-performance virtual server that provides predictable compute, fast NVMe storage, reliable networking, root access, transparent pricing, and enough flexibility to run containers, APIs, CI/CD runners, databases, and internal tools. Modern DevOps teams do not just need a cheap server. They need infrastructure that supports real engineering workflows. A cloud-native team may use a VPS for Docker workloads, staging environments, API services, CI/CD runners, observability tools, internal dashboards, test databases, automation jobs, or small production systems. These workloads behave differently from traditional shared hosting. They need more control, better I/O performance, predictable pricing, and a clean path to scale when usage grows. The mistake many teams make is assuming cloud-native infrastructure must always start with complex managed platforms, Kubernetes clusters, or large cloud accounts. Sometimes that is true. But for many teams, especially early-stage SaaS companies, small DevOps teams, freelancers, agencies, and infrastructure-conscious startups, a properly configured VPS is faster, simpler, and more cost-effective. This guide explains what DevOps teams should look for in a VPS in 2026, when a VPS makes sense, when it does not, and how Raff Technologies fits into the decision. ## Cloud-native teams need more than basic hosting Traditional hosting is usually designed around websites. Cloud-native teams usually need more than that. They need an environment where they can install packages, run containers, configure firewalls, manage SSH access, deploy APIs, test infrastructure scripts, run background workers, connect storage, and debug performance issues without fighting platform limitations. A good VPS for DevOps should support: * Full root access * SSH key authentication * Docker and container workloads * Fast provisioning * Predictable CPU and RAM * NVMe SSD storage * Unmetered or predictable bandwidth * Cloud firewall controls * DDoS protection * Backups and snapshots * Monitoring compatibility * API or automation support * Clear upgrade paths This is different from shared hosting. Shared hosting hides most of the server environment. That can be fine for a simple website, but it is limiting for DevOps teams. You cannot properly test deployment flows, container behavior, background jobs, custom runtimes, system packages, or infrastructure automation when the environment is locked down. Cloud-native teams need control. A VPS gives them that control without requiring the complexity of a full enterprise cloud account. ## What makes a VPS good for DevOps in 2026? A good DevOps VPS should be judged by workload behavior, not marketing labels. The most important factors are: | Factor | Why it matters for DevOps | | -------------------- | ----------------------------------------------------------------------------- | | CPU performance | Affects builds, APIs, workers, containers, and concurrent workloads | | RAM | Keeps databases, containers, caches, and application runtimes stable | | NVMe storage | Improves build speed, database I/O, container startup, and file operations | | Network quality | Affects deployments, backups, API latency, remote access, and service traffic | | Pricing transparency | Prevents surprise bills from bandwidth, I/O, or hidden fees | | Provisioning speed | Helps teams spin up dev, test, staging, and recovery environments quickly | | Root access | Gives teams full control over the operating system and runtime | | Security features | Firewalls, SSH keys, DDoS protection, and backups reduce operational risk | | Scalability | Lets teams resize or add servers as workloads grow | | Support | Matters when infrastructure issues affect delivery or customers | DevOps teams should not choose a VPS only because it is cheap. They should choose the provider that gives the best balance of performance, reliability, cost predictability, and operational control. A low-cost server with weak I/O, poor networking, hidden bandwidth limits, or unstable performance can become expensive quickly. The monthly price may be low, but the engineering time lost to debugging, slow builds, failed deploys, and downtime can be much higher. ## The decision framework for choosing a DevOps VPS The right VPS depends on the workload. A staging server, CI/CD runner, database VM, internal dashboard, Docker host, and production API do not need the same resource profile. Before choosing a VPS, define the job the server must perform. Use this framework: | Workload | Best VPS priority | Recommended direction | | ------------------- | --------------------------------------------- | ------------------------------------------------------ | | Development server | Cost efficiency and flexibility | Small Linux VPS with root access | | Staging environment | Similarity to production | General Purpose VPS with enough RAM | | Docker host | CPU, RAM, and NVMe storage | Balanced VPS with room for containers | | CI/CD runner | CPU consistency and fast disk | CPU-Optimized VPS | | Production API | CPU consistency, uptime, network quality | CPU-Optimized or larger balanced VPS | | Database workload | RAM, storage I/O, backups | CPU-Optimized VPS with NVMe and backup strategy | | Internal dashboard | Reliability and predictable cost | General Purpose VPS | | Automation server | CPU and long-running process stability | General Purpose or CPU-Optimized depending on job load | | Kubernetes lab | Multiple VMs, private networking, root access | Several smaller Linux VMs | | Small SaaS platform | Performance, uptime, scaling path | 4 vCPU / 8 GB RAM class or higher depending on usage | The practical rule is simple: > Choose a VPS based on the workload’s bottleneck, not the cheapest plan on the page. If the workload is CPU-bound, prioritize compute. If it is memory-bound, prioritize RAM. If it writes often, prioritize NVMe storage. If it serves users, prioritize uptime and network reliability. If it is experimental, prioritize cost and flexibility. This makes the VPS decision much clearer. ## VPS vs big cloud: which is better for DevOps teams? Large cloud platforms are powerful. They offer managed databases, serverless services, object storage, queues, Kubernetes, IAM systems, global networking, observability tools, and advanced enterprise features. For some teams, that ecosystem is necessary. But not every DevOps workload needs that complexity. A VPS can be a better choice when the team needs: * A predictable monthly bill * A simple Linux environment * Full root access * Fast setup * Docker or Docker Compose * A staging server * A CI/CD runner * A test database * A production API with moderate traffic * An internal tool * A self-hosted monitoring stack * A small SaaS deployment * A Kubernetes lab or lightweight cluster The difference is not “VPS is better” or “big cloud is better.” The real question is: > Does this workload need cloud platform complexity, or does it need a reliable server? Many DevOps workloads are stable, understandable, and server-shaped. They do not need five managed services, complex IAM rules, usage-based billing surprises, and a long configuration chain. They need a fast machine, predictable networking, enough storage, a clean Linux image, and the freedom to configure the environment. That is where a modern VPS can be the better tool. ## CPU performance matters for builds, APIs, and workers CPU performance is one of the most important factors for DevOps workloads. A slow or inconsistent CPU affects: * CI/CD build times * Test execution * API response time * Container startup * Background workers * Data processing jobs * Compression and encryption * Package installation * Dependency builds * Queue processing For DevOps teams, CPU performance is not only about user-facing speed. It directly affects engineering velocity. If builds are slow, developers wait. If tests are slow, releases slow down. If workers fall behind, product behavior becomes unreliable. If APIs respond slowly, customers feel it. This is why CPU architecture matters when comparing VPS providers. Modern AMD EPYC processors are strong for multi-threaded workloads, containerized applications, and concurrent server tasks. For DevOps teams running builds, APIs, workers, and databases, modern CPU generations can make a real difference. When evaluating a VPS provider, ask: * What CPU generation is being used? * Are vCPUs shared or dedicated? * Is CPU performance consistent under load? * Are there CPU-Optimized plans? * Are benchmarks available? * Is performance stable during peak usage? The cheapest VPS is not always the best value. A slightly more expensive server that completes builds faster, handles more API requests, and stays stable under load may be the better DevOps decision. ## NVMe storage is critical for modern workloads Storage performance matters more than many teams expect. DevOps workflows often create a lot of disk activity: * Pulling container images * Building Docker layers * Installing dependencies * Running database queries * Writing logs * Creating artifacts * Running test suites * Processing files * Storing temporary build data NVMe SSD storage improves these workflows because it offers lower latency and higher throughput than older storage types. This affects: * Faster container startup * Faster package installs * Faster database reads and writes * Faster build pipelines * Faster local caching * Better performance under concurrent disk activity For Docker and Kubernetes workloads, storage speed can be especially visible. Container images, layer caching, logs, and volumes all depend on disk performance. If a VPS provider still uses slow storage, the CPU may not matter as much because the workload becomes I/O-bound. In 2026, DevOps teams should treat NVMe storage as a baseline expectation, not a premium luxury. ## Predictable pricing matters more than complex flexibility DevOps teams often care about cost, but they care even more about cost predictability. Large cloud platforms can become expensive because the bill may include separate charges for compute, storage, bandwidth, snapshots, I/O, IPs, load balancers, managed services, logs, metrics, and data transfer. That flexibility can be useful, but it also creates uncertainty. For stable workloads, predictable pricing is often better. A DevOps team should be able to answer: * What will this server cost each month? * Is bandwidth included? * Are there hidden transfer fees? * Is storage included? * Are backups and snapshots priced clearly? * Is the pricing understandable before deployment? * Can we scale without billing surprises? Predictable pricing is especially important for startups, agencies, freelancers, small teams, and internal platform teams managing multiple environments. If the workload is stable, a high-performance VPS with transparent monthly pricing can be easier to plan than a usage-based cloud setup. ## Containers do not always require Kubernetes Cloud-native teams often use containers. But containers do not automatically mean Kubernetes. For many teams, Docker or Docker Compose on a VPS is enough. This is especially true for early-stage products, internal tools, staging servers, dev environments, small APIs, and self-hosted services. A VPS can run: * Docker containers * Docker Compose stacks * Reverse proxies * Background workers * Databases for test or small production use * Monitoring agents * CI/CD runners * Internal tools * Web apps and APIs Kubernetes becomes useful when the workload needs orchestration, scheduling, self-healing, rolling deployments, service discovery, multiple nodes, and operational separation across teams. Before that, it can be unnecessary overhead. A simple VPS-based container setup is often easier to understand, easier to debug, and cheaper to operate. Use Kubernetes when the architecture earns it. Use a VPS with Docker when the team needs speed, simplicity, and control. ## Best VPS baseline for cloud-native projects A good starting configuration for many cloud-native DevOps workloads is: ```text 4 vCPU 8 GB RAM NVMe SSD storage Unmetered bandwidth Linux OS Full root access SSH key authentication Firewall controls Backups or snapshots ``` This is not the right size for every workload, but it is a strong baseline for early-stage SaaS apps, Docker hosts, staging environments, internal tools, APIs, automation servers, and small production workloads. Smaller workloads can start lower. For example: | Workload | Starting size | | -------------------- | -------------------------------- | | Small dev server | 1–2 vCPU, 1–2 GB RAM | | Staging app | 2 vCPU, 2–4 GB RAM | | Small production API | 2 vCPU, 4 GB RAM | | Docker Compose app | 2–4 vCPU, 4–8 GB RAM | | CI/CD runner | 4+ vCPU, 8+ GB RAM | | Database VM | 4+ vCPU, 8+ GB RAM, NVMe storage | | Moderate SaaS app | 4 vCPU, 8 GB RAM or higher | The correct plan depends on workload behavior. Start with a safe baseline, monitor usage, then resize when evidence appears. ## Security features DevOps teams should check A VPS for DevOps should not only be fast. It should also provide the basic security controls needed for production and internal infrastructure. Look for: * SSH key authentication * Full root access with control * Cloud firewall support * DDoS protection * Private networking options * Backups and snapshots * OS image choices * Clear access controls * Monitoring compatibility * Ability to restrict management ports DevOps teams should avoid exposing everything directly to the public internet. A safer VPS setup usually includes: * Public access only for HTTP and HTTPS * SSH restricted to trusted IPs, VPN, or bastion access * Databases kept private * Firewalls configured with least privilege * Backups enabled * Patching and updates scheduled * Logs monitored A good VPS provider gives teams the building blocks. The team still needs to configure them properly. ## When a VPS is not enough A VPS is powerful, but it is not the right answer for every workload. You may need a more advanced cloud architecture when: * You need managed databases with automated failover * You need multi-region traffic routing * You need advanced IAM and compliance controls * You need large autoscaling fleets * You need fully managed Kubernetes * You need event-driven serverless architecture * You need complex data pipelines * You need advanced enterprise networking * You cannot tolerate single-server failure * You need strict regulatory architecture This is where larger cloud platforms or more complex architectures may make sense. The point is not to force everything onto a VPS. The point is to avoid unnecessary complexity for workloads that do not need it. A modern VPS is best for workloads where server-level control, performance, predictable pricing, and simplicity are more valuable than a large catalog of managed services. ## Why Raff fits cloud-native DevOps teams Raff Technologies is built around a simple infrastructure promise: Fast. Simple. Reliable. For DevOps teams, that means a VPS platform that supports modern cloud-native workflows without forcing unnecessary complexity. Raff Linux VMs support 9 Linux distributions, deploy in under 60 seconds, and provide full root access with SSH key authentication. That makes them practical for developers and DevOps teams that need quick environments for testing, staging, production APIs, containers, runners, and internal systems. Raff infrastructure includes: * AMD EPYC processors * NVMe SSD storage * DDR5 ECC memory * Unmetered bandwidth * 3 Gbps port speed * 99.9% uptime SLA * DDoS protection * Cloud firewall support * Docker-ready Linux environments * Transparent monthly pricing * Plans starting at $4.99/month This combination matters because DevOps teams usually do not want infrastructure that slows them down. They want to deploy quickly, control the environment, understand the bill, and scale when the workload proves the need. Raff is especially useful for: * Docker-based applications * Staging environments * Development servers * CI/CD runners * Backend APIs * Small SaaS platforms * Internal tools * Automation servers * Test databases * Kubernetes labs * Self-hosted DevOps tools The goal is not to replace every part of the cloud ecosystem. The goal is to provide a faster, simpler, more predictable VPS foundation for teams that need performance and control without enterprise-level cloud complexity. ## VPS checklist for DevOps teams Before choosing a VPS provider in 2026, use this checklist: * Does the provider use modern CPUs? * Is NVMe SSD storage included? * Is bandwidth predictable or unmetered? * Are there hidden fees? * Can servers deploy quickly? * Is full root access available? * Is SSH key authentication supported? * Are Docker and container workloads supported? * Are backups and snapshots available? * Is cloud firewall support included? * Is DDoS protection available? * Are there General Purpose and CPU-Optimized plans? * Can the server be resized later? * Is uptime clearly stated? * Is support available when infrastructure becomes urgent? * Does the monthly price make sense for stable workloads? If the workload is important, do not choose only by the lowest price. Choose the VPS that gives the best mix of performance, predictability, reliability, and operational control. ## FAQ ### What is the best VPS for DevOps teams? The best VPS for DevOps teams is one that provides modern CPU performance, NVMe storage, root access, predictable pricing, reliable uptime, Docker support, backups, firewall controls, and enough flexibility to run development, staging, CI/CD, and production workloads. ### Is VPS good for cloud-native applications? Yes. A VPS is a strong fit for many cloud-native workloads, especially Docker apps, APIs, staging environments, internal tools, CI/CD runners, self-hosted services, and early-stage SaaS platforms. ### Do DevOps teams need Kubernetes to be cloud-native? No. Kubernetes is useful for orchestration at scale, but many cloud-native teams can run Docker, Docker Compose, APIs, workers, and internal tools effectively on VPS infrastructure. ### What VPS size should I choose for DevOps workloads? A common starting point for cloud-native DevOps workloads is 4 vCPU, 8 GB RAM, NVMe SSD storage, and unmetered bandwidth. Smaller dev or staging workloads can start lower, while databases and CI/CD runners may need more CPU and RAM. ### Why does NVMe storage matter for DevOps? NVMe storage improves container startup, package installation, database I/O, build pipelines, logging, and file-heavy workloads by reducing storage latency and improving throughput. ### Is a VPS cheaper than major cloud providers? A VPS can be more cost-efficient for stable workloads because pricing is often more predictable and less fragmented than large usage-based cloud platforms. ### Does Raff support Docker workloads? Yes. Raff Linux VMs provide full root access, SSH key authentication, modern Linux distributions, NVMe storage, and Docker-ready environments for containerized workloads. ### How much does Raff Linux VPS start at? Raff Linux VPS plans start at $4.99/month, with 9 Linux distributions, deployment in under 60 seconds, full root access, and unmetered bandwidth. ## Conclusion The best VPS for cloud-native DevOps teams in 2026 is not simply the cheapest server. It is the VPS that gives teams the right balance of performance, control, reliability, and predictable cost. DevOps teams need infrastructure that supports containers, APIs, CI/CD pipelines, staging environments, internal tools, databases, automation, and production services without adding unnecessary complexity. A modern VPS with strong CPU performance, NVMe storage, root access, firewall controls, backups, and clear pricing can be the right foundation for many workloads. Large cloud platforms still have their place. But for stable workloads, small teams, early-stage SaaS products, internal systems, and practical DevOps workflows, a high-performance VPS can be faster to deploy, easier to manage, and more affordable. Raff Technologies is built for that use case: fast, simple, reliable VPS infrastructure for teams that want performance without cloud billing complexity. --- ### What Is a VPS? A Simple Guide for Beginners (2026) URL: https://rafftechnologies.com/blog/what-is-a-vps-guide-for-beginners-2026 Published: 2026-01-24T00:00:00.000Z Description: What Is a VPS? A Simple Guide for Beginners (2026) A VPS is a private cloud server environment you can use to host websites, applications, databases, development tools, and self-hosted software without buying physical hardware. For beginners, the easiest way to understand a VPS is this: it gives you your own controllable server on the internet, with dedicated resources, root access, and more freedom than shared hosting. VPS stands for Virtual Private Server. “Virtual” means the server is created using virtualization software instead of being one entire physical machine. “Private” means your server environment is isolated from other users. “Server” means it can run websites, apps, APIs, databases, and services that other people or systems can access over the internet. At Raff Technologies, we usually explain a VPS as the first serious step after shared hosting or limited managed platforms. It gives developers, founders, SMBs, and learners a practical way to run real infrastructure without needing to own a data center, buy a server, or manage physical hardware. ## The Simple Apartment Analogy The easiest VPS analogy is housing. Shared hosting is like living in a shared hostel room. It is cheap, but you share space, performance, and limits with many other people. If another website on the same server uses too many resources, your site may slow down. A VPS is like renting your own apartment inside a larger building. You still share the physical building, but your apartment has its own walls, space, lock, and resources. What your neighbor does should not directly control your environment. A dedicated server is like renting or buying the entire building. You get maximum control, but it costs more and usually gives you more infrastructure than most beginners need. For most websites, small apps, internal tools, and development environments, a VPS is the practical middle ground: more control than shared hosting, less cost and responsibility than a dedicated physical server. ## How a VPS Works A VPS works by splitting one powerful physical server into multiple isolated virtual servers. The physical server has real CPU, RAM, storage, and networking. A virtualization layer, often called a hypervisor, divides that machine into separate environments. Each environment behaves like its own server, with its own operating system, resources, users, services, files, and network configuration. When you rent a VPS, you usually get: * CPU resources * RAM * Disk storage * Public IP address * Operating system choice * Root or administrator access * Firewall options * Remote access through SSH or RDP * Ability to install software * Ability to host websites, apps, and services This is why a VPS is more flexible than shared hosting. You are not limited to a hosting control panel or a small list of supported applications. You can configure the server based on what your project actually needs. ## VPS vs Shared Hosting Shared hosting is usually the beginner’s first hosting product. It works well for simple static sites, small WordPress websites, and users who do not want to touch server administration. The limitation is control. On shared hosting, you usually cannot install system packages, change low-level server configuration, run background workers, set up custom databases freely, or control the full runtime environment. You are using a managed slice of someone else’s server setup. A VPS gives you more control because you manage the server environment yourself. | Factor | Shared Hosting | VPS | |---|---|---| | Control | Limited | High | | Root access | Usually no | Usually yes | | Performance | Shared with many users | More isolated | | Custom software | Limited | Flexible | | Best for | Simple websites | Apps, APIs, self-hosting, growing sites | | Learning value | Low | High | | Responsibility | Lower | Higher | Choose shared hosting when you want the simplest possible website setup and do not need control. Choose a VPS when you need custom software, better isolation, root access, predictable server behavior, or a place to run real applications. ## VPS vs Cloud VM The terms VPS and cloud VM are often used together, and in many practical conversations they overlap. A VPS traditionally refers to a virtual server sold as a hosting product. A cloud VM refers to a virtual machine running on cloud infrastructure. Both give you a virtual server with CPU, RAM, storage, networking, and operating system access. The difference is usually in the platform behind it. A traditional VPS may be tied to one physical server and sold as a fixed monthly package. A modern cloud VM may run on a more flexible cloud infrastructure layer, with features such as snapshots, backups, private networking, fast provisioning, and easier scaling. For beginners, the practical takeaway is simple: both give you a server you can control. The provider’s infrastructure, reliability, pricing, storage, bandwidth, support, and security features matter more than the label alone. On Raff, a [Raff VM](/products/raff-vm) gives you a cloud server experience with clear pricing, fast deployment, NVMe storage, DDoS protection, snapshots, backups, private networking, and Linux or Windows options. ## When Do You Need a VPS? You need a VPS when your project needs more control, isolation, or flexibility than shared hosting or simple app platforms provide. A VPS makes sense when you want to: * Host a website with better control * Run a backend API * Deploy a Node.js, Python, PHP, Go, or Java app * Host multiple small projects on one server * Run Docker containers * Create a staging environment * Self-host tools such as n8n, Ghost, Plausible, or Uptime Kuma * Install custom packages * Manage your own database * Learn Linux server administration * Run scripts, workers, or scheduled jobs * Create a remote development environment * Host a client demo A VPS is not only for production hosting. It is also useful for learning, testing, development, and repeatable cloud environments. If your project has moved beyond “I just need a simple page online,” a VPS is often the next reasonable step. ## When You Do Not Need a VPS Yet A VPS is powerful, but it is not always necessary. You may not need a VPS if: * You only need a basic static website * You do not want to manage updates or security * You are not comfortable with server administration yet * Your app works perfectly on a managed platform * Your traffic is tiny and shared hosting is enough * You do not need custom packages or background services The important point is honesty. A VPS gives you control, but control comes with responsibility. You need to secure the server, update packages, configure access, monitor usage, and think about backups. For many beginners, this is a good thing because it teaches real infrastructure. But for non-technical users who only want a simple brochure site, managed hosting may be enough. ## VPS Use Cases for Beginners A VPS becomes easier to understand when you connect it to real use cases. ### Website Hosting You can use a VPS to host WordPress, Ghost CMS, static sites, landing pages, company websites, portfolios, and client projects. Compared with shared hosting, a VPS gives you more control over web server configuration, performance tuning, and security settings. If you want a content-focused website, a VPS gives you room to run Nginx, configure HTTPS, manage the database, and install the tools your site needs. ### Application Hosting A VPS is useful for hosting APIs, dashboards, SaaS apps, side projects, internal tools, and backend services. Developers often choose VPS hosting because they can install their exact runtime: Node.js, Python, PHP, Ruby, Go, Java, Docker, PostgreSQL, Redis, or whatever the app requires. For app hosting, a [Raff Linux VM](/products/linux-vm) is usually the right starting point unless your workload specifically needs Windows. ### Self-Hosted Tools Self-hosting means running software on your own infrastructure instead of using a hosted SaaS version. Popular VPS-friendly self-hosted tools include: * n8n * Plausible Analytics * Ghost CMS * Uptime Kuma * Gitea * Vaultwarden * Nextcloud * Mattermost * Coolify A VPS is a natural home for these tools because it gives you control over the environment, data, and configuration. ### Development and Testing A VPS is excellent for development environments because it gives you a clean server that is separate from your laptop. You can use it for: * Staging environments * QA testing * CI/CD runners * Docker experiments * Linux learning * Client demos * Temporary workloads This is one reason many developers eventually stop relying only on local machines. A cloud VM behaves more like production than a laptop does. For more on this idea, read [Rent a Virtual Machine, Don’t Buy Hardware](/blog/rent-virtual-machine-vs-buy-hardware). ## VPS Operating Systems: Linux or Windows? Most beginners should choose Linux for a VPS, especially Ubuntu 24.04 LTS. Ubuntu is beginner-friendly, widely documented, and works well for websites, APIs, Docker, databases, and server learning. Raff’s FAQ also recommends Ubuntu 24.04 LTS for most Linux VPS users because it balances ease of use, community support, and package availability. Choose Linux when you want to run: * WordPress * Nginx or Apache * Docker * Node.js * Python * PHP * PostgreSQL * MySQL * Redis * Open-source tools * Self-hosted apps Choose Windows Server when your workload depends on: * Remote Desktop * IIS * ASP.NET Framework * Windows-only software * Microsoft SQL Server * Active Directory-connected workflows * GUI-based Windows administration If you are unsure, read [Linux vs Windows VPS: Which Server Fits Your App?](/blog/linux-vs-windows-vps-server-choice). The operating system should match the workload, not personal preference. ## What to Look for in a VPS Provider Not all VPS providers are the same. Beginners often compare only the monthly price, but price alone is not enough. Here is what matters. ### Performance Look for modern CPUs, enough RAM, and fast storage. NVMe SSD storage is especially important because disk speed affects websites, databases, package installs, builds, and application startup time. Raff’s public pricing page highlights AMD EPYC processors, DDR5 ECC memory, NVMe SSD storage, unmetered bandwidth, and fast deployment as core infrastructure points. ### Clear Pricing Pricing should be easy to understand before you deploy. You should know what the VM costs, what storage costs, what backups cost, and whether bandwidth creates surprise charges. Raff’s pricing page positions the platform around transparent pricing, and the FAQ explains that Raff uses a subscription model with monthly, 1-year, and 2-year terms. ### Bandwidth Bandwidth matters when your website or app gets traffic. Some providers include only a limited transfer amount and charge for overages. Raff’s FAQ says data transfer is unlimited and untracked, except for suspicious or abusive usage. That makes bandwidth easier to understand for beginners. ### Backups and Snapshots A VPS should not be treated as disposable if it hosts important work. You need recovery options. Backups protect data over time. Snapshots capture server state at a point in time. Both are useful, but they are not the same thing. If your VPS hosts anything important, read [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies) before you need recovery. ### Scaling Your first VPS size may not be your final size. A good provider should let you start small and grow when the workload proves it needs more resources. If you are unsure how much CPU, RAM, or storage you need, start with [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). If performance consistency matters, read [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). ### Security Features A VPS provider should make it practical to secure your server with firewall rules, private networking, SSH access, backups, and support. The provider cannot secure everything for you. But it should give you the controls you need. ## How Much Does a VPS Cost? VPS pricing depends on CPU, RAM, storage, bandwidth, operating system, backups, support, and provider infrastructure. Entry-level VPS plans are often inexpensive, but the cheapest plan is not always the best choice. A very cheap VPS may have weak performance, old storage, limited bandwidth, poor support, or oversold resources. A practical beginner approach is to choose the smallest plan that fits the workload, then monitor usage and resize when there is evidence. On Raff, the public pricing page positions cloud VPS plans from $4.99/month. Raff also publishes clear monthly pricing, supports longer subscription terms, and includes unmetered bandwidth positioning on the pricing page. For beginners, the goal is not to buy the biggest server. The goal is to buy enough server for the current workload and keep a path to grow. ## How to Get Started With Your First VPS The basic VPS setup process looks like this: 1. Choose a VPS provider. 2. Choose your operating system. 3. Select a VM size. 4. Deploy the server. 5. Connect with SSH or RDP. 6. Apply security updates. 7. Configure firewall rules. 8. Install the software you need. 9. Set up your domain and HTTPS. 10. Add backups or snapshots if the workload matters. 11. Monitor the server and resize later if needed. For most beginners on Linux, I recommend starting with Ubuntu 24.04 LTS. It is widely documented, beginner-friendly, and practical for real server work. After deploying your first Ubuntu VPS, secure it before installing your application. Follow [Secure Your Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server), then review [Cloud Firewall Rules Explained](/learn/guides/cloud-firewall-rules-explained) so you understand inbound rules, outbound rules, and least privilege. ## Common Beginner Mistakes The first mistake is opening too many ports. If something does not work, beginners sometimes allow everything through the firewall. Do not do that. Open only what the workload needs. The second mistake is using weak passwords or relying on password login when SSH keys would be safer. The third mistake is skipping updates. A fresh VPS should be updated before it runs important workloads. The fourth mistake is ignoring backups. If the server matters, recovery matters. The fifth mistake is choosing too large a server too early. Overprovisioning wastes money and hides the real workload requirements. The sixth mistake is putting every service on one VPS forever. A single VPS is fine at the beginning, but growing applications may eventually need separate app, database, worker, cache, or storage roles. If your app grows beyond one server, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture). ## VPS vs Managed Platforms Managed platforms such as Vercel, Netlify, Render, and similar services can be excellent for fast deployment. You push code, and the platform handles much of the server layer. The trade-off is control. A managed platform is usually easier at first, but you may run into limits around custom software, background workers, server configuration, data location, pricing, or runtime behavior. A VPS gives you more responsibility, but also more freedom. Choose a managed platform when you want the simplest deployment path and your app fits the platform’s rules. Choose a VPS when you want root access, custom configuration, self-hosted tools, background workers, or more control over cost and infrastructure. There is no universal winner. The best choice depends on how much control your project needs. ## What This Means for You If you are a beginner, a VPS is one of the best ways to learn real cloud infrastructure. It teaches you how servers work, how websites are hosted, how Linux administration feels, how firewalls protect services, how deployments behave, and why backups matter. Start small. Choose a simple workload. Deploy a clean server. Secure it properly. Install one useful application. Document what you did. Then grow from there. A VPS is not only a hosting product. It is a learning environment, development workspace, and production foundation in one. For your first Raff setup, start with a [Raff Linux VM](/products/linux-vm), compare plans on the [pricing page](/pricing), and use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) if you are unsure which plan fits your project. ## Final Thoughts A VPS gives beginners the right balance of control, cost, and learning value. Shared hosting is easier but limited. Dedicated servers are powerful but expensive. Managed platforms are convenient but restrictive. A VPS sits in the middle: flexible enough for real work, affordable enough to start, and practical enough to grow with your project. If you want to host websites, run apps, learn Linux, self-host tools, or build real cloud skills, a VPS is one of the most useful places to begin. Start with one server. Secure it. Run something real. Then scale only when your workload asks for it. --- ### Top 10 Developer Use Cases for Cloud Virtual Machines URL: https://rafftechnologies.com/blog/top-10-developer-use-cases-for-cloud-virtual-machines Published: 2025-08-24T00:00:00.000Z Description: Top 10 Developer Use Cases for Cloud Virtual Machines I've set up a lot of VMs. Some for production workloads, some for testing wild ideas at 11pm, some because a developer messaged us asking "what tier should I use for X?" and I wanted to actually test before answering. That hands-on context is what I'm bringing to this post. Cloud VMs aren't magic. They're just computers you rent by the month — powerful, flexible ones that don't sit under your desk. But the use cases where they genuinely make your development life better are worth spelling out concretely. Here are ten I see regularly, with specific notes on what works and what to watch out for. ## 1 — Running a Persistent Development Environment Your local machine is shared: your browser, Slack, music, and four other projects all compete for CPU and RAM with whatever you're actually trying to build. A cloud VM gives you a dedicated, distraction-free environment that's always on and always ready. The practical benefit isn't just performance — it's consistency. When you SSH into your Raff VM and run your project, it behaves exactly the same way it did yesterday, last week, and three months ago. No accidental `brew upgrade` that broke your Node version. No OS update that shuffled your Python path. A Tier 3 VM (2 vCPU / 4 GB RAM) handles most development environments comfortably — running a dev server, a database, and a background worker simultaneously without swapping. If you're working with larger codebases or running build tools like webpack or esbuild on every save, Tier 4 (4 vCPU / 8 GB RAM) is where compilation times stop being annoying. ## 2 — CI/CD Pipeline Runners Running CI jobs on your local machine ties up your machine for the duration of every build. Running them on a shared CI provider means queuing. Running them on a dedicated VM means neither. A self-hosted GitHub Actions runner or GitLab Runner on a Raff VM gives you a fixed build environment you fully control. You choose the OS, the installed tools, the Node or Python version, and the available memory. There's no "runner unavailable" wait, and there's no per- minute charge that compounds across a team running dozens of builds per day. For a small team running builds for 2-3 repositories, a Tier 3 VM handles the load well. For teams with parallel jobs or longer compilation steps (Go, Rust, Java), Tier 4 or Tier 5 gives you the vCPU headroom to run multiple jobs concurrently without builds queuing behind each other. > **Tip:** Pair your CI runner VM with a [block storage volume](/products/volumes) for > caching build artefacts and Docker layers between runs. This alone can cut build times > by 40-60% on dependency-heavy projects. ## 3 — Hosting Development and Staging Servers Sending a teammate a localhost URL is a dead end — they can't access it, and you can't leave your machine running overnight. A cloud VM running your staging environment means anyone with the IP and credentials can hit it at any time. This is especially useful for: * Sharing in-progress work with non-technical stakeholders * Running end-to-end tests against a real server (not a mocked localhost) * Keeping a stable staging environment separate from your local dev loop * Webhooks that need a real public endpoint (Stripe, GitHub, Slack integrations) A Tier 2 VM (1 vCPU / 2 GB RAM) is enough for most staging environments. You're not handling real traffic — just QA, demos, and integration tests. ## 4 — Self-Hosted Automation with n8n n8n is an open-source workflow automation tool — think Zapier, but self-hosted. It connects APIs, triggers actions on schedules, processes webhooks, and chains together workflows that would otherwise require a custom script for every integration. Running n8n on a cloud VM means your automations run 24/7 without keeping your laptop open. We've seen this use case grow significantly among developers who want automation power without the per-task pricing of SaaS tools. Raff offers a [dedicated n8n VM](/products/n8n-vm) image that gets you running in minutes. For most automation workloads, a Tier 2 or Tier 3 VM is sufficient — n8n is lightweight unless you're processing very large payloads or running dozens of concurrent workflows. > **Tip:** Enable automated backups on your n8n VM. Your workflow configurations and > credentials are stored on disk — a daily backup costs almost nothing and means you can > restore a full working environment in minutes if something goes wrong. ## 5 — Isolated Experiment Environments Testing a new database, trying a different web server configuration, running a beta version of a framework — these experiments have a way of leaving traces on your local machine that cause problems weeks later. A cloud VM gives you a genuinely isolated environment. You can install whatever you want, break whatever you want, and either fix it or destroy the VM and create a fresh one from a snapshot. The experiment stays contained. The workflow I recommend: before you start an experiment, take a snapshot of the VM. Run your experiment. If it works, keep going. If it breaks, restore the snapshot and you're back to a clean state in under a minute. Raff's [snapshot feature](/products/data-protection) is available on all tiers at no fixed cost — you pay only for the storage the snapshot uses. ## 6 — Learning Linux and Server Administration If you want to get serious about Linux, DevOps, or cloud infrastructure, you need a real server to practice on. Your local VM is fine for basics, but it doesn't replicate the experience of managing a remote machine: SSH access, firewall rules, service management, log monitoring, disk management. A Tier 1 VM ($4.99/month, 1 vCPU / 1 GB RAM) is enough for learning. It runs Ubuntu or Debian comfortably, handles all the standard tooling, and costs less than a coffee per week. The 7-day free trial means you can run through an entire learning project before spending anything. Common things developers practice on a dedicated cloud VM: * Configuring Nginx or Apache as a reverse proxy * Setting up SSL certificates with Let's Encrypt * Managing systemd services * Configuring UFW firewall rules * Setting up SSH key authentication and disabling password login * Monitoring disk usage, process lists, and system logs These skills don't transfer from reading — you need to break things and fix them on a real server. ## 7 — Running Databases Separately from Application Servers A common mistake in early-stage projects is running your database on the same VM as your application. It works until it doesn't — a memory spike from your application kills your database, or a misconfigured query runs the CPU to 100% and takes down both. Separating your database onto its own VM, connected via [private networking](/products/private-cloud-networks), gives each layer its own resources and makes both easier to scale independently. A dedicated database VM on Tier 3 or Tier 4 (depending on data size and query load) with a [block storage volume](/products/volumes) attached for the data directory is a reliable setup that mirrors how production environments are actually built. > **Note:** Use Raff's private network (VPC) to connect your application VM and database VM. > Traffic between VMs on the same private network doesn't leave the data centre — it's faster > and more secure than connecting over a public IP. ## 8 — Deploying and Testing Docker Workloads Docker is easier to learn and manage on a cloud VM than on a local machine. You get a consistent Linux environment, no macOS networking quirks, no Docker Desktop memory limits, and a public IP so you can test containers that expose ports. A Tier 3 VM comfortably runs a multi-container Docker Compose stack — a web app, a database, and a cache — with room to spare. If you're building container images as part of your workflow, the faster NVMe I/O on Raff VMs makes layer reads and writes noticeably quicker than on slower storage backends. For developers learning Docker for the first time, starting with a Raff VM removes a lot of the environment-specific friction that makes local Docker setups frustrating. ## 9 — Web Scraping and Long-Running Scripts Scripts that take hours to run — web scrapers, data processors, bulk API callers — can't live on your local machine. Your laptop goes to sleep. The VPN disconnects. You need the terminal tab to stay open. A cloud VM runs your scripts 24/7 with no interruptions. SSH in, start your script in a `tmux` or `screen` session, disconnect, and come back when it's done. The process keeps running regardless of what happens on your local machine. For scraping and data processing workloads, the right tier depends on how CPU-intensive your processing is. Pure I/O-bound scrapers run fine on Tier 2. If you're doing heavy parsing, image processing, or running headless browsers (Playwright, Puppeteer), Tier 3 or Tier 4 gives you the CPU to handle concurrent workers without throttling. ## 10 — Building Your Portfolio: Always-On Project Hosting Side projects that only run when your laptop is open aren't impressive to show people. A cloud VM that hosts your project at a real domain, with HTTPS, running 24/7 — that's something you can put on a resume and send to a hiring manager at midnight. A Tier 2 VM ($9.99/month) running Nginx, a Node.js or Python app, and a small database handles portfolio-scale traffic comfortably. Add a free SSL certificate from Let's Encrypt, point your domain, and your side project looks like a real product. This is one of the most underrated uses of a cheap cloud VM — the professional credibility of having your work actually live on the internet, not just in a GitHub repo. ## What This Means for You The pattern across all ten use cases is the same: a cloud VM gives you a computer that's always on, always available, and completely yours to configure. It removes the constraints of your local machine — power management, shared resources, environment pollution — without adding complexity. Most of the use cases above work fine on a Tier 2 or Tier 3 [Linux VM](/products/linux-vm). Start there, watch your actual CPU and RAM usage for a week, and resize up if the numbers tell you to. Raff's monthly billing means you're not locked into anything. If you're not sure which tier fits your specific use case, the [pricing page](/pricing) has the full breakdown. Or just try it — the 7-day free trial gives you enough time to run through a real workload and see how it performs. --- ### Why We Standardized on AMD EPYC for Raff Cloud Servers URL: https://rafftechnologies.com/blog/why-we-chose-amd-epyc-for-raff-s-cloud-infrastructure Published: 2025-07-18T00:00:00.000Z Description: Why We Standardized on AMD EPYC for Raff Cloud Servers ## AMD EPYC is part of how we keep Raff consistent We chose AMD EPYC for Raff Technologies because we wanted one modern CPU foundation across the platform, not a mixed hardware story that changes depending on where a VM lands. For a cloud provider, that matters more than a benchmark screenshot. The processor decision affects pricing discipline, virtualization consistency, and how predictable the platform feels once users move beyond one small server. A lot of infrastructure vendors talk about CPUs like they are decorative specs. I think that misses the real point. A cloud customer is not buying a chip in isolation. They are buying the experience that sits on top of that hardware: VM responsiveness, stable virtualization behavior, cleaner performance expectations, and a platform that does not quietly shift character between plans or hosts. That is why this was not a spec-sheet decision for us. It was a platform decision. ## We did not want mixed expectations across the product One of the things I dislike in cloud infrastructure is silent inconsistency. A platform can look simple from the outside while behaving differently depending on host generation, CPU family, or which hardware pool a workload lands on. That may be operationally normal for some providers, but it creates the wrong experience for users. A developer should not have to wonder whether one VM feels different from another because the provider made a quiet hardware trade-off in the background. Standardizing on AMD EPYC helped us avoid that kind of fragmentation. The point was not just modern server performance. The point was to give Raff a cleaner baseline across the platform so Linux VMs, storage-heavy workloads, and everyday development environments all sit on infrastructure chosen with consistency in mind. ## CPU choice changes more than raw speed A lot of people think CPU selection is mostly about “faster” versus “slower.” In a cloud platform, the decision reaches much further than that. It affects: * how well the platform behaves under virtualization, * how confidently you can define VM tiers, * how predictable the price-to-performance story stays, * and whether the infrastructure feels current or patched together. That is the real reason I think CPU choice deserves a stronger explanation than most providers give it. At Raff, we are not selling processors. We are selling cloud infrastructure that people use for web apps, databases, containers, CI pipelines, and development environments. The hardware layer should support those workloads cleanly. If it does not, the rest of the stack inherits that weakness. ## Virtualization quality mattered more than marketing value This is the part I care about most. Raff is built around virtual machines. That means the hardware decision had to make sense specifically in a virtualization-heavy environment. We were not picking a processor because it looked good in a rack spec sheet. We were choosing the foundation underneath the VM experience itself. That changes the evaluation. The real question becomes: * does this hardware support clean VM performance? * does it fit the platform we want to build? * does it help the cloud product stay understandable as it grows? For us, AMD EPYC made sense because it aligned with the kind of virtualization-first platform we wanted to build, not just the kind of marketing sentence we wanted to publish. ## The decision was also about economics This is where hardware and product philosophy meet. A lot of infrastructure choices look strong technically and weak economically. The hardware may be impressive, but if it pushes the platform toward the wrong pricing logic, the customer eventually pays for that inefficiency. We did not want that. We wanted hardware that supported a practical platform — one where the cloud product above it could stay rational, modern, and predictable as we expanded VMs, storage, networking, and protection layers. That is one reason this decision fits the rest of Raff so well. It supports a platform built around AMD EPYC, NVMe-backed infrastructure, fast provisioning, and pricing clarity instead of one where “premium hardware” becomes a separate upsell category later. Raff’s public site already reflects that broader positioning: AMD EPYC, NVMe, fast deployment, and pricing starting from $4.99/month are presented as part of one infrastructure story, not separate premium tiers. ([Raff Technologies][1]) That is the more useful frame: not “which CPU sounds most impressive?” but “which hardware lets us build the right cloud product on top?” ## Why this matters to users A user does not need to memorize EPYC model numbers for this decision to matter. The practical benefit is that the platform is built on hardware chosen for the right reasons: * a cleaner VM baseline, * a more current infrastructure layer, * stronger alignment with virtualization-heavy workloads, * and a better long-term performance story for the product above it. That is also why we do not think of AMD EPYC as a standalone bragging point. It matters together with the rest of the platform: [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [data protection](/products/data-protection), and the broader architecture choices underneath Raff. The CPU is not the product. But it absolutely shapes the product. ## Why this page exists now This is also part of why I wanted this post to be more specific than the usual “AMD is powerful” article. That angle already exists everywhere, including on our own site. The more useful explanation is not that AMD has become important in cloud. The more useful explanation is why we standardized on it for Raff specifically, and what that says about the kind of platform we are building. That distinction matters for search too. People searching for AMD EPYC in cloud infrastructure are not only asking whether the processor is good. They are often really asking what that hardware choice means for VM consistency, virtualization, pricing, and long-term platform design. That is the question I actually wanted to answer. ## What This Means for You If you are evaluating cloud infrastructure, I would look past CPU branding as a decorative spec and ask a more useful question: What does the processor choice say about the platform behind it? Does it look like the provider chose hardware that supports a coherent cloud experience, or just something easy to advertise? Does the rest of the stack make sense around that decision? Will the platform still feel predictable when you add storage, networking, backups, and more demanding workloads? That is the better question. At Raff, AMD EPYC is not there to make a product page look modern. It is part of a larger infrastructure philosophy: build on current hardware, keep the platform understandable, and let the layers above it grow in the right order. If you want to see how that shows up in practice, start with [Linux VMs](/products/linux-vm), then look at how the broader platform connects through [object storage](/products/object-storage), [private networking](/products/private-cloud-networks), and [data protection](/products/data-protection). That is where the decision makes the most sense. Not as a chip choice in isolation. As part of the kind of cloud platform we are trying to build. [1]: https://rafftechnologies.com/?utm_source=chatgpt.com "Raff Cloud Servers & VPS Hosting | From $4.99/mo" --- ### Simple and Affordable Cloud Infrastructure for Small Teams URL: https://rafftechnologies.com/blog/simple-and-affordable-cloud-power-for-sm-bs-startups-and-learners Published: 2025-04-14T00:00:00.000Z Description: Simple and Affordable Cloud Infrastructure for Small Teams ## In short Small teams usually do not need the largest cloud service catalog. They need infrastructure they can understand, deploy, secure, back up, and grow without turning every decision into a separate project. A practical starting point is often one right-sized VM, clear storage, restricted networking, backups, and a documented owner for the operating system and application. Raff focuses on those core building blocks for developers, startups, SMBs, and learners. Current plans and product availability should always be checked on the live product and pricing pages rather than copied from an old article. ## Why small teams struggle with cloud complexity The problem is rarely a lack of available services. It is the amount of attention required to choose, connect, price, and operate them. Small teams often need to: - host an application or website; - run a Windows business workload; - create a development or staging server; - self-host an internal tool; - store files or backups; - give a remote team access to one controlled environment. These workloads do not always justify a complex platform architecture on day one. ## Start with the workload, not the cloud catalog Before choosing infrastructure, answer: 1. What must run? 2. Which operating system does it require? 3. How many users or requests will it serve? 4. How much data will it store? 5. Which services need public access? 6. What must be backed up? 7. Who will maintain it? This usually leads to a simpler and more defensible first design. ## The building blocks most teams need first ### Virtual machines A VM gives the team a clear compute environment for applications, APIs, databases, development, remote work, and self-hosted software. Use Linux when the application stack supports it and Windows when the workload depends on Windows Server, RDP, or supported Windows business applications. ### Storage Separate operating-system capacity from growing application data when the workload justifies it. Plan for database growth, uploads, logs, reports, and backups instead of sizing only for installation day. ### Private networking Internal databases and services should not be exposed publicly merely because another VM needs to reach them. Private networking helps create cleaner service boundaries. ### Backups and snapshots Snapshots are useful before risky changes. Backups and restore testing are needed when the data or application matters to the business. ### Recovery access Browser console access provides another way to reach a VM when normal SSH or RDP access is broken. ## Simplicity does not remove responsibility A simpler platform still requires operational ownership. Customers running their own VMs remain responsible for: - operating-system updates; - administrator accounts; - application deployment; - firewall configuration; - database maintenance; - monitoring; - backups and restore testing; - incident response. The goal of simplicity is to reduce unnecessary friction, not to hide these responsibilities. ## When a broader platform is the better fit A hyperscale or highly managed platform may be more appropriate when the team needs: - many global regions; - a large managed-service catalog; - advanced enterprise governance; - native serverless or analytics ecosystems; - organization-wide cloud standards already built around another provider; - a fully managed application platform instead of VM administration. The best platform is the one that matches the team's current operational capability and workload—not the one with the longest feature list. ## A practical small-team architecture ```text Users | v One public application VM | +-- Application service +-- Reverse proxy +-- Monitoring | v Private database or internal service | v Backups and recovery copies ``` Start with one understandable environment. Separate services when performance, security, team ownership, or recovery requirements create a real reason. ## How Raff fits Raff provides Linux and Windows VMs, block storage, private networking, security controls, snapshots, backups, and browser console access for practical cloud workloads. Use [Linux VM](/products/linux-vm), [Windows VM](/products/windows-vm), [Volumes](/products/volumes), [Private Cloud Networks](/products/private-cloud-networks), and [Data Protection](/products/data-protection) to evaluate the building blocks your workload actually needs. Review the live [pricing page](/pricing) for current plan information. :::cta Learn More Explore practical cloud building blocks without unnecessary platform complexity. ::: ## Final takeaway Small teams should not buy complexity in anticipation of every possible future. Start with infrastructure the team can operate confidently, measure the workload, and add new layers when a clear requirement appears. Simple cloud infrastructure is not limited infrastructure. It is infrastructure whose purpose, cost, ownership, and recovery path remain understandable. --- ### We Built Raff for Developers Who Outgrow Shared Hosting URL: https://rafftechnologies.com/blog/developers-who-outgrow-shared-hosting Published: 2026-04-27T00:00:00.000Z Description: We Built Raff for Developers Who Outgrow Shared Hosting ## In short Shared hosting works well for simple websites, but developers often outgrow it when they need Docker, background workers, custom runtimes, server-level configuration, private services, staging environments, or more control over deployment. A cloud VM is the next step when the project needs an operating environment you can manage directly. That control also brings responsibility for updates, security, backups, monitoring, and application configuration. Raff was built for teams that need a practical path from limited hosting to real Linux or Windows infrastructure without starting with an oversized cloud architecture. ## The moment shared hosting stops being enough Shared hosting is designed to simplify website publishing. The provider controls most of the server and exposes a limited set of tools through a hosting panel. That model becomes restrictive when the workload requires: - Docker or custom system packages; - background jobs and queues; - application servers and APIs; - custom versions of Node.js, Python, PHP, Java, or .NET; - database configuration beyond the hosting plan; - SSH and root-level administration; - staging or test environments; - private networking between services; - predictable resource allocation. At that point, the problem is no longer the website plan. The project has become infrastructure. ## What a VM changes A cloud VM gives you an operating system you control. You decide what runs, which ports are open, how services are configured, and how deployments are performed. | Shared hosting | Cloud VM | |---|---| | Provider-managed environment | Customer-managed operating system | | Limited packages and runtimes | Install supported software directly | | Panel-based workflow | SSH, RDP, scripts, APIs, and automation | | Designed mainly for websites | Suitable for apps, APIs, tools, and services | | Provider controls server configuration | Customer controls server configuration | | Less operational responsibility | More control and more responsibility | A VM is not automatically better. It is better when the workload needs that control. ## Do not move before the project is ready Stay with shared hosting when: - the site is simple and stable; - no custom server software is required; - the hosting provider handles the needed backups and maintenance; - nobody on the team can own server administration; - the current platform meets performance and support needs. Move to a VM when the limits are blocking product or operational work—not because a VM sounds more advanced. ## Plan the first VM around one real workload A first migration should remain understandable. A common starting pattern is: ```text Users | v Nginx or another web server | v Application service | +-- Background worker +-- Local or private database +-- Monitoring | v Backups and recovery copies ``` Keep the architecture small until traffic, security, or recovery requirements justify separating roles. ## Responsibilities that move to your team With a VM, your team normally owns: - operating-system updates; - application deployment; - SSH or RDP access; - firewall configuration; - database maintenance; - monitoring and alerts; - backup design and restore testing; - incident response; - capacity planning. The infrastructure provider supplies the VM platform, but it does not automatically operate everything installed inside the server. ## Migration checklist Before leaving shared hosting: 1. Inventory domains, files, databases, email dependencies, cron jobs, and certificates. 2. Confirm the new VM supports the application stack. 3. Build a test environment before changing DNS. 4. Configure firewall rules and administrator access. 5. Copy the application and database. 6. Test uploads, forms, background jobs, and scheduled tasks. 7. Configure backups and perform a restore test. 8. Lower DNS TTL before cutover where appropriate. 9. Keep the old environment available during validation. 10. Monitor errors and resource usage after launch. ## How Raff fits Raff offers Linux and Windows VMs with root or administrator access, NVMe storage, firewall controls, private networking, snapshots, backups, and browser console access. Use [Linux VM](/products/linux-vm) for Linux applications and self-hosted tools, [Windows VM](/products/windows-vm) for supported Windows workloads, and the [Learn Hub](/learn) for practical deployment guidance. Review the live [pricing page](/pricing) after estimating the workload instead of choosing from an old hard-coded price. :::cta Explore Raff VM Move beyond shared hosting when your workload needs real control. ::: ## Final takeaway Shared hosting is a good starting point. A VM becomes the better tool when hosting limitations prevent you from operating the application correctly. The goal is not to add complexity. It is to gain the specific control the project now requires while keeping the first infrastructure design simple, recoverable, and supportable. --- ### Why More MSPs Should Offer a U.S.-Hosted Infrastructure Option URL: https://rafftechnologies.com/blog/why-more-msps-should-offer-us-hosted-infrastructure-option Published: 2026-04-22T00:00:00.000Z Description: Why More MSPs Should Offer a U.S.-Hosted Infrastructure Option ## In short A U.S.-hosted infrastructure option helps MSPs give clients a clearer answer about where workloads run, who manages them, and how remote users, applications, backups, and internal services are connected. It can improve service packaging for U.S.-focused clients, but location alone does not guarantee compliance, low latency, or security. The MSP still needs to define access, data handling, backups, recovery, monitoring, and support ownership. ## Why hosting location matters to MSP clients Clients often ask simple questions before they ask technical ones: - Where is the workload hosted? - Is the environment staying in the United States? - Who can access it? - What happens if the server fails? - Can the MSP move or recover it later? A clear U.S.-hosted option makes these conversations easier to document in proposals, onboarding records, and service descriptions. ## It creates a more repeatable service package MSPs scale more effectively when each client environment follows a known pattern. A repeatable U.S.-hosted package might define: - supported Linux or Windows VM sizes; - standard firewall rules; - private-network layout; - backup and retention options; - monitoring requirements; - administrator access; - escalation and recovery responsibilities. This reduces one-off decisions and makes support handoffs easier. ## Geography is not compliance U.S. hosting may support a client's data-location preference, but it should not be marketed as automatic compliance. Compliance depends on the full system: contracts, access controls, encryption requirements, data processing, retention, logging, incident response, and the customer's industry obligations. The MSP should use precise language such as “U.S.-hosted infrastructure” rather than making unsupported legal or certification claims. ## Private networking strengthens the design A useful MSP environment separates public and internal services. ```text Client users | v Approved public or remote-access endpoint | v Client VM environment | +-- Application server +-- Windows business server +-- Internal tools | v Private database, storage, or support service ``` Private networking can reduce public exposure, but every service still needs authentication, least privilege, and logging. ## Good MSP use cases A U.S.-hosted option is especially useful for: - Windows business applications and RDP environments; - client file and application servers; - Linux application hosting; - dedicated client infrastructure; - backup and disaster-recovery targets; - test and migration environments; - SaaS and agency client workloads; - internal tools used by U.S.-based teams. ## Questions to answer before standardizing The MSP should define: 1. Which workloads are supported? 2. Which operating systems and applications are allowed? 3. Who owns OS and application updates? 4. How are administrator accounts managed? 5. Which backup layers are included? 6. Who tests restores? 7. What is the response process when a client is locked out? 8. How are client environments separated? 9. What must remain local or vendor-hosted? ## How Raff fits Raff provides U.S.-hosted Linux and Windows VM infrastructure with firewall controls, private networking, snapshots, backups, and browser console access. The MSP remains responsible for client architecture, user access, application licensing, workload security, monitoring, backup policy, and support delivery. Review [U.S. Cloud Server](/products/us-cloud-server), [Windows VM](/products/windows-vm), [Linux VM](/products/linux-vm), [Private Cloud Networks](/products/private-cloud-networks), and [Data Protection](/products/data-protection) when designing a repeatable client service. :::cta Explore US Cloud Server Standardize U.S.-hosted client environments with clearer operational boundaries. ::: ## Final takeaway For MSPs, hosting geography is part of the service story—not the whole service. The real value comes from pairing a clear U.S.-hosted option with repeatable architecture, controlled access, documented recovery, and honest responsibility boundaries. --- ### Access Your VM Anywhere with the Raff VNC Console URL: https://rafftechnologies.com/blog/access-your-vm-anywhere-with-our-new-vnc-console Published: 2025-08-17T00:00:00.000Z Description: Access Your VM Anywhere with the Raff VNC Console ## In short The Raff VNC Console gives you browser-based access to a virtual machine when normal SSH or RDP access is unavailable. It is most valuable as a recovery path after a firewall mistake, broken network configuration, failed remote-access service, or boot problem. It should not replace secure day-to-day administration. Use SSH for normal Linux management and RDP for supported Windows workflows. Use the VNC Console when the normal network path is broken or direct console visibility is required. ## Why a second access path matters Remote administration normally depends on the guest operating system, its network stack, firewall rules, and SSH or RDP service. If one of those components is misconfigured, the same path needed to fix the server may no longer work. Browser console access provides a separate way to inspect and repair the machine. ## When to use the VNC Console ### After a firewall lockout A rule may close SSH or RDP, restrict the wrong source address, or block required traffic. The VNC Console lets you reach the operating system and correct the configuration. ### When SSH or RDP fails The service may be stopped, misconfigured, or unable to start after an update. Console access lets you inspect logs, restart services, and correct configuration files. ### During boot problems If a VM does not complete startup normally, a network connection may never become available. Console visibility can reveal boot prompts, filesystem problems, or service failures that are otherwise difficult to diagnose. ### During network reconfiguration Changes to interfaces, routes, DNS, or guest firewall settings can interrupt connectivity. A separate console path reduces the risk of turning a recoverable change into a rebuild. ## What the VNC Console does not replace The console is not a substitute for: - SSH keys and restricted Linux administration; - secure RDP or RDS design; - operating-system updates; - cloud firewall rules; - backups and snapshots; - monitoring and logging; - a tested recovery plan. It is one layer in a broader resilience strategy. ## A safer change workflow Before a risky change: 1. Confirm you can open the VNC Console. 2. Create a snapshot or backup where appropriate. 3. Record the current network or access configuration. 4. Apply one controlled change at a time. 5. Test SSH or RDP from a separate session. 6. Keep the console open until the new configuration is confirmed. This is especially useful when changing firewall rules, SSH settings, RDP policies, network interfaces, or authentication configuration. ## Shared responsibility still applies Raff provides the browser console and the underlying VM infrastructure. Customers remain responsible for guest operating-system configuration, user accounts, firewall rules inside the VM, SSH or RDP security, application access, and recovery decisions. A console can help you repair a configuration problem, but it cannot replace good access control or a backup strategy. ## How Raff fits The VNC Console is available as part of the Raff VM management experience for supported workloads. Pair it with [Security](/products/security), [Data Protection](/products/data-protection), [Linux VM](/products/linux-vm), or [Windows VM](/products/windows-vm) depending on the environment you operate. :::cta Deploy Your Server Launch a VM with browser-based recovery access available when needed. ::: ## Final takeaway The best recovery tool is the one that exists before the lockout happens. Use the Raff VNC Console as an independent access path, keep regular administration on secure protocols, and protect important workloads with tested backups and rollback procedures. --- ### 7 Mistakes Developers Make When Choosing a Cloud VPS URL: https://rafftechnologies.com/blog/cloud-vps-mistakes-2026 Published: 2026-03-19T00:00:00.000Z Description: 7 Mistakes Developers Make When Choosing a Cloud VPS ## In short The most expensive VPS mistakes usually come from choosing only by headline price and ignoring what happens after deployment. Developers should evaluate sizing, storage, bandwidth policy, resize paths, backups, security controls, support boundaries, and migration risk before committing. A VPS is not just CPU, RAM, and disk. It becomes part of the way your team deploys, recovers, scales, and operates. ## Mistake 1: choosing by price alone A low monthly price can hide important trade-offs: limited storage, capped transfer, paid backups, rigid upgrades, or weak recovery options. Compare the complete operating cost, not one number. Include storage growth, backup retention, support time, migration effort, and the impact of downtime. Use the live [Raff pricing page](/pricing) for current plans rather than relying on figures embedded in an older article. ## Mistake 2: sizing only for today's workload A server that works during launch may struggle after adding background jobs, more users, larger databases, monitoring, or staging services. Start lean, but confirm the provider gives you a practical resize path. Monitor CPU, memory, disk latency, and storage growth so scaling decisions are based on evidence. ## Mistake 3: ignoring storage performance Slow storage can make package installation, container builds, database queries, backups, and deployments feel inconsistent even when CPU usage looks normal. Ask what storage technology is used, how much capacity is included, and whether extra block storage can be added without rebuilding the VM. ## Mistake 4: treating bandwidth as a footnote Applications that serve files, APIs, media, backups, or synchronization traffic can grow faster than expected. Review whether bandwidth is metered, what fair-use rules apply, and whether traffic growth could create unexpected cost or throttling. Bandwidth policy should be understood before a successful launch changes usage patterns. ## Mistake 5: assuming a snapshot is a backup strategy Snapshots are useful before upgrades, configuration changes, and migrations. They are not automatically a complete backup plan. A production workload may also need database-aware backups, file-level recovery, off-server copies, retention rules, and restore testing. A backup process is only proven when the team can restore the application and its data successfully. ## Mistake 6: exposing services before designing access New servers are often deployed with broad SSH, RDP, database, or administration access because it is convenient during setup. Instead: - expose only required ports; - use named administrator accounts; - restrict source networks where practical; - keep databases and internal services private; - separate daily users from privileged accounts; - patch the OS and applications deliberately. Infrastructure controls and customer configuration are both required. A provider cannot protect a weak password, leaked key, outdated package, or public database inside a customer-managed VM. ## Mistake 7: choosing a platform with no clear recovery or support boundary Before deploying, know who owns: - operating-system updates; - application configuration; - database maintenance; - backups and restores; - firewall rules; - monitoring; - incident response; - migration and rollback. A platform may provide infrastructure support without managing everything installed inside the VM. This boundary should be clear before a production issue occurs. ## A practical VPS evaluation table | Decision area | Question to ask | |---|---| | Compute | Can the VM be resized when the workload changes? | | Storage | Is storage fast enough and expandable? | | Network | Is bandwidth predictable and are private networks available? | | Security | Can public access be restricted easily? | | Recovery | Are snapshots, backups, and restore paths available? | | Operations | Is browser console or recovery access available? | | Support | Who handles the platform, OS, application, and database? | | Migration | Can the workload be moved without rebuilding everything? | ## How Raff fits Raff provides Linux and Windows VMs with NVMe storage, cloud firewall controls, private networking, snapshots, backups, and browser console access. Customers remain responsible for the operating system, applications, identities, databases, workload security, and recovery acceptance. Review [Linux VM](/products/linux-vm), [Windows VM](/products/windows-vm), [Volumes](/products/volumes), [Security](/products/security), and [Data Protection](/products/data-protection) when comparing the complete environment. :::cta View Pricing Compare current VM options after defining your real workload needs. ::: ## Final checklist Before choosing a VPS, confirm: 1. The application and operating system are supported. 2. The starting size is based on a real workload. 3. Storage and bandwidth policies are understood. 4. Resize and migration paths are documented. 5. Public ports are minimized. 6. Backups and restores have an owner. 7. Support responsibilities are clear. The best VPS is not the one that looks cheapest on day one. It is the one that remains practical when the workload becomes real. --- ### What to Host on a U.S.-Based Cloud Server URL: https://rafftechnologies.com/blog/what-to-host-us-based-cloud-server-2026 Published: 2026-03-18T00:00:00.000Z Description: What to Host on a U.S.-Based Cloud Server ## In short A U.S.-based cloud server is a strong fit when most users, customers, integrations, or operators are in North America. Common workloads include web applications, APIs, background workers, internal tools, self-hosted software, databases placed near the application, and Windows business workloads. Location alone does not guarantee speed, compliance, or reliability. The right choice also depends on user geography, application architecture, network paths, data requirements, backups, and operational ownership. Raff provides U.S.-hosted infrastructure for teams that need practical Linux or Windows compute. Customers remain responsible for application design, data classification, security configuration, and legal or compliance decisions. ## Workloads that usually benefit from U.S. hosting ### Customer-facing applications Web applications, SaaS dashboards, portals, and e-commerce backends benefit when the origin infrastructure is close to the users who make most requests. A CDN may distribute static content globally, but application logic and database calls still depend on the origin architecture. ### APIs and integration services Place APIs near the systems and users they communicate with most frequently. U.S.-based hosting can be useful for applications integrated with U.S.-based payment, communications, developer, and business services. Do not assume geography eliminates timeout or reliability problems. Use retries, idempotency, queueing, and monitoring for important integrations. ### Databases near the application The application and its primary database should usually be in the same location or private network unless a deliberate distributed design requires otherwise. Avoid exposing database ports publicly. Use private networking, restricted accounts, application-aware backups, and tested restores. ### Background workers and scheduled jobs Queue workers, data imports, reporting jobs, webhooks, automation tasks, and scheduled scripts are good VM workloads when they need a stable environment and do not justify a larger platform. Separate these jobs from the public application when resource spikes or security boundaries make that useful. ### Internal tools Monitoring dashboards, admin tools, CI runners, documentation services, and private business applications can fit U.S.-based infrastructure when the team primarily operates in North America. Restrict internal tools by identity and network policy instead of relying on obscure URLs. ### Windows business workloads Remote Desktop, supported accounting or ERP applications, shared business files, legacy Windows software, and office-server replacement can fit a U.S.-hosted Windows VM. Confirm software compatibility, Microsoft and application licensing, RDS requirements, printers, integrations, and backup responsibilities before migration. ## Workloads that need more careful evaluation ### Global applications A single U.S. server may be sufficient for an early product, but globally distributed users can experience different latency. Measure real user performance before introducing multi-region complexity. ### Regulated or sensitive data U.S. hosting does not automatically make a workload compliant. Data location is only one part of privacy, contractual, industry, and regulatory obligations. ### GPU-intensive workloads Do not assume a general-purpose cloud VM includes GPU capacity. Training, rendering, and other accelerator-dependent workloads require infrastructure designed and explicitly offered for that purpose. ### High-availability systems One VM is one failure domain. Applications with strict uptime requirements need redundancy, health checks, database recovery, and a tested failover design. ## A practical starter architecture ```text Users | v Public application endpoint | v Linux or Windows VM | +-- Application +-- Background services +-- Monitoring agent | v Private database or internal service | v Backups and recovery copies ``` Start with the simplest architecture that satisfies the current workload, then separate roles when performance, security, or recovery requirements justify it. ## Security and recovery basics A production U.S.-hosted server should include: - only required public ports; - named administrator accounts; - current operating-system and application patches; - private connectivity for internal services; - database and file backups; - snapshots before risky changes; - monitoring for CPU, memory, storage, errors, and failed logins; - a tested restore or rebuild process. Infrastructure protection and customer configuration work together. The provider cannot secure an outdated application, leaked credential, or publicly exposed database inside a customer-managed VM. ## How Raff fits Raff supports U.S.-hosted Linux and Windows VM workloads with NVMe storage, firewall controls, private networking, snapshots, backups, and browser console access. Use [Linux VM](/products/linux-vm) for Linux applications and infrastructure, [Windows VM](/products/windows-vm) for supported Windows workloads, [Private Cloud Networks](/products/private-cloud-networks) for internal traffic, and [Data Protection](/products/data-protection) for recovery planning. Review the live [pricing page](/pricing) for current plans rather than relying on a fixed figure in an article. :::cta Explore US Cloud Server Place North American workloads on practical U.S.-hosted infrastructure. ::: ## Placement checklist Before choosing a U.S.-based server, confirm: 1. Where are the majority of users and operators? 2. Where are the application's key integrations? 3. Can the application and database stay close together? 4. Does the workload need local hardware or another region? 5. What data-location obligations apply? 6. What happens if the VM or internet path becomes unavailable? 7. Who owns updates, security, backups, and recovery? The right location is the one that best matches the workload—not the one with the strongest marketing label. --- ### MCP Server Security: Run AI Agents Without Leaking Secrets URL: https://rafftechnologies.com/blog/mcp-server-security-2026 Published: 2026-03-23T00:00:00.000Z Description: MCP Server Security: Run AI Agents Without Leaking Secrets ## In short An MCP server should be treated like a privileged production backend, not a harmless AI add-on. It can connect models to files, databases, APIs, internal tools, and credentials, so a weak design can turn prompt injection or excessive permissions into a real infrastructure incident. The safest architecture keeps secrets outside model context, exposes narrowly scoped tools, validates every action, isolates the MCP service from unrelated workloads, and records sensitive operations for review. Raff can provide the Linux VM, firewall controls, private networking, backups, and recovery access underneath this architecture. The customer remains responsible for the MCP implementation, tool permissions, application security, secrets, logging, and incident response. ## Why MCP servers create a different risk Traditional APIs expose predetermined endpoints. MCP servers allow an AI system to discover and call tools based on user input and model reasoning. That creates three linked risks: 1. **Prompt injection:** untrusted content influences which tool the model calls. 2. **Over-privileged tools:** one tool can read, write, delete, or administer more than the task requires. 3. **Secret exposure:** credentials appear in prompts, logs, tool output, files, or environment dumps. A secure MCP design assumes the model can make a bad decision and limits the damage that decision can cause. ## Keep secrets outside model context Do not place API keys, database passwords, private tokens, or administrator credentials in prompts or tool descriptions. Use a backend execution layer that retrieves credentials only when an approved tool action is executed. The model should request an operation such as `create_support_ticket` or `read_invoice_status`, not receive the raw credential used to perform it. Also review logs. Debug logging can unintentionally capture headers, environment variables, tool arguments, user data, and full third-party responses. ## Use narrow tools instead of broad access Avoid tools such as: - `run_any_sql` - `execute_shell_command` - `read_any_file` - `call_any_api` - `manage_all_users` Prefer task-specific tools such as: - `get_customer_by_id` - `create_draft_invoice` - `read_deployment_status` - `restart_staging_service` - `search_approved_documents` Each tool should define allowed inputs, output limits, authorization rules, timeouts, and failure behavior. ## Put a policy layer between the model and external systems A practical architecture is: ```text User request | v AI model | v MCP server | v Policy and validation layer | +-- Authentication +-- Authorization +-- Input validation +-- Rate limits +-- Approval rules +-- Audit logging | v Approved API, database, or internal service ``` The model proposes an action. The policy layer decides whether that action is allowed. High-impact actions such as deleting data, changing permissions, sending payments, publishing content, or accessing sensitive records should require additional checks or human approval. ## Isolate the MCP service Run production MCP services separately from unrelated applications and development environments. A stronger deployment normally includes: - a dedicated VM or isolated service boundary; - no unnecessary public ports; - restricted outbound access; - private connectivity to internal services; - separate development and production credentials; - non-administrator service accounts; - independent logs and monitoring. Private networking reduces public exposure, but it does not replace authentication or authorization. A private service can still be abused by a compromised internal workload. ## Defend against prompt injection Prompt injection cannot be solved with one system prompt. Reduce risk by combining: - strict tool schemas; - untrusted-content labeling; - allowlisted actions; - output validation; - data-access boundaries; - human confirmation for destructive operations; - separate read and write tools; - monitoring for unusual tool sequences. Never let content retrieved from a webpage, email, uploaded document, or database record automatically redefine security policy. ## Logging without leaking data Audit logs should answer: - who initiated the request; - which tool was called; - what resource was targeted; - whether the action was approved; - when it occurred; - whether it succeeded; - which policy rule applied. Logs should not store raw secrets, unnecessary personal data, full authentication headers, or unrestricted model context. ## Backups and recovery still matter Security controls reduce risk but do not eliminate mistakes. An agent may still modify the wrong record, trigger a faulty integration, or expose an application bug. Plan: - database backups; - versioned configuration; - snapshots before major changes; - rollback procedures; - credential rotation; - a method to disable tools quickly; - restore tests for critical systems. ## How Raff fits Raff Linux VMs can host MCP services with root access, NVMe storage, firewall controls, private networking, snapshots, backups, and browser console access. Raff provides the infrastructure layer. Customers remain responsible for application code, model behavior, MCP tool design, secrets, permissions, monitoring, and compliance decisions. Review [Linux VM](/products/linux-vm), [Private Cloud Networks](/products/private-cloud-networks), [Security](/products/security), and [Data Protection](/products/data-protection) when designing the environment. :::cta Explore Security Build stronger boundaries around agents, tools, secrets, and services. ::: ## Production checklist Before launching an MCP server, confirm: - secrets never enter prompts or model-visible output; - tools are narrowly scoped; - destructive actions require stronger approval; - development and production are separated; - public exposure is minimized; - outbound network access is restricted; - logs exclude sensitive values; - tool usage is auditable; - credentials can be rotated quickly; - backups and rollback have been tested. The central principle is simple: the model should never have more authority than the task requires. --- ### Why Self-Hosted CI Runners Still Make Sense for Small Teams URL: https://rafftechnologies.com/blog/self-hosted-ci-runners-2026 Published: 2026-03-23T00:00:00.000Z Description: Why Self-Hosted CI Runners Still Make Sense for Small Teams ## In short Self-hosted CI runners still make sense for small teams when builds are frequent, resource-intensive, dependent on custom tooling, or slowed down by repeated downloads and cold caches. The benefit is control: you choose the operating system, CPU and memory, installed packages, network access, cache strategy, and runner lifecycle. The trade-off is responsibility. Your team must secure, patch, monitor, clean, and replace the runner instead of delegating those tasks to a managed CI provider. A good first design is usually one dedicated Linux VM for CI, isolated from production, with restricted repository access and no inbound public services unless they are truly required. ## What a self-hosted CI runner actually changes A managed runner is temporary infrastructure supplied by the CI platform. A self-hosted runner is infrastructure that your team operates and registers with the CI system. ```text Source repository | v CI platform and job queue | v Dedicated self-hosted runner | +-- Build and test +-- Reuse approved caches +-- Build container images +-- Publish artifacts +-- Deploy through restricted credentials ``` The CI platform still handles workflow definitions, job scheduling, and repository integration. Your runner handles the actual execution. ## When self-hosting creates real value ### Frequent builds A persistent runner can reuse package, compiler, and container caches between jobs. That can reduce repeated network downloads and setup work. Caching should remain controlled. A cache can become stale, consume the disk, or allow one workflow to influence another. Define cache keys, expiration rules, disk thresholds, and cleanup jobs instead of treating persistence as automatically beneficial. ### Custom system dependencies Some pipelines need specific SDKs, browsers, database clients, kernel features, internal certificates, or licensed build tools. A self-hosted runner lets the team create a known environment rather than reinstalling everything for every job. Document the runner build process in a script, image, or configuration-management repository. A manually configured runner that nobody can reproduce becomes operational debt. ### Predictable resources Teams with long compiles, large test suites, container builds, or parallel jobs may benefit from assigning a known amount of CPU, memory, and NVMe-backed storage to CI. This does not guarantee that every build will be faster. Performance still depends on the workflow, cache quality, concurrency, dependency servers, and test design. Measure queue time and job duration before and after moving workloads. ### Access to private services A runner may need to test against an internal database, package registry, staging API, or private artifact store. Private networking can reduce the need to expose those services publicly. Keep access narrow. A runner should reach only the systems required for its jobs, not every production service in the environment. ## When managed runners remain the better choice Self-hosting is not automatically cheaper or simpler. Managed runners are usually a better fit when: - build volume is low; - workflows are short and standard; - the team does not want to manage another server; - jobs process untrusted pull requests from public contributors; - rapid elasticity matters more than persistent caching; - the organization lacks an owner for patching, monitoring, and incident response. The correct comparison includes engineering time, security work, maintenance, failed jobs, replacement procedures, and idle capacity—not only the server price. ## The security boundary matters more than the hardware CI runners handle valuable assets: source code, repository tokens, deployment credentials, signing keys, package-registry access, and cloud secrets. Treat the runner as a privileged automation system. ### Do not mix CI and production workloads A production application and its CI runner should not share one VM. Build scripts execute code from repositories and dependencies. A compromised workflow should not automatically gain access to production processes, files, or credentials. ### Restrict which repositories can use the runner Register runners at the narrowest practical scope. Separate trusted production repositories from experiments and public projects. Review who can edit workflow files because workflow access can become infrastructure access. ### Minimize secrets Provide each workflow only the credentials it needs. Prefer short-lived credentials and deployment-specific service accounts. Avoid placing broad administrator keys in global runner configuration, shell history, cached directories, or reusable images. ### Be careful with untrusted pull requests Running code from unknown contributors on a persistent runner can expose files, credentials, caches, and network access. Public projects should use isolated or disposable execution patterns unless the team has designed a strong trust boundary. ### Control outbound access Inbound firewall rules are only part of the picture. Restrict the services the runner can reach, especially production databases, control panels, internal administration endpoints, and metadata services. ## A practical small-team architecture A sensible first deployment can be simple: ```text GitHub or GitLab | v Dedicated Linux runner VM | +-- No public application ports +-- Repository-specific runner registration +-- Minimal deployment credentials +-- Separate build workspace +-- Disk and resource monitoring +-- Controlled private access where needed | v Artifact registry or staging environment ``` Do not start with an autoscaling runner fleet unless build demand justifies it. One well-documented runner gives the team real usage data before it adds orchestration complexity. ## How to size the first runner Start from the heaviest representative job, not from employee count. | Workload characteristic | Resource most likely to matter | |---|---| | Compiling large projects | CPU and memory | | Running many tests in parallel | CPU and memory | | Building container images | CPU, memory, and storage I/O | | Large dependency caches | Storage capacity | | Browser or end-to-end tests | Memory and CPU | | Multiple concurrent jobs | CPU, memory, and runner concurrency | | Large artifacts | Storage and network throughput | Run representative pipelines, then review CPU peaks, memory pressure, free disk, cache growth, job duration, and queue time. Increase resources only after identifying the actual bottleneck. ## Maintenance tasks teams often forget Assign an owner for: - operating-system and runner updates; - runner-token rotation; - disk and cache cleanup; - failed service alerts; - capacity monitoring; - dependency and base-image updates; - backup decisions for configuration files; - replacement and re-registration procedures; - incident response when a workflow is compromised. Build output should normally be reproducible from source, so backing up a runner's entire workspace may be unnecessary. Back up the configuration, scripts, certificates, and any unique state that cannot be recreated safely. ## How Raff fits Raff Linux VMs provide full root access on AMD EPYC infrastructure with NVMe storage. Teams can combine a dedicated runner with cloud firewall controls, private networking, snapshots, backups, and browser console access. Raff supplies the infrastructure layer. The customer remains responsible for runner registration, CI platform permissions, operating-system security, workflow trust, secrets, monitoring, and cleanup. Review [Raff Linux VM](/products/linux-vm) for the compute layer, [Private Cloud Networks](/products/private-cloud-networks) for internal connectivity, [Security](/products/security) for infrastructure controls, and [Data Protection](/products/data-protection) for recovery planning. Use the live [pricing page](/pricing) when comparing current plans rather than relying on a hard-coded figure in an article. :::cta Deploy Your Server Build a dedicated CI runner without mixing builds and production. ::: ## Final decision checklist A self-hosted runner is worth testing when you can answer these questions: 1. Which workflows will use it? 2. Are those repositories trusted? 3. Which secrets and private services does it need? 4. Who will patch and monitor the runner? 5. How will caches and workspaces be cleaned? 6. Can the runner be rebuilt from documented configuration? 7. What measurements will determine whether it improved the pipeline? Self-hosting works best when it solves a measured CI problem and has a clear operational owner. Without those two conditions, a managed runner is usually the safer default. --- ### Looking for a Windows VPS? What to Check Before You Deploy URL: https://rafftechnologies.com/blog/looking-for-a-windows-vps-what-to-check Published: 2025-07-17T00:00:00.000Z Description: Looking for a Windows VPS? What to Check Before You Deploy ## In short A Windows VPS is a practical fit when your workload depends on Windows software, Remote Desktop, .NET, business applications, scheduled tasks, or an always-available Windows environment. The right provider should make the infrastructure clear: available Windows versions, current pricing, licensing terms, VM sizing, storage, remote-access options, backup choices, and support responsibilities. These details can change, so this article no longer publishes fixed license fees, unsupported BYOL promises, exact provisioning times, or hard-coded operating-system availability. Before deploying, confirm the current options on the [Windows VM product page](/products/windows-vm) and [Raff pricing page](/pricing). ## What a Windows VPS is A Windows VPS is a cloud virtual machine running an available Windows Server image. It gives the customer administrator-level control and is commonly accessed through Remote Desktop Protocol, with browser-based console access available as a recovery path on Raff. Typical use cases include: * Windows-only business applications * Remote work environments * .NET development and testing * Accounting, ERP, inventory, and legacy software * Browser automation and scheduled Windows tasks * Application demonstrations and QA environments A Windows VPS provides the infrastructure. Customers and their software vendors remain responsible for application compatibility, application licensing, user configuration, database administration, and workload-specific testing. ## Check software compatibility first Do not choose a Windows Server version only because it is the newest option shown in a control panel. Confirm: * which Windows Server releases the application vendor supports * whether the application requires a specific .NET version * whether the database should run on the same VM or separately * whether USB devices, scanners, printers, smart cards, or serial equipment are involved * whether the software supports Remote Desktop sessions * whether multiple users require Remote Desktop Services and separate licensing Legacy applications can behave differently on newer server releases. Test the complete workflow before moving production users. ## Verify licensing from the current product information Windows licensing is not a detail that should be frozen inside an old blog post. The available licensing model, included editions, pricing, and eligibility rules may change. Before purchasing, verify: * whether the Windows license is included or billed separately * which editions and versions are currently available * whether your planned use requires additional Microsoft licenses * whether multi-user access requires RDS CALs * whether a bring-your-own-license arrangement is explicitly supported for your agreement Do not assume that a desktop Windows license, Microsoft 365 subscription, or existing server key can automatically be used in a hosted environment. Licensing questions should be checked against the current Raff offer and the customer's Microsoft licensing position. ## Size the VM for the workload, not only the user count Windows Server has its own memory and storage requirements before the business application starts consuming resources. Sizing should consider: * number of concurrent users * application memory usage * database size and query activity * background services * Windows Update and antivirus overhead * file storage growth * reporting and batch jobs * peak CPU usage during login or processing periods Start from a measured baseline where possible. A five-user accounting environment and a five-user engineering application can require very different resources. ## Plan RDP access carefully RDP is the normal day-to-day access method for many Windows workloads, but it should not be exposed carelessly. Use strong administrator credentials, restrict access where possible, keep Windows updated, review failed login activity, and avoid giving every user broad administrative privileges. Where the business requires multiple simultaneous user sessions, plan the correct Remote Desktop Services roles and licensing rather than relying on the two administrative sessions intended for server management. The Raff browser console should be treated as a recovery path when RDP is unavailable, not as a replacement for a properly configured remote-access model. ## Separate cloud workloads from local hardware dependencies A Windows VPS works best for software and data that can operate over a network connection. Some workflows may still need a local or hybrid component, including: * warehouse scanners and label printers * local scales or serial devices * specialized USB license keys * high-end GPU applications * latency-sensitive plant equipment * software that must continue during an internet outage Test these dependencies before migration. A hybrid design is often safer than forcing every physical workflow into the cloud. ## Protect the environment before it becomes critical A production Windows VPS should have a documented protection plan covering: * application-consistent backups where required * database backups * file and document backups * snapshots before risky changes * off-server copies where appropriate * retention periods * restore testing * administrator access during recovery Snapshots are useful, but they should not automatically be treated as the only backup strategy. The recovery process matters more than the presence of a backup button. ## Understand the support boundary Raff provides the cloud infrastructure and platform controls. The customer, software vendor, or MSP normally owns: * application installation and configuration * application and Microsoft licensing decisions * database maintenance * user permissions * RDS configuration * device and printer testing * application-level security * migration planning and validation * backup contents and restore acceptance Clear ownership prevents a migration from stalling when an application-specific problem appears. ## What to confirm before ordering Use this checklist: 1. Confirm the application supports a currently available Windows Server image. 2. Verify current Windows pricing and licensing terms. 3. Estimate concurrent users, RAM, CPU, storage, and database growth. 4. Identify printers, scanners, USB devices, and local integrations. 5. Decide whether the database stays on the same VM. 6. Plan RDP and RDS licensing correctly. 7. Define backups and test restoration. 8. Confirm which tasks Raff, your MSP, and the software vendor will own. 9. Test the full workflow before the final cutover. ## What this means for you A good Windows VPS decision is not based on one advertised price or one server specification. It depends on compatibility, licensing, sizing, access, data protection, and whether the complete business workflow has been tested. Review the current [Windows VM options](/products/windows-vm), then speak with the team before moving a business-critical or multi-user workload. :::cta Talk to Windows Engineer Confirm compatibility, sizing, and current Windows VM options. ::: --- ### Is Raff Secure? How Cloud Security Responsibility Works URL: https://rafftechnologies.com/blog/is-raff-secure-cloud-security-shared-responsibility Published: 2025-05-20T00:00:00.000Z Description: Is Raff Secure? How Cloud Security Responsibility Works ## In short Raff provides the infrastructure controls needed to build a safer cloud environment, including network-level DDoS protection, firewall controls, private networking options, snapshots, backups, and recovery access through the web console. But no cloud provider can secure everything inside a customer-managed virtual machine automatically. Security is a shared responsibility. Raff protects and operates the cloud platform; customers remain responsible for the operating system, user accounts, SSH or RDP access, application configuration, software updates, secrets, and backup recovery planning. This distinction matters because vague security claims create the wrong expectations. A secure cloud setup is not created by one checkbox or one provider feature. It comes from combining infrastructure protection with disciplined server administration. ## What Raff protects at the infrastructure layer Raff operates the physical and cloud infrastructure underneath your virtual machines. The platform provides controls that help reduce common infrastructure risks and give customers practical ways to protect and recover their workloads. ### Network-level DDoS protection Raff includes network-level protection designed to help absorb and filter malicious traffic aimed at disrupting services. DDoS protection reduces infrastructure-level exposure, but it does not replace application security, rate limiting, authentication, or monitoring inside your workload. ### Cloud firewall controls Firewall rules help customers limit which ports and services are reachable from the public internet. A strong starting configuration normally exposes only the services the workload needs, such as HTTPS and carefully restricted administrative access. A firewall cannot protect an application that is misconfigured or running vulnerable software. It should be treated as one layer in a broader security model. ### Private networking Private cloud networks allow supported Raff resources to communicate without exposing every internal service publicly. This is useful for separating application servers, databases, internal tools, and management services. A database, Redis instance, or internal API generally should not be public merely because another server needs to reach it. Private networking gives teams a cleaner way to design those boundaries. ### Snapshots, backups, and recovery paths Security also includes recovery. Accidental deletion, failed updates, ransomware, application bugs, and administrator mistakes can be as damaging as external attacks. Snapshots and backups help create recovery points, while the browser-based console provides another access path when SSH or RDP is unavailable. These tools reduce recovery risk, but customers should still define retention periods and test restores instead of assuming that a successful backup automatically guarantees a successful recovery. ## What customers are responsible for A Raff VM gives you administrative control. That control also creates responsibility. Customers should manage: * operating-system updates and security patches * SSH keys, passwords, RDP access, and administrator accounts * application authentication and authorization * secrets, API keys, database credentials, and environment variables * firewall rules inside the guest operating system where applicable * services and ports exposed by the application * database permissions and data-access policies * malware prevention and application-level monitoring * backup schedules, retention, and restore testing Raff does not automatically inspect or securely configure every application installed inside a customer VM. A server can be deployed on protected infrastructure and still become vulnerable through an outdated package, weak password, exposed database port, leaked API key, or overly permissive account. ## Secure connections depend on the protocol you use The previous version of this article incorrectly suggested that every connection to a Raff VM used universal end-to-end SSL encryption. That was too broad. Connection security depends on the service and protocol being used. Linux administrators should use SSH with strong keys and restricted access. Windows administrators should secure RDP access and use appropriate account controls. Web applications should use HTTPS with correctly configured TLS certificates. Private services should stay on private networks or localhost whenever possible. The important rule is simple: do not expose an unencrypted or unnecessary service to the public internet merely because the VM has a public IP address. ## What we do not claim without verification Security documentation should be precise. Raff does not use this article to make universal claims about disk encryption, end-to-end encryption for every protocol, compliance certifications, or application-level protection unless those capabilities are explicitly documented for the relevant product. That is intentional. Customers should be able to distinguish between a verified platform feature, a configuration they must implement, and a security requirement that may need additional products or professional review. ## A practical Raff VM security baseline For a new Linux or Windows VM, use this baseline: 1. Create only the administrator accounts you need. 2. Use SSH keys for Linux and strong, restricted administrator access for Windows. 3. Apply operating-system and application updates. 4. Close every public port that the workload does not require. 5. Place databases and internal services behind private networking where possible. 6. Keep secrets outside source code and public repositories. 7. Create backups before the workload becomes business-critical. 8. Test at least one restore before relying on the backup process. 9. Monitor login attempts, service errors, storage usage, and unusual activity. 10. Remove unused accounts, packages, services, and credentials. This approach is more useful than assuming a cloud provider can make a customer-managed server secure without customer participation. ## Security is a system, not a marketing claim The safest way to evaluate a cloud provider is to ask specific questions: * Which infrastructure protections are included? * Which ports and networks can I control? * How do I recover from a bad configuration or failed update? * Which security tasks remain my responsibility? * Are product claims documented clearly enough to verify? Raff's goal is to provide practical infrastructure controls without pretending that infrastructure alone solves every security problem. Use [Raff Security](/products/security) to review platform protections, [Private Cloud Networks](/products/private-cloud-networks) to separate internal services, and [Data Protection](/products/data-protection) to plan snapshots, backups, and recovery. :::cta Explore Security Review the controls available for protecting your Raff workloads. ::: --- ### Why We Keep Support Human in a Cloud-First World URL: https://rafftechnologies.com/blog/real-human-support-in-a-digital-world-why-raff-puts-developers-first Published: 2025-08-17T00:00:00.000Z Description: Why We Keep Support Human in a Cloud-First World Cloud infrastructure is technical, but the support experience should not feel distant, scripted, or impossible to reach. At Raff, we see support as part of the product itself. When a developer is launching a VM, moving a workload, checking a network issue, restoring data, or choosing the right infrastructure setup, the quality of support directly affects how fast they can keep moving. That is why we keep support human, close to the product, and focused on context instead of generic replies. Automation helps with speed. Documentation helps with repeatable answers. But when infrastructure decisions affect production workloads, people still need clear help from people who understand the system. ## Support is part of the infrastructure experience Most cloud platforms talk about support as if it sits outside the product. You build on the platform first. Then, if something goes wrong, you open a ticket. I do not think infrastructure works that way. For developers, startups, small teams, agencies, and MSPs, support is not a separate department. It is part of the real experience of using the platform. If a user cannot understand why a VM is unreachable, if a backup workflow feels unclear, if an app is slow and they do not know whether the problem is CPU, disk, network, or application code, the product experience is already affected. That is not just a support issue. It is a product issue. Cloud infrastructure is only useful when people can actually operate it with confidence. That confidence comes from a few things: - clear products - predictable pricing - useful documentation - stable infrastructure - fast provisioning - visibility into what is happening - support that helps users understand the situation, not just close the ticket That last part matters more than people admit. ## Automation is useful, but it cannot replace understanding We use automation. Any serious infrastructure platform should. Automation helps with: - faster VM provisioning - repeatable server actions - safer reset flows - billing workflows - monitoring - alerts - internal operations - customer-facing product actions Automation is not the problem. The problem starts when companies use automation to avoid understanding the customer's actual issue. A bot can route a ticket. A help article can explain a common setup step. A status page can confirm whether a platform-level incident is happening. But many infrastructure questions are not that simple. A developer may ask: ```text Why is my server slow? ``` But the real question might be: ```text Did I choose the wrong VM size? Is my app using too much memory? Is the database on the same server becoming the bottleneck? Is this a disk issue? Is the problem network-related? Should I scale vertically or split the workload? ``` Those are different questions. They require context. That is where human support still matters. ## Why many cloud support experiences feel broken A lot of cloud support feels frustrating because it is designed around internal scale before customer momentum. Large platforms often use: - layered ticket queues - scripted replies - generic troubleshooting flows - separate sales, billing, and technical support paths - support teams far away from product decisions - documentation loops instead of direct help That model may be efficient for the provider. It often feels slow for the customer. The user has to explain the same problem multiple times. They get answers that technically relate to the issue but do not solve the real situation. They lose time. They lose confidence. Sometimes they even change their architecture around what is easiest to get support for, instead of what is best for the application. For enterprise teams with dedicated cloud engineers, that friction may be manageable. For small teams, it is expensive. Not only in money. In attention. In delay. In uncertainty. In the cost of stopping real work to decode the platform. ## Smaller teams need clarity, not ceremony A lot of cloud content assumes the buyer has a large engineering organization behind them. But many teams do not work that way. A founder may be handling infrastructure. A developer may also be responsible for deployment, backups, and basic security. An agency may be managing client apps with a small technical team. An MSP may need a cloud provider that helps them move faster without adding operational confusion. A small SaaS team may be running production without a dedicated platform engineer. These users are capable. They are not asking for hand-holding. They are asking for clarity. They need support that respects momentum. They need answers that help them understand: - what is happening - what is safe to change - what should be checked first - what belongs to the infrastructure layer - what belongs to the application layer - what the next practical step should be That is a different standard from generic "premium support." It is not about sounding friendly. It is about being useful. ## What human support should actually mean "Human support" is easy to say and hard to do well. To us, it should mean a few concrete things. ### 1. Context before templates A support reply should not feel like a pasted checklist that ignores the situation. Sometimes the right answer is a command. Sometimes the right answer is a link. But often, the right answer starts by identifying the category of the problem. Is it a VM issue? A DNS issue? A firewall issue? A disk space issue? An application process issue? A Windows RDP issue? A database sizing issue? A backup or restore concern? Infrastructure problems often look similar at the surface but have very different causes underneath. Human support should help users find the real layer of the problem. ### 2. Momentum matters People use infrastructure because they are trying to do something else. They are building. Launching. Migrating. Debugging. Serving customers. Shipping a feature. Testing a new idea. Support should help them keep moving. The goal is not simply to close a ticket. The goal is to reduce friction so the user can continue the work they came to do. That mindset changes the quality of the answer. ### 3. Product knowledge matters Support is better when it is close to the product. If the people helping users understand how the infrastructure actually works, they can give better answers. They can also see patterns faster: - where users get stuck - where docs are unclear - where a workflow needs improvement - where a feature solves most of the problem but leaves confusion - where the dashboard should explain more - where product design can remove a future support request That loop matters. Support should not only react to problems. It should improve the product. ### 4. Honesty matters Good support does not pretend every issue is simple. Sometimes the answer is: ```text This is an application-level bottleneck. ``` Sometimes it is: ```text You need a larger VM. ``` Sometimes it is: ```text This setup should be split across services. ``` Sometimes it is: ```text This is not something the infrastructure layer can fix directly. ``` That honesty helps users make better decisions. A vague answer may feel easier in the moment, but it does not build trust. ## Why Raff made a different decision At Raff, we wanted support to stay close to the product from the beginning. That means support is not just a contact form on top of the platform. It is part of how we think about the product. When someone launches a Raff VM, connects to a Windows VM, reviews data protection, uses Object Storage, or builds across private networks, the support experience should feel connected to the same system. The product should be simple enough that users do not need support for every basic action. But when they do need help, the answer should feel grounded in how the platform actually works. That is the balance we care about: Simple enough to use without constant support. Human enough when support matters. That is one of the reasons we focus on clear infrastructure products instead of trying to turn every cloud feature into a maze. ## Documentation is necessary, but it is not enough We believe in documentation. Docs, tutorials, guides, FAQs, and product pages are important. They help users move independently. But documentation and support are not the same thing. Documentation works best when the user already knows what they are trying to do. Support becomes critical when the user is unsure what the real problem is. A guide can explain how to connect to a server. A tutorial can explain how to configure a firewall. A product page can explain what a VM includes. But when a user is deciding whether to scale, restore, resize, split workloads, change architecture, or debug a production issue, they often need interpretation. Not just information. That is why support still matters in a world full of docs, AI assistants, community forums, and automated workflows. ## Human support also improves the platform Support is not only useful for users. It is useful for the company building the product. When support stays close to product development, the team learns faster. You can see: - which terms confuse users - which product pages need clearer explanations - which dashboard actions need better labels - which errors need better messaging - which workflows should be simplified - which features need stronger defaults - which documentation should be written next That feedback is valuable. If support is too far from the product, the learning becomes weaker. The company may keep answering the same questions without fixing the product reason those questions exist. That is not the model we want. We want support to feed back into a better Raff experience. ## The real cost of bad support Bad support makes infrastructure more expensive than it looks. Not always through the invoice. Through the work around the invoice. Every unclear reply creates another round trip. Every generic answer forces the customer to investigate alone. Every delayed response slows down the work that was supposed to be the actual priority. Every confusing workflow creates hesitation. For a developer, that may mean a launch takes longer. For an agency, it may mean client work slows down. For a startup, it may mean the founder loses a day to infrastructure uncertainty. For an MSP, it may mean operational overhead increases. That is why we do not separate support quality from product quality. A cloud provider can have strong hardware, good pricing, and useful features. But if users cannot get clear help when it matters, the real experience is weaker than the feature list suggests. ## What we are trying to build at Raff We are trying to build a cloud experience where support feels native to the product. That means: - the platform should be simple enough that users need less help - help should still be reachable when users need it - answers should reflect real infrastructure understanding - support should reduce confusion, not add another process - documentation should improve based on real user questions - product decisions should reduce repeated support friction - users should feel like they are talking to people who understand what they are building This is harder than only saying "we care about customers." But it is the kind of company we want to build. Raff is built for developers, small teams, founders, MSPs, and businesses that want infrastructure without unnecessary complexity. For those users, support is not a luxury feature. It is part of the operating experience. ## What this means when choosing a cloud provider When evaluating a cloud provider, do not only ask: ```text Do they offer support? ``` Ask better questions: - How close is support to the actual product? - Will I get context or only scripted replies? - Can I reach someone when the issue matters? - Does the documentation match the real product? - Does support help me keep moving? - Do repeated support questions improve the product over time? Those questions reveal more about the real experience than a generic support badge. Infrastructure is not just CPUs, RAM, storage, and bandwidth. It is the full system around those resources. Provisioning. Networking. Backups. Security. Documentation. Billing clarity. Recovery paths. Support. All of it shapes whether the platform feels usable in real work. ## Why we keep it human We keep support human because infrastructure is still used by humans. Even when the systems are automated. Even when the docs are detailed. Even when dashboards are improving. Someone still has to make decisions under pressure. Someone still has to debug the server. Someone still has to decide whether to resize, restore, redeploy, or wait. Someone still has to explain the problem to a customer, a teammate, or a client. When support is human, close to the product, and focused on context, that person does not have to carry the whole uncertainty alone. That is the kind of cloud experience we want Raff to represent. Not support as a wall between the company and the user. Support as part of the product itself. --- ### What You Can Build with Claude AI + Raff Technologies VPS URL: https://rafftechnologies.com/blog/build-ai-apps-claude-vps-guide Published: 2026-03-11T00:00:00.000Z Description: What You Can Build with Claude AI + Raff Technologies VPS Claude is a powerful model for building AI products, but the model alone is not the product. If you are building with Claude through an API, your real application still needs infrastructure. You need a backend. You need authentication. You need a database. You need API key protection. You need streaming support. You need rate-limit handling. You need logs. You need workers. You need backups. You need a place where the app can reliably run. That is where VPS infrastructure still matters. The short answer: > You can build many Claude-powered AI apps on a VPS because the heavy AI model runs through Claude’s API. Your VPS runs the product layer: backend API, database, Redis, workers, queues, file processing, tool execution, security, monitoring, and deployment. This guide explains what developers can build with Claude, what infrastructure those apps need, when a single VPS is enough, and how to design a clean architecture that can grow. ## Quick answer A Claude-powered app usually looks like this: ```text User ↓ Frontend ↓ Backend API on VPS ↓ Claude API ↓ Database / Redis / files / tools / workers ``` The VPS does not run Claude itself. The VPS runs your application. That application is responsible for: * user accounts * permissions * prompt construction * Claude API calls * streaming responses * conversation storage * tool execution * file processing * database writes * rate limits * retries * logs * backups * security * monitoring For many MVPs and early production apps, one VPS can host the full backend stack. As the product grows, you can split the architecture into multiple VMs or managed services. ## What you can build with Claude and a VPS Claude can be used as the AI layer for many types of applications. A VPS gives you the backend foundation to turn that AI layer into a real product. Common Claude-powered apps include: * AI chatbots * internal assistants * document analysis tools * customer support copilots * sales assistants * developer tools * AI agents * workflow automation systems * knowledge base assistants * report generators * contract review tools * research assistants * SaaS copilots * onboarding assistants * operations dashboards The key difference between a demo and a product is infrastructure. A demo can call Claude once. A product must handle users, data, reliability, cost, security, and operations. ## Why Claude apps still need infrastructure Claude provides the model. Your app still needs the system around the model. A real Claude-powered app needs to handle questions like: * Who is the user? * What organization do they belong to? * What data can they access? * What prompt should be sent to Claude? * Should the response stream back to the frontend? * Should Claude use tools? * Should documents be retrieved first? * Should the request be queued? * What happens if the Claude API is slow? * What happens if a rate limit is hit? * How is usage tracked? * Where is chat history stored? * How are files stored? * How are logs handled? * How are secrets protected? * How are backups restored? Those are infrastructure and backend questions. A VPS gives you a controlled environment to answer them. ## Claude API app architecture A simple Claude app can start with this architecture: ```text Browser ↓ Frontend ↓ Backend API ↓ Claude API ↓ Response ``` A more complete production architecture looks like this: ```text User ↓ Frontend ↓ Nginx or Caddy ↓ Backend API ├── Claude API ├── PostgreSQL ├── Redis ├── Queue ├── Worker process ├── Object storage ├── Vector search └── Logs / monitoring ``` The backend API is the control layer. It decides what gets sent to Claude, what gets stored, what gets shown to the user, and how failures are handled. ## The role of the VPS A VPS is useful because it gives you a dedicated server environment for the backend of your Claude app. Your VPS can run: * Node.js backend * Python FastAPI backend * Laravel backend * Go backend * Nginx or Caddy reverse proxy * PostgreSQL * Redis * background workers * queue workers * Docker containers * monitoring tools * admin dashboards * document processing jobs * webhook handlers * cron jobs The VPS does not replace Claude. It supports Claude. Think of Claude as the intelligence layer and the VPS as the application layer. ## Why most Claude apps do not need GPU servers If you are using Claude through an API, you are not hosting the model yourself. That means your infrastructure does not need to run large model inference. You usually do not need a GPU server for: * Claude chatbots * Claude-powered SaaS features * document Q&A apps * internal assistants * AI support tools * AI workflow automations * report generation tools * customer-facing copilots Your main server workload is usually: * backend request handling * database queries * file processing * queue workers * API calls to Claude * streaming responses * logs * security checks That is why a VPS can be a good starting point. You need GPU infrastructure only when you are running or fine-tuning models yourself, not when you are using Claude as an external API. ## Core components of a Claude-powered app ## 1. Backend API The backend API is the center of the product. It receives requests from the frontend and decides how to interact with Claude. The backend usually handles: * authentication * organization logic * permissions * prompt templates * system instructions * Claude API requests * streaming responses * rate limits * retries * file upload logic * document retrieval * conversation storage * usage tracking * billing checks * logs Common backend stacks include: * Node.js * Express * Fastify * Next.js API routes * Python FastAPI * Django * Flask * Laravel * Go * .NET For a first version, choose the stack your team can operate confidently. ## 2. Database Most Claude apps need a database. PostgreSQL is a strong default for many AI apps because it can store: * users * organizations * conversations * messages * prompts * files * metadata * billing events * usage records * permissions * audit logs * settings A Claude chatbot without a database is usually just a demo. A Claude app with a database becomes a product. ## 3. Redis Redis is not required for every Claude app, but it becomes useful quickly. Use Redis for: * caching * sessions * rate limits * queue state * temporary context * token counters * cooldowns * duplicate request protection * job coordination Example: ```text User sends message ↓ Backend checks Redis rate limit ↓ Backend sends prompt to Claude ↓ Backend stores result in PostgreSQL ``` This prevents one user, bug, or script from overwhelming the system. ## 4. Queues and workers Claude apps often have tasks that should not run directly inside the web request. Examples: * parsing PDFs * generating summaries * extracting structured data * creating embeddings * processing long documents * generating reports * retrying failed Claude calls * sending emails * processing webhooks * syncing knowledge bases A better pattern is: ```text User action ↓ Backend API ↓ Queue ↓ Worker ↓ Claude API ↓ Database result ``` This makes the app more stable because long-running jobs do not block the frontend request. ## 5. File storage Many Claude apps work with files. Examples: * PDFs * contracts * CSVs * Word documents * support transcripts * product manuals * invoices * reports Do not treat uploaded files casually. You need to decide: * where files are stored * who can access them * how long they are retained * how they are processed * whether they are deleted * whether extracted text is stored * whether files are sent to Claude * whether private data is logged A clean architecture separates file storage from app code. For production apps, object storage is often better than storing everything inside the application directory. ## 6. Vector search for Claude apps Claude can answer questions better when your app retrieves relevant context first. This is common for: * document Q&A * internal knowledge assistants * customer support bots * legal document tools * onboarding assistants * product documentation search * company wiki assistants A simplified RAG flow: ```text User asks a question ↓ Backend searches relevant documents ↓ Backend retrieves useful context ↓ Backend sends context + question to Claude ↓ Claude returns grounded answer ``` For early apps, you can start simple. As the product grows, you may add dedicated vector search infrastructure. The important rule: > Do not send every document to Claude on every request. Retrieve only the context that is relevant. ## 7. Reverse proxy Use Nginx or Caddy in front of the app. A reverse proxy helps with: * HTTPS * routing * static files * compression * request forwarding * security headers * keeping the app port private A clean setup looks like this: ```text User ↓ Nginx or Caddy ↓ Backend app on localhost ``` Do not expose your backend development port directly to the internet. ## 8. Monitoring and logs Claude apps need normal system monitoring and AI-specific monitoring. System metrics: * CPU usage * RAM usage * disk usage * HTTP error rate * request latency * database performance * Redis memory * queue depth * worker failures Claude-specific metrics: * Claude API latency * Claude API error rate * rate-limit errors * retry count * timeout count * input token usage * output token usage * cost per user * cost per workspace * failed generations * streaming failures * tool call failures If you cannot see these metrics, you cannot operate the app properly. ## Example: simple Claude app on one VPS A clean MVP architecture can run on one VPS: ```text Single Raff VM ├── Nginx or Caddy ├── Backend API ├── PostgreSQL ├── Redis ├── Worker process └── Logs / monitoring ``` This is enough for many early Claude apps. Use one VPS when: * traffic is low to moderate * the app is still early * you want predictable monthly cost * the database is not large * workers are not heavy * you want operational simplicity * you are validating product demand A single VPS is not the final architecture for every app. But it is often the right first production foundation. ## Example: multi-VM Claude app architecture As the product grows, split services: ```text Load balancer ↓ App VM ↓ Database VM ↓ Redis / queue VM ↓ Worker VM ↓ Monitoring ``` Move to this when: * web traffic grows * workers slow down the main app * database load increases * you need stronger isolation * uptime requirements increase * multiple developers are deploying * customers depend on the app daily * background jobs are business-critical The goal is not to overbuild from day one. The goal is to design the first version so it can grow without a painful rewrite. ## Minimal Claude backend example Here is a simplified Node.js-style backend flow. This is not a full production app, but it shows the right pattern: ```js import express from "express"; import Anthropic from "@anthropic-ai/sdk"; const app = express(); app.use(express.json()); const anthropic = new Anthropic({ apiKey: process.env.CLAUDE_API_KEY }); app.post("/api/chat", async (req, res) => { try { const { message } = req.body; if (!message || typeof message !== "string") { return res.status(400).json({ error: "Message is required." }); } const response = await anthropic.messages.create({ model: process.env.CLAUDE_MODEL, max_tokens: 800, system: "You are a helpful assistant for this application.", messages: [ { role: "user", content: message } ] }); return res.json({ answer: response.content }); } catch (error) { console.error("Claude request failed:", error); return res.status(500).json({ error: "AI response failed. Please try again." }); } }); app.listen(3000, () => { console.log("Claude app backend running on port 3000"); }); ``` Important details: * the Claude API key stays on the server * the frontend never calls Claude directly * the backend validates input * errors are handled * the app runs behind a reverse proxy * the model name is controlled by environment variable * production apps should add authentication, rate limits, logs, and database storage ## Streaming Claude responses For chat experiences, streaming improves perceived speed. Without streaming: ```text User sends message ↓ Wait ↓ Full response appears ``` With streaming: ```text User sends message ↓ First tokens appear ↓ Response continues in real time ``` Streaming requires the backend and reverse proxy to support longer-lived responses. You should test: * frontend streaming UI * proxy timeout settings * backend timeout settings * user cancellation * partial response handling * error handling during stream * logging for failed streams Streaming is useful, but it adds complexity. For an MVP, start without streaming if needed. For a polished chatbot, add streaming once the core flow is stable. ## Claude tool use architecture Claude can work with tools, but your application must decide how tools are executed. A tool can be something like: * search internal documents * check order status * create a support ticket * query a database * call a CRM API * generate a report * schedule an event * fetch product information * run a workflow A simplified tool flow: ```text User asks a request ↓ Backend sends tool definitions to Claude ↓ Claude requests a tool call ↓ Backend validates permission ↓ Backend executes tool ↓ Backend sends tool result back to Claude ↓ Claude responds to user ``` Tool use is powerful, but it must be controlled. Do not let AI tools execute dangerous actions without validation. For production: * define strict schemas * validate tool inputs * check user permissions * log tool calls * add approval steps for risky actions * prevent access to unauthorized data * avoid exposing internal admin tools directly Claude can decide when a tool may be useful, but your backend is responsible for safe execution. ## Prompt caching for Claude apps Prompt caching can help when your app repeatedly sends the same long context. Useful cases include: * long system prompts * repeated tool definitions * large instruction blocks * documentation context * repeated examples * long multi-turn conversations * stable knowledge packs A simple example: ```text System prompt + tool definitions + stable docs ↓ Cached prefix ↓ New user message changes each request ``` This can reduce cost and latency for repeated workloads. But prompt caching works best when the cached part stays stable. If your app changes the prompt structure on every request, caching becomes less effective. Good caching strategy: * keep stable instructions at the beginning * keep dynamic user content later * avoid constantly changing tool definitions * monitor cache hit rate * cache large repeated context, not tiny prompts * keep private data handling rules clear Prompt caching is not a replacement for good retrieval. For document apps, still retrieve only relevant context. ## Handling rate limits and retries Claude API usage is not unlimited. Your backend should expect limits and failures. Handle: * request rate limits * input token limits * output token limits * temporary API errors * timeouts * retry-after headers * sharp traffic spikes * user abuse * duplicate requests Bad pattern: ```text User sends request ↓ Claude rate limit hit ↓ App crashes or returns generic error ``` Better pattern: ```text User sends request ↓ Backend checks local rate limit ↓ Claude request sent ↓ If rate-limited, respect retry timing ↓ Return clear message or retry safely ↓ Log the event ``` Add your own application-level limits too. Examples: * messages per minute * tokens per day * requests per workspace * file upload limits * document processing limits * free plan usage caps * paid plan usage caps This protects your product and your AI API budget. ## Security basics for Claude apps Claude apps often handle sensitive information. Treat security as part of the architecture. ## Keep API keys on the server Never expose your Claude API key in frontend code. Bad pattern: ```text Browser → Claude API ``` Better pattern: ```text Browser → your backend → Claude API ``` The backend protects secrets and controls usage. ## Use environment variables or secrets Do not hard-code API keys into source code. Use: * environment variables * secret managers * deployment secrets * restricted server files Also rotate keys if they are exposed. ## Validate user access Every request should check: * user identity * workspace membership * role * document access * billing status * usage limits * admin permissions This is especially important for SaaS products and internal assistants. ## Protect files and documents If users upload files, control: * max file size * file types * access permissions * retention * deletion * storage location * extraction safety * whether file content is logged * whether file content is sent to Claude Document apps need strong data handling rules. ## Do not over-log sensitive content Logs are useful, but dangerous if they contain private data. Avoid logging: * API keys * passwords * full private documents * sensitive prompts * customer secrets * payment data * personal data you do not need Log enough to debug. Do not log everything. ## Example Claude app use cases ## 1. Customer support chatbot A support chatbot can answer customer questions using: * product documentation * FAQ pages * help center articles * account metadata * ticket history * order status tools Infrastructure needed: * backend API * database * vector search * Redis rate limits * support tool integrations * logs * admin review tools ## 2. Document analysis app A document app lets users upload files and ask questions. Infrastructure needed: * file upload handling * object storage * text extraction * background workers * vector search * PostgreSQL * Claude API calls * file access controls * retention rules ## 3. Internal company assistant An internal assistant can help employees search company knowledge. Infrastructure needed: * authentication * role-based access * document sync jobs * vector database * Claude API integration * audit logs * admin controls * private networking if needed ## 4. AI SaaS copilot A SaaS copilot helps users complete actions inside a product. Infrastructure needed: * product database access * user permissions * tool execution * workflow controls * safe action approvals * usage tracking * billing integration * monitoring ## 5. AI workflow automation A workflow automation app uses Claude to classify, summarize, or generate actions. Infrastructure needed: * webhook handlers * queue workers * retries * scheduled jobs * tool calls * API integrations * Redis * logs * error handling ## Deployment pattern for a Claude app on a VPS A practical first deployment can look like this: ```text Raff VM ↓ Ubuntu ↓ Firewall ↓ Nginx or Caddy ↓ Backend app on localhost ↓ PostgreSQL + Redis ↓ Claude API ``` The backend app should not be exposed directly. Use a reverse proxy. Use HTTPS. Keep databases private. Use firewall rules. Run the app with a process manager such as: * systemd * PM2 * Docker Compose * Supervisor Pick the method your team can maintain. ## Production checklist Before launching a Claude-powered app, check these basics. ## Server * Use a stable Linux server. * Configure SSH key access. * Disable password login if possible. * Configure firewall rules. * Install Nginx or Caddy. * Use HTTPS. * Keep app ports private. * Set up automatic security updates if appropriate. * Monitor CPU, RAM, disk, and network usage. ## Backend * Keep Claude API keys on the server. * Use environment variables. * Validate user input. * Add authentication. * Add authorization. * Store conversations in a database. * Add rate limits. * Handle timeouts. * Handle retries safely. * Return clear user-facing errors. * Log failures without leaking sensitive data. ## Claude integration * Use system prompts intentionally. * Keep prompts versioned. * Track token usage. * Monitor latency. * Monitor errors. * Handle rate limits. * Use streaming only after testing proxy and frontend behavior. * Use prompt caching for repeated long context. * Use tools only with validation and permission checks. ## Data * Back up the database. * Back up uploaded files. * Define retention rules. * Restrict document access. * Test restore. * Avoid logging sensitive prompts or documents. * Separate customer data by workspace or organization. ## Workers * Use queues for slow tasks. * Monitor queue depth. * Track worker failures. * Retry safely. * Avoid duplicate job execution. * Keep long tasks outside normal web requests. ## Operations * Create a staging environment. * Document deployment steps. * Add rollback strategy. * Monitor logs. * Monitor API spend. * Track usage by user or workspace. * Review failed requests regularly. ## When one VPS is enough One VPS is often enough when: * you are building an MVP * traffic is low to moderate * users are early-stage * the database is not large * background jobs are light * uptime needs are reasonable * you want simple operations * you want predictable monthly pricing * you are still validating the product Example starter stack: ```text 1 VPS ├── Nginx ├── Backend API ├── PostgreSQL ├── Redis ├── Worker └── Monitoring ``` This is a strong starting point for many Claude-based products. ## When to split into multiple VMs Move beyond one VPS when: * traffic grows * workers slow down the app * database load increases * Redis becomes critical * file processing becomes heavy * uptime requirements increase * multiple developers deploy frequently * staging and production must be isolated * customers depend on the app daily * you need clearer security boundaries A next-stage setup: ```text Load balancer ↓ App VM ↓ Database VM ↓ Redis / queue VM ↓ Worker VM ↓ Monitoring ``` This gives you more control over scaling and reliability. ## How Raff VM fits Claude app infrastructure Raff VM gives developers a simple cloud server foundation for Claude-powered apps. You can use Raff VM to run: * Claude app backends * AI chatbot APIs * SaaS copilots * internal assistants * document analysis tools * Redis * PostgreSQL * workers * queues * Docker workloads * staging environments * monitoring tools For an MVP, one Raff VM can host the full backend stack. As the product grows, you can split services across multiple Raff VMs: ```text App VM Database VM Redis VM Worker VM Monitoring VM ``` Raff VM is useful when you want: * simple deployment * full server control * predictable monthly pricing * strong CPU performance * NVMe storage * unmetered bandwidth * Linux or Windows VM options * a clean path from MVP to production The goal is not to add cloud complexity. The goal is to give the Claude app a reliable place to run. ## Common mistakes when building Claude apps ## Mistake 1: Calling Claude directly from the frontend This exposes your API key and removes backend control. Always use a backend. ## Mistake 2: No database If conversations, users, and usage are not stored, the app is only a demo. Use a database early. ## Mistake 3: No rate limits A single user, bot, or bug can create high API costs. Add rate limits before public launch. ## Mistake 4: No worker queue Long document processing and batch AI tasks should not block web requests. Use workers. ## Mistake 5: No prompt versioning Prompts are application logic. Track prompt changes like code changes. ## Mistake 6: No cost monitoring AI API usage can grow quickly. Track requests, tokens, retries, and cost by user or workspace. ## Mistake 7: No restore testing Backups are not enough. You must test restore. ## Mistake 8: Overbuilding too early Do not start with complex architecture before users exist. Start clean, then scale. ## Mistake 9: Underbuilding after customers arrive Once customers depend on the app, add staging, monitoring, backups, security hardening, and failure handling. ## Final architecture recommendation For most Claude app builders, use this path: ```text Stage 1: Prototype Local development + Claude API Stage 2: MVP One VPS with backend, database, Redis, worker Stage 3: Early production One stronger VPS or separate database Stage 4: Growth App VM + database VM + Redis/queue VM + worker VM Stage 5: Scale Load balancer, multiple app VMs, stronger observability, managed services where needed ``` This keeps infrastructure practical. Do not overbuild before demand. Do not stay too simple when users depend on the product. ## FAQ ### Can I build Claude apps on a VPS? Yes. Many Claude-powered apps can run on a VPS because Claude itself runs through an external API. The VPS runs your backend, database, Redis, workers, queues, logs, and application logic. ### Do Claude apps need GPU servers? Not if you are using Claude through the API. GPU servers are needed when you run models yourself. API-based Claude apps usually need reliable backend infrastructure, not GPU inference infrastructure. ### What can I build with Claude and a VPS? You can build AI chatbots, document analysis tools, internal assistants, support copilots, SaaS copilots, automation tools, developer tools, and AI workflow systems. ### What infrastructure does a Claude app need? A Claude app usually needs a backend API, database, reverse proxy, authentication, rate limits, logs, and Claude API integration. More advanced apps may need Redis, queues, workers, object storage, vector search, and monitoring. ### Should the frontend call Claude directly? No. The frontend should call your backend, and your backend should call Claude. This keeps API keys private and lets you control permissions, rate limits, logging, and usage. ### Do I need Redis for a Claude app? Not always, but Redis is useful for caching, sessions, rate limits, queues, temporary state, and background job coordination. ### When should I use workers in a Claude app? Use workers for slow or long-running tasks such as document parsing, embeddings, report generation, batch processing, retries, webhooks, and scheduled AI jobs. ### How does Raff VM help with Claude app deployment? Raff VM gives developers a cloud server foundation for running Claude app backends, databases, Redis, workers, Docker workloads, staging environments, and monitoring tools with simple deployment and predictable monthly pricing. ## Conclusion Claude can power powerful AI products, but Claude alone is not your application. Your product still needs backend infrastructure. It needs authentication, database storage, rate limits, streaming, tools, workers, queues, security, logs, monitoring, backups, and deployment discipline. For many Claude-powered apps, a VPS is the right starting point. It gives enough control to build a real backend without forcing your team into unnecessary cloud complexity. Start with a clean VPS architecture. Run the backend properly. Protect your API keys. Store data carefully. Add rate limits and observability. Use workers for slow tasks. Use prompt caching and retrieval where they make sense. Then scale into multiple VMs when the product proves it needs more structure. The AI model generates the intelligence. Your infrastructure makes it reliable. --- ### AI Chatbot Infrastructure in 2026: How to Run API-Based AI Apps on a VPS URL: https://rafftechnologies.com/blog/ai-chatbots-api-infrastructure-2026 Published: 2026-03-02T00:00:00.000Z Description: AI Chatbot Infrastructure in 2026: How to Run API-Based AI Apps on a VPS AI chatbots are no longer just demos. In 2026, teams are building AI chatbots for: * customer support * internal knowledge search * sales assistance * coding workflows * document analysis * onboarding * operations * reporting * SaaS copilots * workflow automation But there is one mistake many builders still make. They think the hardest infrastructure problem is the AI model. For most API-based AI chatbots, that is not true. If you are using AI providers through APIs, the model is not running on your server. Your real infrastructure problem is the application backend. Your backend must handle users, sessions, prompts, context, API calls, retries, rate limits, logs, storage, queues, workers, security, and uptime. That is where infrastructure still matters. The short answer: > Most API-based AI chatbots do not need GPU servers. They need a reliable backend server that can orchestrate AI API calls, store context, run workers, manage queues, protect secrets, and stay online. A well-sized VPS can be enough for many AI chatbot MVPs and early production apps. This guide explains how API-based AI chatbot infrastructure works, what components you need, when one VPS is enough, and when to split into multiple servers. ## Quick answer Most AI chatbots built with external AI APIs need infrastructure like this: ```text User ↓ Frontend ↓ Backend API ↓ AI provider API ↓ Database / Redis / vector store / queue / workers ``` The backend is the control layer. It decides: * who the user is * what the user is allowed to do * what prompt should be sent * what context should be included * which AI model or provider to call * how to handle streaming responses * how to store messages * how to retry failed requests * how to manage rate limits * how to log errors * how to protect API keys * how to monitor cost and usage For an MVP, this can often run on one VPS. For a growing AI product, you may later separate the app server, database, Redis, workers, and monitoring into different VMs or managed services. ## Why most AI chatbots do not need GPU servers Some AI workloads need GPU infrastructure. Examples include: * training models * fine-tuning large models * running local LLM inference * serving open-source models at scale * image or video generation workloads * high-throughput model hosting But many AI chatbot products do not start there. Most early AI chatbot apps use external AI APIs. That means the heavy model inference happens outside your infrastructure. Your server does not need to run the model. Your server needs to run the product. That includes: * user accounts * chat interface backend * conversation storage * prompt construction * retrieval logic * payment checks * usage limits * API provider calls * streaming response handling * background jobs * logs and monitoring * admin tools * security controls So for many teams, the first infrastructure question should not be: ```text Which GPU server do we need? ``` It should be: ```text Where should we run the backend that controls the AI product? ``` For many MVPs, SaaS prototypes, internal tools, and production-ready small apps, the answer can be a VPS. ## What the AI chatbot backend actually does A serious AI chatbot is not just a frontend calling an AI API. The backend is responsible for the logic that turns a model response into a usable product. A typical AI chatbot backend handles: * authentication * user permissions * organization or workspace logic * chat history * prompt templates * system instructions * message formatting * AI provider requests * response streaming * rate limits * retries and timeouts * billing or usage limits * file uploads * document parsing * vector search * database writes * logs * analytics * security checks * admin dashboards This is why infrastructure matters. The model may generate the answer, but your backend decides how the product behaves. If your backend is slow, unstable, insecure, or poorly designed, the AI experience will feel broken even if the model is good. ## Typical AI chatbot architecture A simple API-based AI chatbot architecture looks like this: ```text Browser or mobile app ↓ Frontend application ↓ Backend API ↓ AI provider API ↓ Response back to user ``` A more realistic production architecture looks like this: ```text User ↓ Frontend ↓ Backend API ├── PostgreSQL for users, messages, billing, metadata ├── Redis for cache, sessions, rate limits, queues ├── Vector database for document search and embeddings ├── Worker process for background jobs ├── Object storage for uploaded files └── AI provider API for model responses ``` The backend is the center of the system. It connects your product to the AI provider, but also controls everything around that provider. That is the difference between a demo and a real AI application. ## Core infrastructure components An API-based AI chatbot usually needs several infrastructure pieces. Not every project needs all of them on day one, but most serious products eventually use some version of this stack. ## 1. Backend API server The backend API server is the main application layer. It may be built with: * Node.js * Python * FastAPI * Flask * Django * Laravel * Go * Ruby on Rails * .NET * Java The backend receives user requests, validates them, builds prompts, calls AI APIs, stores results, and returns responses. For small teams, this is usually the first thing to deploy on a VPS. A simple starting point: ```text Ubuntu VPS ↓ Nginx reverse proxy ↓ Backend app ↓ PostgreSQL / Redis / AI provider API ``` ## 2. Database Most AI chatbots need a relational database. PostgreSQL is a common choice because it works well for: * users * teams * organizations * permissions * subscriptions * chat sessions * conversation metadata * message history * usage tracking * audit logs * billing events * application settings A database gives your AI chatbot memory at the product level. Without a database, you may be able to generate answers, but you cannot build a serious product. ## 3. Redis Redis is useful for fast, temporary, and high-frequency data. In AI chatbot infrastructure, Redis can help with: * caching * session storage * rate limiting * request deduplication * queue management * temporary conversation state * API cooldowns * token budget counters * background job coordination Redis is especially useful when the app becomes more than a simple request-response chatbot. For example, if users upload documents and you need to process them in the background, Redis can support a queue system that sends jobs to workers. ## 4. Queue and workers Many AI tasks should not run directly inside the web request. Examples: * document parsing * file conversion * embedding generation * long summaries * report generation * email workflows * scheduled jobs * webhook processing * batch AI calls * retrying failed provider requests If these jobs run inside the main web request, users may wait too long or the request may time out. A better pattern is: ```text User request ↓ Backend API ↓ Add job to queue ↓ Worker processes job ↓ Store result ↓ Notify user or update UI ``` This keeps the app responsive. It also makes scaling easier because workers can be separated from the main web server later. ## 5. Vector database or vector search Many AI chatbots need to answer questions using private documents or company knowledge. That is where vector search comes in. A vector search system stores embeddings so the app can retrieve relevant chunks of information before calling the AI model. Typical use cases: * support knowledge base chatbot * internal company assistant * document Q&A * legal document assistant * product documentation chatbot * onboarding assistant * customer success copilot * sales enablement assistant A simplified retrieval flow looks like this: ```text User question ↓ Create query embedding ↓ Search vector database ↓ Retrieve relevant context ↓ Send context + question to AI API ↓ Return grounded answer ``` This is often called retrieval-augmented generation, or RAG. A simple AI chatbot may not need vector search. A chatbot that answers from private knowledge usually does. ## 6. Object storage AI chatbot products often handle uploaded files. Examples: * PDFs * Word documents * CSV files * images * contracts * support transcripts * knowledge base exports * product manuals The app should not always store these directly on the application server. For many products, object storage is better for uploaded files because it separates file storage from compute. A common pattern: ```text User uploads file ↓ Backend stores file in object storage ↓ Worker extracts text ↓ Worker creates embeddings ↓ Vector database stores searchable chunks ``` This is cleaner than keeping everything inside one app directory. ## 7. Reverse proxy A reverse proxy such as Nginx or Caddy sits in front of your backend app. It can handle: * HTTPS * request routing * compression * static files * connection handling * basic security headers * proxying traffic to the app * redirecting HTTP to HTTPS A common setup: ```text User browser ↓ Nginx ↓ Backend app on localhost ``` This keeps the app port private and exposes only standard web ports. ## 8. Monitoring and logs AI chatbot infrastructure needs visibility. You should be able to answer: * Is the app online? * Are AI API calls failing? * Are users seeing errors? * Are requests timing out? * Are workers stuck? * Is Redis overloaded? * Is the database slow? * Are rate limits being hit? * Are costs increasing? * Which deployment caused problems? At minimum, track: * application logs * error logs * request latency * AI API latency * failed AI API calls * token usage or request volume * database performance * queue depth * worker failures * disk usage * CPU and RAM usage Observability becomes more important as the AI app moves from demo to product. ## Why queues and background workers matter AI apps often involve slow or unpredictable tasks. A normal web app might save a form and return immediately. An AI app may need to: * call an external AI API * wait for streaming output * process documents * generate embeddings * summarize long files * retry failed requests * call multiple tools * update a vector database * generate follow-up actions If all of this happens inside the main web request, the app becomes fragile. Queues solve this. They let you process long-running work outside the user request. For example: ```text User uploads 50-page PDF ↓ Backend accepts file ↓ Queue job created ↓ Worker extracts text ↓ Worker chunks document ↓ Worker creates embeddings ↓ Worker stores vectors ↓ User can ask questions later ``` This is a much better experience than forcing the user to wait while everything happens synchronously. ## Rate limits, retries, and API failure handling AI APIs can fail. They can also be slow, rate-limited, unavailable, or return errors. Your backend should expect this. A reliable AI chatbot backend should handle: * timeouts * retries * rate limits * provider errors * invalid responses * partial streaming failures * duplicate requests * user cancellation * slow requests * fallback behavior * graceful error messages Bad pattern: ```text User sends message ↓ Backend calls AI API ↓ AI API fails ↓ User sees generic error ``` Better pattern: ```text User sends message ↓ Backend calls AI API with timeout ↓ If temporary failure, retry safely ↓ If still failing, return clear message ↓ Log error for debugging ↓ Track failure rate ``` You do not need a complex system on day one. But you should avoid pretending AI APIs will always respond perfectly. Production AI apps need failure handling. ## Streaming responses Many chatbots stream responses token by token. This makes the product feel faster because the user sees output while the model is still generating. Streaming requires your backend to handle open connections properly. Your infrastructure should support: * long-lived HTTP responses * connection timeouts * reverse proxy configuration * frontend streaming UI * cancellation handling * partial response storage * error handling during streaming For a basic chatbot MVP, streaming is optional. For a polished chat experience, it often matters. ## Security basics for AI chatbot infrastructure AI chatbots introduce security risks. Your backend may handle: * user messages * private documents * API keys * customer data * uploaded files * internal knowledge * database credentials * AI provider credentials * billing information * admin access Start with these basics. ## Protect API keys Never expose AI provider API keys in frontend code. API keys should live on the server. Bad pattern: ```text Browser → AI provider API directly using public key ``` Better pattern: ```text Browser → your backend → AI provider API ``` This lets your backend control usage, permissions, rate limits, and logging. ## Validate users and permissions Do not assume every authenticated user can access every conversation or file. Check: * user ID * organization ID * workspace access * document permissions * admin role * billing status * usage limits This is especially important for multi-tenant SaaS chatbots. ## Do not expose private services publicly Databases, Redis, admin panels, and internal dashboards should not be open to the public internet. Only expose what must be public. For many AI apps, public ports should usually be limited to: * 80 for HTTP * 443 for HTTPS * SSH access restricted and secured Private services should be bound to localhost, private networking, or protected access controls. ## Sanitize and control uploaded files If your AI chatbot accepts files, treat uploads carefully. Think about: * file type limits * file size limits * malware scanning * text extraction safety * storage permissions * user access controls * deletion policy * retention rules * private data exposure Document chatbots are useful, but uploaded files create real operational responsibility. ## Log carefully Logs help debugging. But logs can also leak sensitive data. Avoid logging: * full API keys * passwords * secrets * private documents * payment data * unnecessary personal data * full prompts containing sensitive customer information Log enough to debug. Do not log everything blindly. ## When one VPS is enough One VPS is often enough for an AI chatbot MVP or early production product. A simple architecture can run: * backend API * Nginx or Caddy * PostgreSQL * Redis * worker process * application logs * monitoring agent Example: ```text Single VPS ├── Nginx ├── Backend API ├── PostgreSQL ├── Redis ├── Worker process └── Monitoring ``` This can be a good starting point when: * traffic is low to moderate * the app is early-stage * the team wants simplicity * the database is not huge * workers are not heavy * uptime requirements are reasonable * the product is still validating demand * the team wants predictable monthly cost Do not overbuild too early. For many AI products, the first bottleneck is not infrastructure. It is product-market fit, prompt quality, onboarding, retention, and workflow design. A simple VPS keeps the system understandable. ## When you need more than one VM As the AI product grows, the single-server setup may become limiting. Move toward multi-VM architecture when: * web traffic grows * background jobs slow down the app * database load increases * Redis becomes critical * workers need independent scaling * downtime risk becomes unacceptable * deploys need better separation * staging and production must be isolated * monitoring becomes more important * the team needs clearer security boundaries A next-step architecture: ```text Load balancer ↓ App VM ↓ Database VM ↓ Redis / queue VM ↓ Worker VM ↓ Monitoring / logs ``` You do not need this on day one. But it is good to design the app so it can grow into this structure. The easiest way to scale later is to avoid hard-coding everything into one machine from the beginning. ## Single VPS vs multi-VM AI chatbot architecture | Stage | Infrastructure | Best for | | ---------------- | -------------------------------------------------- | ------------------------------------------- | | Prototype | Local app or small VPS | Testing idea and UI | | MVP | One VPS with app, database, Redis, worker | Early users and product validation | | Early production | VPS with app + managed or separate database | More reliability and safer operations | | Growing product | Separate app, database, Redis, worker VMs | Higher traffic and background jobs | | Larger scale | Load balancer, multiple app VMs, separate services | Teams with serious uptime and scaling needs | Start simple. Scale when the workload proves it needs more structure. ## Example MVP stack for an AI chatbot on a VPS A practical MVP stack could look like this: ```text Ubuntu VPS Nginx Node.js or FastAPI backend PostgreSQL Redis Worker process AI provider API Basic logs Daily backups ``` This stack can support: * user login * chat sessions * AI API calls * saved conversations * rate limits * background jobs * document processing * basic admin tools * staged deployment process For many builders, this is enough to launch the first version. ## Example production-ready stack A stronger production setup could look like this: ```text Frontend ↓ Load balancer ↓ App VM ↓ PostgreSQL VM or managed database ↓ Redis / queue VM ↓ Worker VM ↓ Object storage ↓ Monitoring and logs ``` This setup is better when: * the app has paying users * uptime matters * background jobs are frequent * database load is growing * multiple developers deploy changes * file uploads are common * business data must be protected * the app needs staging and production separation This is the point where infrastructure becomes part of the product experience. ## Cost control for AI chatbot infrastructure AI chatbot cost has two sides. The first is infrastructure cost. This includes: * VPS * database * object storage * backups * bandwidth * monitoring * logs The second is AI provider cost. This includes: * model API calls * input tokens * output tokens * embeddings * batch jobs * retries * tool calls * image, audio, or multimodal usage if used A good backend helps control both. You can reduce waste by adding: * request caching * prompt size limits * document chunking * rate limits per user * usage quotas * retry limits * model selection by task * background batch processing * shorter system prompts * response length controls * analytics for expensive users or workflows Infrastructure is not just about uptime. It also helps control AI spend. ## Common mistakes when building AI chatbot infrastructure ## Mistake 1: Calling the AI API directly from the frontend This exposes secrets and removes backend control. Use a backend server. ## Mistake 2: Not storing conversations properly Chat history is product data. Store it in a database with user and organization ownership. ## Mistake 3: No rate limits Without rate limits, one user or bug can create high API usage. Use rate limits by user, organization, IP, or plan. ## Mistake 4: No queue for slow tasks Long-running AI tasks should often run in background workers. Do not force every task into the main web request. ## Mistake 5: No observability If you cannot see errors, latency, queue depth, and AI API failures, you cannot operate the product properly. ## Mistake 6: Treating prompts as hard-coded text Prompts become part of the application. Version them, test them, and review changes. ## Mistake 7: Ignoring data privacy AI chatbots often handle sensitive information. Think carefully about retention, logs, access, and user permissions. ## Mistake 8: Overbuilding before users exist Do not build enterprise-scale infrastructure before validating the product. Start with a clean VPS architecture. Scale when the workload proves it needs it. ## Mistake 9: Underbuilding after users arrive Once customers depend on the chatbot, infrastructure matters more. Add backups, monitoring, staging, security hardening, and recovery planning. ## What to monitor in an AI chatbot app Monitor both system health and AI-specific behavior. System metrics: * CPU usage * RAM usage * disk usage * network usage * database performance * Redis memory * queue depth * worker failures * HTTP error rate * request latency AI-specific metrics: * AI API latency * AI API error rate * timeout rate * retries * token usage * cost per user * cost per workspace * failed generations * average response length * document processing failures * embedding job failures Product metrics: * messages per user * retained users * active workspaces * completed workflows * user satisfaction * support escalations * conversion from trial to paid A chatbot that is technically online can still be failing as a product. Monitor the system and the user experience. ## How Raff VM fits AI chatbot infrastructure Raff VM is a good fit for teams building API-based AI chatbots because these apps often need a reliable cloud server more than a GPU cluster. A Raff VM can run: * backend API server * Nginx or Caddy reverse proxy * PostgreSQL * Redis * worker processes * Docker workloads * internal AI tools * chatbot backends * SaaS admin panels * staging environments * monitoring tools For an MVP, one Raff VM can act as the main backend server. As the product grows, teams can separate services across multiple VMs: ```text App VM Database VM Redis / queue VM Worker VM Monitoring VM ``` This gives the app a clean growth path. Raff VM fits AI chatbot teams that want: * simple deployment * full server control * predictable monthly pricing * strong CPU performance * NVMe storage * unmetered bandwidth * Linux or Windows VM options * a practical path from MVP to production The goal is not to make infrastructure complicated. The goal is to give the AI product a stable place to run. ## Practical launch checklist Before launching an AI chatbot backend, check the basics. ## Server setup * Choose a VPS size that fits your expected traffic. * Use a stable Linux distribution. * Configure SSH key access. * Set up a firewall. * Install your runtime. * Put Nginx or Caddy in front of the app. * Use HTTPS. * Keep the app process managed with systemd, PM2, Docker, or another process manager. ## App setup * Store API keys on the server, not in frontend code. * Use environment variables or a secrets strategy. * Add authentication. * Store users and conversations in a database. * Add rate limits. * Add request timeouts. * Handle retries safely. * Log failures. * Add basic admin visibility. ## AI setup * Track model usage. * Limit prompt size. * Control response length. * Add usage quotas. * Handle API provider errors. * Add streaming only when the backend and proxy are ready. * Use background workers for slow tasks. * Test with real user workflows. ## Data setup * Back up the database. * Decide retention rules. * Protect uploaded files. * Avoid logging sensitive data. * Separate user data by organization or workspace. * Test restore before production. ## Operations setup * Monitor uptime. * Monitor disk usage. * Monitor logs. * Monitor queue depth. * Monitor AI API failures. * Create a rollback plan. * Create a staging environment before serious releases. A simple checklist prevents many painful launch problems. ## When a VPS is not enough A VPS is a good starting point for many AI chatbot apps, but it is not always enough. You may need more infrastructure when: * you run local LLM inference * you need GPU acceleration * traffic is very high * uptime requirements are strict * database size grows quickly * multiple workers are constantly busy * customers require dedicated environments * compliance requirements increase * you need regional deployment * you need high availability architecture At that point, you may move toward: * multiple VMs * load balancers * managed databases * object storage * Kubernetes * GPU servers * dedicated vector search infrastructure * separate environments for each customer Do not start there unless the product needs it. But design your system so it can grow. ## FAQ ### Do AI chatbots need GPU servers? Not always. API-based AI chatbots usually do not need GPU servers because the AI model runs through an external provider API. The chatbot backend still needs reliable infrastructure for users, prompts, sessions, queues, databases, logs, and API orchestration. ### Can I run an AI chatbot backend on a VPS? Yes. Many AI chatbot MVPs and early production apps can run on a VPS, especially if they use external AI APIs. The VPS can host the backend API, reverse proxy, PostgreSQL, Redis, worker processes, and monitoring tools. ### What infrastructure does an AI chatbot need? A typical AI chatbot needs a backend API server, database, AI provider integration, authentication, logging, rate limits, and error handling. More advanced chatbots may also need Redis, queues, background workers, object storage, and vector search. ### What database should I use for an AI chatbot? PostgreSQL is a strong default for users, conversations, organizations, permissions, usage tracking, and metadata. If the chatbot uses private documents or knowledge search, you may also need vector search or a vector database. ### Do I need Redis for an AI chatbot? Not always, but Redis is useful for caching, sessions, rate limits, queues, temporary state, and background job coordination. It becomes more useful as the chatbot grows beyond a simple request-response app. ### What is the best architecture for an AI chatbot MVP? A practical MVP architecture is one VPS running Nginx or Caddy, a backend API, PostgreSQL, Redis, and a worker process. This keeps infrastructure simple while still supporting real users, stored conversations, and background tasks. ### When should I split an AI chatbot across multiple VMs? Split the architecture when traffic grows, background jobs slow down the app, the database needs isolation, workers need independent scaling, or uptime requirements become more serious. A common next step is separate app, database, Redis, and worker VMs. ### How does Raff VM help with AI chatbot infrastructure? Raff VM gives teams a cloud server foundation for running AI chatbot backends, APIs, Redis, PostgreSQL, workers, Docker workloads, staging environments, and monitoring tools. It is a practical starting point for API-based AI apps that need reliable backend infrastructure without unnecessary cloud complexity. ## Conclusion AI chatbots may look like model-driven products, but real AI products still depend on infrastructure. For API-based chatbots, the model usually runs through an external provider. Your responsibility is the backend. That backend must handle users, sessions, prompts, context, database writes, Redis, queues, workers, API failures, rate limits, logs, security, and uptime. For many teams, a VPS is the right starting point. It gives enough control to build a real product without forcing the team into complex cloud architecture too early. Start with a clean VPS setup. Run the backend, database, Redis, and workers properly. Add monitoring, backups, security, and staging. Then split into multiple VMs or managed services when the workload proves it needs more structure. For builders creating AI chatbots, AI agents, SaaS copilots, internal AI tools, or document Q&A systems, Raff VM provides a simple cloud server foundation for the backend infrastructure that keeps the product running. The AI model may generate the answer. But your infrastructure makes the product reliable. --- ### Cloud Computing in 2026: What Small Teams Should Watch URL: https://rafftechnologies.com/blog/cloud-computing-in-2025-navigating-the-new-frontiers Published: 2025-06-30T00:00:00.000Z Description: Cloud Computing in 2026: What Small Teams Should Watch Cloud computing in 2026 is not only about AI data centers, hyperscaler spending, or the next big platform announcement. For small teams, startups, developers, and SMBs, the real cloud question is more practical: how do you get reliable infrastructure without buying more complexity than you can operate? At Raff Technologies, we see this every day. Most teams do not wake up asking for “cloud transformation.” They need a VM for an app, a database for a product, storage for files, a secure test environment, or a simple way to move faster without turning infrastructure into a full-time job. That is why the most important cloud trend in 2026 is not only bigger infrastructure. It is more focused infrastructure. The teams that win will not be the ones using every cloud service available. They will be the ones choosing the few services that directly help them ship, secure, automate, and scale. ## The Cloud Market Is Bigger, But Teams Need Simpler Decisions The cloud industry keeps expanding, but that does not mean every team needs a larger cloud footprint. This is the mistake many small teams make. They look at enterprise cloud adoption and assume they need the same architecture. They see AI infrastructure, multicloud diagrams, edge computing, Kubernetes, managed platforms, serverless, and automation tools — then they feel behind before they have even deployed their first useful workload. But small teams do not need to copy enterprise infrastructure. They need to understand what problem they are solving. A startup launching a SaaS app needs a different cloud model than a global enterprise running hundreds of workloads. A student learning Linux needs a different cloud model than a bank designing compliance-heavy systems. An SMB hosting an internal tool needs a different model than a hyperscaler training foundation models. The right question is not “What is everyone using?” The right question is: > **What is the smallest reliable cloud architecture that solves our current problem and still gives us room to grow?** That is the lens small teams should use in 2026. ## AI Is Making Infrastructure More Important, Not Less AI is changing cloud infrastructure, but not always in the way people expect. The loudest part of the AI cloud story is GPU clusters, model training, and massive data center investment. That matters, but it is not the whole story. For many small teams, AI creates a different need: more automation, more internal tools, more API-connected workflows, and more backend services that need reliable compute. AI tools still need somewhere to run. Automation agents need servers. Vector databases need storage. Internal dashboards need hosting. Webhooks need endpoints. MCP servers, workflow engines, and API bridges need secure environments. That means cloud VMs are not becoming less relevant. In many cases, they are becoming more relevant because they are the flexible base layer for AI-assisted development and automation. A [Raff Linux VM](/products/linux-vm) can host the practical side of AI workflows: automation services, backend APIs, internal tools, n8n instances, testing environments, model-adjacent services, and lightweight agent infrastructure. This is where the opportunity is for small teams. You do not need to build an AI data center to benefit from AI infrastructure. You need clean, secure, flexible compute that can run the tools around your AI workflows. ## Cost Control Will Matter More Than Cloud Access In 2026, cloud access is not the problem. Almost anyone can create an account and launch resources. The problem is cost control. Small teams need to know what they are paying for, why they are paying for it, and when to resize, stop, or replace a workload. Cloud waste usually starts quietly: one oversized server, one forgotten test environment, one storage volume nobody owns, one workload copied from production “just in case.” Large enterprises can sometimes absorb waste for a while. Small teams feel it quickly. That is why cost control should be treated as a product habit, not an accounting task. Every workload should have a reason, owner, size, and review point. For Raff users, that starts with choosing the right VM size instead of guessing. A workload that needs 2 GB RAM should not be deployed on a large machine because the team is afraid to make a decision. A database that needs consistent CPU should not be placed on the wrong plan because the team only looked at monthly price. If you are unsure where to start, use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) before deploying production workloads. If you are comparing predictable performance against lower-cost shared compute, read [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). Cloud cost control is not about choosing the cheapest plan. It is about choosing the plan that matches the workload. ## Simple Cloud Will Keep Winning for SMBs and Startups The more complex the cloud market becomes, the more valuable simple infrastructure becomes for small teams. This may sound counterintuitive, but it is true. Complexity has a cost. Every new service adds a learning curve, security model, billing model, and operational responsibility. Sometimes that complexity is worth it. Often, it is not. For many SMBs and startups, the best first cloud architecture is still simple: * One VM for the app * A database when needed * Backups and snapshots when the environment matters * Private networking when services need isolation * Object storage when files should not live on the app server * A load balancer when one app server is no longer enough That path is understandable. It gives the team a way to start small and grow only when the workload demands it. This is the reason Raff’s positioning is intentionally practical. We are not trying to make every small team buy cloud like an enterprise. We are trying to give them the core infrastructure they actually need first: VMs, storage, networking, backups, snapshots, and a path to scale. If this sounds familiar, read [Small Teams Need Simple Cloud, Not More Complexity](/blog/simple-cloud-for-small-teams). That article explains why small teams should avoid buying complexity before their workloads earn it. ## The VM Is Still the Most Understandable Cloud Building Block Every few years, someone says virtual machines are old news. Yet VMs keep remaining useful because they are understandable. A VM gives you a server. You know where the app runs. You know where logs live. You know which operating system is installed. You can SSH into it. You can install packages, configure services, monitor resources, resize when needed, and rebuild from a clean baseline. That clarity matters. For developers, VMs are useful because they behave like real infrastructure. For founders, they are useful because cost and ownership are easier to understand. For SMBs, they are useful because a VM maps directly to a business need: host this app, run this tool, test this service, support this client. Containers, managed platforms, and serverless all have their place. But in 2026, the VM is still one of the strongest starting points for teams that want control without unnecessary abstraction. That does not mean every workload should stay on one VM forever. It means one VM is often the right place to begin. When a workload grows, the team can resize vertically, split app and database roles, add workers, introduce caching, or move multiple app VMs behind a load balancer. Raff’s [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) explains that growth path in more detail. ## Automation Will Move From Nice-to-Have to Expected In 2026, automation is no longer only for large DevOps teams. Small teams increasingly expect infrastructure to support repeatable workflows. They want to provision environments faster, trigger tasks from APIs, connect tools, automate backups, and reduce manual work without hiring a full platform team. The key is to automate the right things. Bad automation makes bad decisions faster. Good automation turns a known, repeated action into a safer workflow. A practical small-team automation path looks like this: * Start with manual deployment until the workflow is understood * Document the steps * Automate provisioning or setup * Add monitoring and alerts * Use API keys carefully * Keep rollback simple * Review permissions regularly This is where cloud infrastructure and automation tools meet. A VM can host automation engines, internal tools, API bridges, and workflow systems. A platform API can help teams connect infrastructure actions to business workflows. If your team is thinking about cloud automation, read [Raff API Keys for Small-Team Automation](/learn/guides/raff-api-keys-automation-small-teams). For workflow automation specifically, Raff’s [n8n self-hosted automation guide](/learn/guides/n8n-self-hosted-workflow-automation-guide) is a useful companion. ## Data Will Need Better Separation In early-stage projects, teams often keep everything together: app, database, uploads, logs, backups, and background jobs. That can work for a while. But in 2026, small teams should become more disciplined about separating data from application compute. The reason is simple: applications can be rebuilt faster than data can be recovered. User uploads should not live forever on the app server if the product is growing. Databases should not be treated like disposable local files. Backups should not be an afterthought. Snapshots should not be confused with a full data strategy. As workloads mature, teams should ask: * Where does persistent data live? * Is the database separate from the app? * Are backups tested? * Are user uploads stored outside the app server? * Who can access production data? * Can the environment be rebuilt if the VM fails? * Does the team know the recovery process? This is where products such as managed databases, object storage, volumes, backups, and snapshots become important. The point is not to add complexity for its own sake. The point is to protect the parts of the system that matter most. For growing SaaS apps, the database is usually the first thing worth separating from the app server. Raff’s [Managed Database or VM Database](/learn/guides/managed-database-or-vm-database) guide explains when to use a managed database and when running your own database on a VM still makes sense. ## Security Will Be About Defaults and Discipline Security in 2026 will not only be about advanced tools. It will also be about whether teams consistently do the basics. For small teams, the most common security problems are rarely exotic. They are usually simple: * Public services that should be private * Weak SSH practices * Unpatched servers * Over-permissive firewall rules * Credentials stored carelessly * No backup testing * No clear ownership * Too much access for too many people * Test environments treated like production Good cloud security starts with defaults and discipline. A secure VM setup should include SSH keys, firewall rules, least-privilege access, regular updates, backups, and clear ownership. If the workload involves internal services, private networking should be considered early. If the app handles customer data, backup and recovery planning should not wait until after an incident. This is why Raff’s infrastructure topics connect together. VM sizing, private networking, backups, firewalls, and scaling are not separate concerns. They are all part of operating cloud systems responsibly. A useful starting point is [Cloud Firewall Rules Explained](/learn/guides/cloud-firewall-rules-explained), especially if your team is exposing services to the internet or connecting multiple VMs. ## Multicloud Is Not Automatically a Strategy Multicloud gets a lot of attention, but small teams should be careful with it. Using multiple cloud providers can reduce vendor dependency and improve resilience in some cases. It can also multiply complexity. Every provider adds separate networking, billing, IAM, monitoring, deployment, and support models. For a small team, multicloud should solve a real problem, not create a more impressive architecture diagram. Good reasons for multicloud include: * Regulatory or customer requirements * Geographic latency needs * Specific service availability * Disaster recovery planning * Avoiding dependency on one critical provider * Cost optimization for specific workloads Weak reasons include: * “Large companies do it” * “It sounds more resilient” * “We want optionality someday” * “It looks more enterprise” Most small teams should first build one clean, documented, secure cloud environment. Then they can add additional providers when the business need is clear. The same principle applies to every cloud trend: adopt what solves the current problem, not what makes the diagram look modern. ## What This Means for Small Teams If you are planning cloud infrastructure in 2026, keep your decision process practical. Start with the workload. Choose the simplest reliable architecture. Use VMs when you need control and clarity. Use managed services when they remove real operational burden. Separate persistent data from disposable compute. Measure before scaling. Automate only after the workflow is understood. Add complexity only when the workload earns it. That is not a conservative strategy. It is a focused strategy. Small teams do not win by imitating enterprise cloud architecture. They win by moving faster with infrastructure they can understand, secure, and afford. For Raff users, this usually means starting with a [Linux VM](/products/linux-vm) or [Raff VM](/products/raff-vm), comparing plans on the [pricing page](/pricing), then adding databases, object storage, private networking, backups, and load balancing only when the workload asks for them. ## Final Thoughts Cloud computing in 2026 will be shaped by AI, automation, data growth, edge use cases, and continued infrastructure expansion. But small teams should not let the size of the market distract them from the reality of their own workload. The future of cloud is not only bigger. It is more selective. The best teams will know when to use a VM, when to resize, when to split services, when to automate, when to choose managed infrastructure, and when to say no to complexity. That is the cloud strategy Raff Technologies cares about: practical infrastructure for teams that need to build, test, ship, and grow without turning cloud into a maze. Start simple. Measure honestly. Add complexity only when it creates real value. --- ### Raff Is Now a Microsoft SPLA Partner URL: https://rafftechnologies.com/blog/raff-microsoft-spla-partner Published: 2026-05-08T00:00:00.000Z Description: Raff Is Now a Microsoft SPLA Partner Raff Technologies is now a Microsoft SPLA Partner. For us, this is more than a licensing milestone. It is a trust milestone. Raff Technologies has always focused on making cloud infrastructure easier for developers, startups, freelancers, learners, small teams, and businesses that need practical computing power without unnecessary complexity. Becoming a Microsoft Service Provider License Agreement Partner strengthens that direction, especially for customers who need Windows VMs, hosted Microsoft software, or clearer licensing around Microsoft workloads. The Microsoft Services Provider License Agreement, usually called SPLA, is a licensing program that allows service providers to license eligible Microsoft products and provide hosted software services to customers. In practical terms, Raff LLC is now licensed to host Microsoft software through our SPLA agreement where applicable. That matters because infrastructure is not only about CPU, RAM, storage, and bandwidth. It is also about confidence. When a customer launches a Windows VM, they are not only choosing a server. They are trusting the provider behind it to operate responsibly, license properly, and support the workload in a way that makes business sense. That is the part we want to make clearer. ## Why This Matters Microsoft software is widely used in real businesses. Windows Server, Remote Desktop environments, Microsoft-based applications, business tools, internal systems, and legacy workloads are still part of how many organizations operate. Even as Linux, containers, and open-source infrastructure continue to grow, Windows workloads remain important for many teams. For cloud providers, that creates responsibility. It is not enough to simply say, “we offer Windows servers.” Customers should also know whether the provider has a proper path for Microsoft software licensing in hosted environments. That is why SPLA matters. SPLA gives service providers a licensing framework for offering hosted Microsoft software services to customers. Microsoft explains the program as a way for service providers and software companies to license eligible Microsoft products on a monthly basis during a three-year agreement term, so they can provide software services and hosted applications to end customers. For Raff, this directly supports our Windows VM direction. It allows us to speak more clearly about Microsoft software licensing through our SPLA agreement and gives customers another reason to trust the infrastructure they are building on. ## What We Can Now Say Clearly There are a few phrases we can now use confidently and responsibly: * Raff LLC is a Microsoft SPLA Partner. * Raff LLC is a Microsoft Service Provider License Agreement Partner. * Raff LLC is licensed to host Microsoft software through SPLA. * Microsoft software licensing is available through our SPLA agreement where applicable. * Raff can provide hosted Microsoft software services under our SPLA agreement. These statements are important because they are specific. They do not overclaim. They do not suggest that Raff is Microsoft, or that Microsoft is endorsing every Raff service. They simply explain the licensing relationship in a way customers can understand. That distinction matters. Trust is not built by using the biggest words possible. Trust is built by being precise. So we will be careful with the language. We will not describe Raff as a “Microsoft-certified cloud provider” or “Microsoft-endorsed hosting provider” unless that exact status is separately granted and documented. SPLA is already a meaningful trust signal on its own. We do not need to exaggerate it. The accurate message is strong enough: Raff LLC is a Microsoft SPLA Partner, licensed to provide hosted Microsoft software services through the Microsoft Services Provider License Agreement. ## Why We Took This Step One lesson I have learned while building Raff is that business customers do not only buy infrastructure. They buy confidence. A developer may start by comparing CPU, RAM, storage, and price. A founder may look at monthly cost and deployment speed. A small team may care about simplicity and support. But as soon as Microsoft workloads enter the conversation, licensing clarity becomes part of the decision. That is especially true for Windows VM customers. A Windows VM is often used for business-specific tasks: remote desktop access, Windows-based applications, legacy software, testing environments, development workflows, administration tools, and workloads that cannot easily move to Linux. In those cases, licensing cannot be treated as an afterthought. This is one reason we pursued SPLA. We want Raff to be a serious infrastructure provider, not just a place where someone can launch a server. Serious infrastructure includes performance, pricing, networking, backups, support, and licensing clarity. The Microsoft SPLA partnership helps us strengthen that foundation. It gives us a clearer framework for hosting eligible Microsoft software services and gives customers a cleaner answer when they ask, “How is Microsoft licensing handled?” That question deserves a real answer. Now we have one. ## What This Means for Windows VM Customers For customers using or evaluating [Raff Windows VMs](/products/windows-vm), this means Raff has a proper licensing path for hosted Microsoft software through SPLA where applicable. That is important for several types of users. A business running Windows-based applications may need a cloud environment that is both practical and properly licensed. A freelancer may need a Windows VM for client work, testing, or remote access. A small team may need Windows Server infrastructure without buying and maintaining physical hardware. A company may want hosted Microsoft software services without managing every licensing detail alone. In all of these cases, the provider matters. The server is only one part of the decision. The operating model behind the server matters too. With SPLA, Raff can support hosted Microsoft software licensing in a more structured way. That gives customers a clearer foundation when choosing Raff for Windows workloads. It also fits our broader product direction. We want Raff to make cloud infrastructure feel easier to understand without removing the serious parts that customers depend on. Licensing is one of those serious parts. ## Why Licensing Clarity Is a Product Feature Licensing may not sound like a product feature at first. But for business infrastructure, it absolutely is. A product feature is not only something visible in the dashboard. It is anything that helps the customer use the service with more confidence. Clear pricing is a product feature. Reliable backups are a product feature. Private networking is a product feature. Support is a product feature. And for Microsoft workloads, licensing clarity is a product feature. If a customer is unsure whether their Windows VM is properly licensed, that uncertainty affects the whole experience. It affects trust. It affects procurement. It affects whether a business feels comfortable putting real work on the platform. That is why this announcement matters. It is not only a badge. It is part of Raff becoming more mature as a cloud infrastructure provider. ## The Practical Customer Benefit The practical benefit is simple: customers evaluating Windows workloads on Raff can now see that Microsoft software licensing is handled through Raff LLC’s SPLA agreement where applicable. This is especially useful for customers who care about: * Windows Server hosting * Remote Desktop workloads * hosted Microsoft software services * business applications that require Microsoft environments * development or testing on Windows VMs * clearer licensing responsibility * infrastructure providers with stronger trust signals For some users, Linux will still be the natural starting point. Raff continues to support Linux VMs for development, self-hosting, automation, Docker, web hosting, and general cloud workloads. But for customers who need Windows, this is a different conversation. They need performance and simplicity, yes. They also need licensing confidence. That is where SPLA makes Raff stronger. ## How This Fits Raff’s Direction Raff’s positioning is simple: Fast. Simple. Reliable. The Microsoft SPLA partnership supports the “Reliable” part in a very practical way. Reliability is not only uptime. Reliability is also whether the provider is taking the right operational steps behind the scenes. A customer may never read the full licensing terms behind a Microsoft-hosted workload. But they still benefit when the provider has a structured licensing agreement in place. That is the kind of invisible work that makes infrastructure more trustworthy. From the outside, a VM may look like CPU, RAM, storage, and an operating system. From the inside, cloud infrastructure is a series of responsibilities. Hardware responsibility. Network responsibility. Backup responsibility. Security responsibility. Billing responsibility. Support responsibility. Licensing responsibility. The stronger we become in each of these areas, the stronger Raff becomes as a company. That is why this milestone matters to me. It is not just about being able to say we are a Microsoft SPLA Partner. It is about what that says regarding the kind of cloud provider we are trying to become. ## What This Does Not Mean It is also important to be clear about what this does not mean. This does not mean every Microsoft product is automatically included in every Raff service. It does not mean every workload has the same licensing requirements. It does not mean customers should ignore their own compliance, software, or contractual responsibilities. It does not mean Raff is claiming a separate Microsoft endorsement beyond the SPLA relationship. Microsoft licensing can be specific, and the right answer depends on the product, workload, deployment model, and customer scenario. That is why we will continue to be careful with language. The correct statement is that Raff LLC is licensed to provide hosted Microsoft software services through the Microsoft Services Provider License Agreement where applicable. For customers, the practical takeaway is this: If your workload involves Microsoft software, Raff now has a clearer licensing framework to support hosted services through SPLA. That is the trust signal. ## What This Means for You If you are evaluating a Windows VM provider, do not only compare price. Price matters, but it is not the whole decision. Ask whether the provider can clearly explain how Microsoft software licensing is handled. Ask whether the infrastructure gives you enough control. Ask whether backups, snapshots, networking, and support fit your workload. Ask whether the pricing model is understandable before you deploy. Ask whether the provider is serious enough for the work you plan to run. If you need a Windows environment for development, business applications, remote access, testing, or hosted Microsoft workloads, you can start with [Raff Windows VMs](/products/windows-vm). If you are still comparing operating systems or workload types, you can also review [Raff VM options](/products/raff-vm) and [Raff pricing](/pricing) before deciding. For Microsoft workloads specifically, the important update is this: Raff LLC is now a Microsoft SPLA Partner, licensed to host Microsoft software through our SPLA agreement where applicable. That gives us a stronger foundation for Windows VM customers and a clearer trust signal for businesses evaluating Raff. ## Final Thought Cloud infrastructure is built in layers. Some layers are visible: the dashboard, the VM, the operating system, the storage, the price. Other layers are less visible: licensing, operational responsibility, provider maturity, and the decisions made before the customer ever launches a server. Becoming a Microsoft SPLA Partner strengthens one of those less visible layers. It helps Raff serve Windows VM customers more responsibly. It gives business users a clearer answer around Microsoft software licensing. And it moves Raff one step further toward becoming the kind of infrastructure company we want to build. Fast. Simple. Reliable. And now, stronger for Microsoft-hosted workloads through SPLA. --- ### Cloud-Native Apps in 2026: What Small Teams Get Wrong URL: https://rafftechnologies.com/blog/cloud-native-best-practices-2026 Published: 2026-01-26T00:00:00.000Z Description: Cloud-Native Apps in 2026: What Small Teams Get Wrong Cloud-native apps in 2026 are not about using every modern infrastructure tool at once. They are about building applications that can be deployed, recovered, scaled, observed, and secured without turning the platform itself into the hardest part of the product. At Raff Technologies, this is the cloud-native lesson I care about most: small teams should not jump from one VM directly into Kubernetes, service meshes, and five observability tools because a diagram told them to. A healthy cloud-native path usually starts simpler: one clean VM, containerized workloads, repeatable deployment, basic monitoring, backups, firewall rules, and only then more advanced orchestration when the workload earns it. Cloud-native means designing applications to take advantage of cloud infrastructure: elastic compute, automation, isolation, repeatable deployment, resilient recovery, and observable systems. It does not mean every app needs microservices. It does not mean every team needs Kubernetes on day one. It means your infrastructure should help the application survive change. ## Cloud-Native Is a Discipline, Not a Tool List The biggest mistake in cloud-native engineering is treating it like a shopping list. Containers? Add them. Kubernetes? Add it. CI/CD? Add it. Observability? Add it. Service mesh? Add it. Infrastructure as Code? Add it. That approach creates complexity faster than it creates resilience. A cloud-native system is not better because it has more layers. It is better when those layers solve specific operational problems. If a team cannot explain why a tool exists, who owns it, and what happens when it fails, the tool is not helping yet. The practical question is: > What is the smallest cloud architecture that lets this application deploy safely, recover quickly, and grow without becoming fragile? That question keeps engineering honest. ## Start With the Runtime You Can Operate Before Kubernetes, before autoscaling, before multi-region diagrams, start with a runtime your team can actually operate. For many small teams, that runtime is still a VM. A [Raff Linux VM](/products/linux-vm) gives you a clean server environment where you can install the application runtime, run Docker, configure Nginx, set up firewall rules, manage logs, and understand exactly what is happening. That clarity matters. A VM is not the opposite of cloud-native. A VM can be the first cloud-native building block if it is treated correctly: documented, reproducible, secured, monitored, backed up, and sized for the workload. The problem is not “using a VM.” The problem is using a VM like an undocumented box that nobody can rebuild. A cloud-native VM should have: * A clear role * A documented setup path * Firewall rules * SSH key-based access * Backups or snapshots * Monitoring and logs * A known deployment process * A plan for resizing or splitting later If those basics are missing, Kubernetes will not magically fix the environment. ## Containers Are Useful Because They Reduce Drift Containers are one of the most practical cloud-native tools because they reduce environment drift. A container packages the application with its runtime, dependencies, and configuration expectations. That makes it easier to run the same workload across development, staging, and production without relying on every server being manually configured the same way. For developers, containers solve a real problem: “it worked on my machine” becomes less common when the application runs in a defined container image. But containers are not enough by themselves. You still need to think about: * Persistent storage * Environment variables * Secrets * Image updates * Logs * Networking * Health checks * Backups * Resource usage * Deployment rollback Containers make applications more portable. They do not remove operational responsibility. If your team is still early, learn containers on one VM before jumping into clusters. Start with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), then move toward Docker Compose or a more structured deployment model. ## Kubernetes Should Solve a Real Problem Kubernetes is powerful, but it should not be the default answer for every small application. Use Kubernetes when you need orchestration: multiple services, multiple replicas, rolling updates, self-healing behavior, service discovery, resource scheduling, and standardized deployment across a cluster. Do not use Kubernetes only because the word “cloud-native” appears in the same sentence. A single app with one database and predictable traffic may run better on a simple VM or a small multi-VM architecture. A startup that has not validated its workload yet should probably not start by operating a cluster. A small team without DevOps capacity should be careful before adding a control plane, ingress layer, manifests, resource limits, cluster networking, and upgrade procedures. The right question is not “Is Kubernetes modern?” It is: > Is container orchestration currently one of our real bottlenecks? If the answer is no, start simpler. For a deeper decision path, read [Kubernetes for Developers: When to Use K8s vs VMs](/blog/kubernetes-for-developers-k8s-vs-vms). The short version is simple: Kubernetes is valuable when manual container operations become more expensive than running a cluster. ## Build for Failure, But Keep Failure Modes Visible Cloud-native systems should assume failure. Servers fail. Containers crash. Deployments break. Networks drop. Dependencies time out. Databases slow down. Disk fills up. Human mistakes happen. The goal is not to pretend failure can be avoided. The goal is to make failure smaller, more visible, and easier to recover from. A practical resilience plan includes: * Health checks * Graceful shutdowns * Retry limits * Timeouts * Queue-based processing for slow work * Backups * Snapshots before risky changes * Monitoring and alerting * Clear rollback steps * Separation between app and data The most important part is visibility. If your application fails and the team cannot quickly answer what changed, where it failed, and how to roll back, the system is not resilient yet. Simple infrastructure helps here. When the architecture is understandable, failure is easier to diagnose. When the architecture is overcomplicated, failure hides inside layers. ## Separate App, Database, Worker, and Cache When It Matters Cloud-native does not always mean microservices. Sometimes the first meaningful improvement is simply separating infrastructure roles. A common early setup puts everything on one VM: * App * Database * Background workers * Cache * Logs * Uploads * Cron jobs That is fine for a prototype. It becomes risky when the workload grows. The first role to separate is usually the database. Application compute is replaceable. Production data needs stronger protection. After that, background workers often deserve their own VM because jobs can spike CPU, memory, or database load without directly slowing web requests. A practical cloud-native progression looks like this: | Stage | Architecture | Why It Helps | |---|---|---| | Early app | One VM | Simple, low-cost, fast to understand | | First production step | App VM + database | Protects persistent data | | Growing workload | App VM + database + worker VM | Stops background jobs from hurting web traffic | | Scaling app | Multiple app VMs + load balancer | Adds capacity and better availability | | Advanced orchestration | Kubernetes | Standardizes container operations across a cluster | That path is boring in the right way. It adds complexity only when there is a reason. If your app is starting to outgrow one server, use [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) to decide whether to split the database, workers, cache, or app servers before moving to Kubernetes. ## CI/CD Should Make Deployments Boring Cloud-native teams do not need dramatic deployments. A good deployment should be boring: repeatable, observable, reversible, and understood by the team. CI/CD helps because it turns the build-test-deploy path into a controlled workflow. But a pipeline should encode a process the team already understands. If the deployment process is unclear, automation will only hide the confusion. A practical small-team CI/CD path looks like this: * Build the application * Run tests * Build the container image * Deploy to staging * Verify the app * Create or confirm a recovery point * Deploy to production * Monitor logs and health * Roll back if needed The point is not to deploy 50 times a day. The point is to make each deployment safer. For small teams, a VM-based DevOps lifecycle can be enough for a long time. Raff’s [DevOps Lifecycle on VMs](/blog/devops-lifecycle-on-vms) explains how build, test, staging, deployment, and recovery can work without buying a heavy platform stack too early. ## Observability Should Answer Real Questions Monitoring tells you whether something is up. Observability helps you understand why something is behaving the way it is. For cloud-native apps, you need enough visibility to answer practical questions: * Is the app slow? * Is the database the bottleneck? * Are background jobs piling up? * Did the latest deployment increase errors? * Is memory leaking? * Are users affected? * Which service changed? * Can we roll back safely? Start simple. A small team does not need an enterprise observability stack on day one. It needs useful logs, basic metrics, uptime checks, deployment notes, and alerts tied to real user impact. As the system grows, add more: * Centralized logging * Metrics dashboards * Error tracking * Request tracing * Queue depth monitoring * Database performance metrics * Deployment annotations * Alert routing The rule is simple: observe what helps you make decisions. Do not collect data nobody uses. ## Security Belongs in the First Deployment Security should not be a later phase. The first deployment should already include the basics: SSH keys, firewall rules, least-privilege access, updates, backups, and clear ownership. A cloud-native app usually has more moving parts than a traditional single-server app. More services mean more network paths, credentials, ports, images, and dependencies. That makes early security discipline more important, not less. Start with these controls: * Use SSH keys instead of weak password access * Keep only necessary ports open * Put private services on private networks where possible * Use separate credentials for each service * Avoid storing secrets in source code * Patch the operating system and packages * Limit admin access * Back up important data * Review public exposure after every architecture change Firewall design is especially important. If a database, cache, worker, or internal API does not need to be public, do not make it public. Raff’s [Cloud Firewall Rules Explained](/learn/guides/cloud-firewall-rules-explained) is a good companion piece because cloud-native security starts with basic network boundaries before advanced tools matter. ## Recovery Is the Part Teams Ignore Until It Hurts A cloud-native app without recovery planning is not resilient. Backups, snapshots, rollback steps, and restore testing are part of the application architecture. They are not administrative extras. A good recovery plan answers: * What data must be protected? * How often is it backed up? * Where are backups stored? * Who can restore them? * How long does restore take? * Have we tested the restore process? * What happens if the latest deployment breaks production? * Can we roll back without losing data? Snapshots are useful before risky infrastructure changes. Backups are necessary for long-term recovery. They solve related but different problems. If your team has not tested recovery, do not call the system resilient yet. For a practical framework, read [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies). Build recovery into the lifecycle before a real incident forces the lesson. ## Cost Is a Cloud-Native Design Constraint Cloud-native architecture should scale, but scaling without cost discipline creates waste. Small teams should treat cost as an engineering signal. If a workload is oversized, forgotten, duplicated, or running without an owner, the system is not well designed. Cost-aware cloud-native practices include: * Right-sizing VMs * Shutting down temporary environments * Separating workloads only when needed * Choosing dedicated CPU only when consistency matters * Avoiding Kubernetes before orchestration is necessary * Reviewing backups, volumes, and idle resources * Using staging environments intentionally * Measuring before scaling Raff’s [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) is useful here because many cost problems begin with guessing. Start with the workload, choose the smallest reasonable plan, measure, then resize when there is evidence. That is better than overprovisioning because the team is afraid to make a decision. ## Raff’s Practical Cloud-Native Path The Raff approach to cloud-native infrastructure is simple: start with usable building blocks, then add complexity only when the workload asks for it. A practical path on Raff looks like this: * Start with a Linux VM * Deploy the app * Containerize when consistency matters * Add backups and snapshots when the environment matters * Use firewall rules and private networking to reduce exposure * Split database and worker roles when one VM becomes too crowded * Add load balancing when one app server is not enough * Consider Kubernetes when orchestration becomes the real problem That path is not as flashy as starting with a full platform stack. But it is healthier for small teams because every layer has a reason. Cloud-native should make your system easier to change and recover. If it only makes the diagram look more modern, something is wrong. ## What This Means for You If you are building cloud-native apps in 2026, do not start with the tool. Start with the pressure. Are deployments risky? Improve CI/CD. Are environments inconsistent? Use containers. Are workloads competing on one VM? Split roles. Is one app server overloaded? Scale horizontally. Are services hard to debug? Improve observability. Is data at risk? Fix backups and recovery. Is the system too exposed? Tighten firewall rules and private networking. Are container operations becoming painful? Then evaluate Kubernetes. This is how you avoid cloud-native chaos. Start simple, measure honestly, and add infrastructure only when it solves a real operational problem. ## Final Thoughts Cloud-native best practices in 2026 are not about adopting every modern infrastructure trend. They are about building systems that are easier to deploy, easier to recover, easier to secure, and easier to scale without overwhelming the team operating them. For many teams, the right first step is still a clean VM, Docker, clear firewall rules, backups, and a boring deployment process. Kubernetes, advanced automation, and multi-service platforms come later when the workload proves they are worth it. That is the cloud-native path I trust: simple first, resilient always, complex only when necessary. Start with a [Raff Linux VM](/products/linux-vm), compare plans on the [pricing page](/pricing), and build the smallest reliable architecture your application actually needs. --- ### Why Backup Tools Matter More Than Backup Promises URL: https://rafftechnologies.com/blog/why-backup-tools-matter-more-than-backup-promises Published: 2026-05-03T00:00:00.000Z Description: Why Backup Tools Matter More Than Backup Promises Backup tools matter more than backup promises because recovery is not a slogan — it is an operational path that either works under pressure or does not. At Raff Technologies, we think about backups less as a checkbox and more as a chain of tools, decisions, and restore habits that must survive the worst possible moment: the moment when a server is already broken, a deployment has already gone wrong, or a database has already been damaged. The promise is usually easy to write. “Daily backups included.” “Your data is safe.” “Disaster recovery ready.” Those phrases look clean on a pricing page, but they do not answer the question that matters: can you actually get back to a working state when something fails? That is why I care more about the tools behind the promise. A backup strategy is not one feature. It is a set of recovery paths: snapshots for fast rollback, file-level backups for selective recovery, database dumps for application state, object storage for off-server copies, and restore tests to prove the whole thing is more than decoration. ## A Backup Promise Is Not a Recovery Plan A backup promise tells you that something is being copied. A recovery plan tells you what can be restored, where it can be restored, how long it should take, and how much data you may lose. That distinction sounds simple, but it is where a lot of teams get into trouble. They buy or configure “backup” and assume the job is done. Then the first serious incident arrives and they discover the backup is too old, too incomplete, stored on the same machine, missing database consistency, or impossible to restore without guessing. This is why we publish recovery-focused guides like [Understanding Cloud Server Backups: RPO, RTO, and Snapshots](/learn/guides/cloud-server-backup-rpo-rto-snapshots). RPO and RTO are not enterprise jargon. They are practical questions every server owner should answer. How much data can you afford to lose? How quickly do you need the system back? If you cannot answer those two questions, the backup promise is still vague. It may be technically true that a backup exists, but you do not yet know whether it solves your actual failure scenario. ## Tools Reveal What the Promise Really Means The tool you choose reveals the kind of failure you are preparing for. A VM snapshot helps when you need to roll back an entire server quickly. That is useful before risky upgrades, package changes, firewall edits, or application deployments. But a snapshot is not the same as a long-term backup strategy, because it captures a point-in-time state of the machine rather than giving you clean, application-aware recovery forever. That is why [Cloud Snapshots vs Backups: What’s the Difference?](/learn/guides/snapshots-vs-backups-cloud-server) exists as a separate guide. We do not want users to treat snapshots and backups as interchangeable words. They are different tools for different types of pain. File-level backups solve a different problem. If a user deletes an upload directory, a configuration file, or a project folder, you may not want to roll back the entire VM. You may only want the missing files. That is where tools like `rsync`, `tar`, and scheduled scripts are still useful. They are boring, predictable, and easy to inspect. Database backups solve another problem again. A database is not just a folder of files you can copy casually while writes are happening. PostgreSQL, MySQL, and MariaDB need backup methods that respect consistency. For databases, a “backup” that cannot restore a valid database is not a backup. It is just a false sense of comfort. The promise sounds the same in all three cases: “we have backups.” The tools tell the truth. ## The Dangerous Backup Is the One Stored Too Close to the Failure One of the most common mistakes we see in small infrastructure setups is storing the backup too close to the thing it protects. A backup folder on the same VM is better than nothing, but it does not protect you from enough failure modes. If the VM disk becomes corrupted, credentials are compromised, a bad script deletes too much, or the server needs to be rebuilt cleanly, a local-only backup may disappear with the incident. That is why off-server storage matters. A stronger backup design moves recovery data away from the main server path. It does not necessarily need to be complicated, but it does need separation. This is one reason [S3-compatible object storage](/learn/guides/s3-compatible-object-storage-use-cases-for-developers) is so useful in real infrastructure design. Object storage gives you a clean place for backups, database dumps, logs, exports, and application files that should not live forever on the VM disk. It separates compute from durable file storage. On Raff, that separation is deliberate. A [Linux VM](/products/linux-vm) should run the application. VM disk should hold the operating system and runtime state. [Object storage](/products/object-storage) should hold data that benefits from being outside the server lifecycle. When those responsibilities are mixed together, backup design becomes harder to reason about. ## Restore Testing Is Where Backup Marketing Ends The real test of a backup tool is not whether it produces files. The real test is whether you can restore those files into a working system. This is where backup promises often collapse. A dashboard says the job completed. A folder contains archives. A bucket contains objects. But no one has restored the database, checked the application, validated permissions, confirmed service startup, or measured how long the process takes. A backup that has never been restored is only a backup candidate. That is why I like simple restore drills. Pick a clean target. Restore the files. Import the database. Start the application. Check logs. Confirm users can reach the service. Write down what failed, then fix the backup process so the next restore is less dramatic. This is not glamorous work. It does not create a shiny feature announcement. But it is the difference between “we probably have backups” and “we know exactly how recovery works.” If you want a practical example, our tutorial on [automating backups with cron and rsync on Ubuntu 24.04](/learn/tutorials/automate-backups-cron-rsync-ubuntu-24-04) does not stop at scheduling a script. It also includes retention and restore thinking because the job is not finished when the archive is created. The job is finished when you can use it. ## The Right Tool Depends on the Failure No single backup tool protects against everything. A snapshot is excellent before an upgrade. It gives you a fast rollback path if the server state changes badly. But if the application writes bad data into the database and the snapshot happens after the corruption, the snapshot faithfully preserves the broken state. A file backup is useful when you need a specific directory or configuration file. But it may not capture a live database safely unless you dump the database properly first. A database dump is essential for application recovery. But it does not restore the whole server, firewall rules, system packages, Nginx configuration, TLS certificates, uploads, and background workers by itself. Object storage is excellent for keeping backup data away from the VM. But object storage is not a restore plan by itself. You still need naming conventions, retention, credentials, lifecycle rules, and restore documentation. Replication is useful for availability. But replication is not a replacement for backups because it can replicate bad changes too. This is why our guide on [PostgreSQL replication vs backups vs snapshots](/learn/guides/postgresql-replication-vs-backups-vs-snapshots) separates the failure classes clearly: replication helps you stay online, backups help you go back, and snapshots help you roll back infrastructure quickly. The wrong question is “which backup tool is best?” The better question is “which failure am I trying to survive?” ## Backup Tools Should Create Operational Options A good backup system gives you options when something goes wrong. You should be able to roll back the whole VM when the server state is the problem. You should be able to restore one folder when a file-level mistake is the problem. You should be able to restore a database when application state is the problem. You should be able to rebuild on a clean VM when the original server is no longer trustworthy. That last point matters. In a serious incident, restoring onto the same machine is not always the safest choice. If credentials were exposed, packages were modified, or unknown changes happened on the server, a clean rebuild may be better. In that case, the backup tool must support recovery away from the original machine. This is where object storage, documented restore steps, and infrastructure discipline work together. You can launch a new VM, pull clean backup data, restore the application, and cut traffic over once the result is verified. The backup tool is not just preserving history. It is creating a route out of chaos. That is also why we built Raff’s platform around separate primitives instead of pretending one checkbox solves recovery. Snapshots, automated backups, object storage, block storage, web console access, and private networking all solve different operational problems. The job of the platform is to make those tools available. The job of the operator is to combine them honestly. ## Promises Hide Trade-Offs. Tools Expose Them. Every backup decision has a trade-off. Frequent backups reduce data loss but increase storage usage. Long retention gives more recovery history but costs more and requires better organization. Snapshots restore quickly but are not a full substitute for independent backups. Database dumps are portable but must be scheduled and secured properly. Object storage is durable and flexible, but permissions and lifecycle rules need care. A vague promise hides those trade-offs. A real toolchain exposes them so you can make better decisions. This matters for small teams because they usually do not have a dedicated recovery engineer. The developer who deploys the app is often the same person who has to recover it. The founder who approves the cloud bill may also be the person explaining downtime to a customer. In that environment, backup design must be understandable. A simple backup plan that the team can restore under pressure is better than an impressive-looking plan nobody understands. ## A Practical Backup Stack for Small Teams For many small teams, a practical backup stack does not need to be complicated. Start with snapshots before risky infrastructure changes. Add automated VM backups for broad rollback coverage. Use database-native dumps for application state. Store copies outside the VM, ideally in object storage. Document the restore process. Then test it on a clean machine before the first real incident forces you to learn under pressure. That structure gives you several recovery paths: * Roll back quickly if a deployment breaks the server. * Restore a database if application state is damaged. * Recover specific files if something is deleted. * Rebuild cleanly if the original VM should not be trusted. * Keep backup data outside the server that failed. If you already use Raff Object Storage, the [AWS CLI tutorial for Raff S3-compatible storage](/learn/tutorials/raff-s3-object-storage-aws-cli) is a useful next step because it shows how to create buckets, upload files, sync directories, and generate pre-signed URLs. Once you can move data in and out of object storage reliably, you can build better backup workflows around it. The goal is not to make backups complicated. The goal is to make recovery less mysterious. ## What This Means for You If you are running production workloads, stop evaluating backup by the promise and start evaluating it by the restore path. Ask these questions: * What exact tool creates the backup? * What data does it include? * What data does it miss? * Where is the backup stored? * Can the backup survive the original VM failing? * Who has access to restore it? * How long would recovery take? * When was the last restore test? * What would we rebuild first if the server disappeared? Those questions are uncomfortable in a useful way. They turn backup from a marketing phrase into an operating practice. If you are just starting, begin with [Cloud Server Backup Strategies: Snapshots, RPO, and Recovery Planning](/learn/guides/cloud-server-backup-rpo-rto-snapshots). Then read [Cloud Snapshots vs Backups: What’s the Difference?](/learn/guides/snapshots-vs-backups-cloud-server). If you want a practical implementation path, follow [Automate Server Backups with Cron and Rsync on Ubuntu 24.04](/learn/tutorials/automate-backups-cron-rsync-ubuntu-24-04), then move off-server copies into [Raff Object Storage](/products/object-storage). Backup tools matter because incidents do not care about promises. They only care whether your recovery path works. At Raff, that is the standard we want our own infrastructure content to push toward: fewer vague claims, more usable tools, and restore processes that can survive the day they are actually needed. --- ### Kubernetes for Developers: When to Use K8s vs VMs URL: https://rafftechnologies.com/blog/kubernetes-for-developers-k8s-vs-vms Published: 2026-01-20T00:00:00.000Z Description: Kubernetes for Developers: When to Use K8s vs VMs Kubernetes is useful when your application has outgrown “one container on one server” and you need a reliable way to deploy, scale, update, and recover containerized workloads across multiple machines. For developers, the important question is not “Should I learn Kubernetes?” The important question is “When does Kubernetes solve a real infrastructure problem?” At Raff Technologies, we think Kubernetes should be treated as a serious operations layer, not a badge of technical maturity. A single VM, Docker Compose, or a small multi-VM setup is often the right first step. Kubernetes becomes valuable when the cost of managing containers manually becomes higher than the cost of running a cluster. Kubernetes, often shortened to K8s, is an open-source platform for managing containerized applications. It helps teams declare how an application should run, then works continuously to keep the system close to that desired state. That makes it powerful — but also easy to overuse too early. ## Kubernetes Solves Container Operations, Not Every Hosting Problem Kubernetes exists because containers are easy to start but harder to operate at scale. Running one Docker container on one VM is simple. Running dozens of containers across multiple machines, with rolling updates, service discovery, restarts, traffic routing, resource limits, secrets, and health checks, is a different problem. That is the problem Kubernetes was built to solve. Kubernetes helps answer operational questions like: * Where should this container run? * What happens if the container crashes? * How many replicas should exist? * How do we update without replacing everything manually? * How does traffic reach the right workload? * How do workloads discover each other? * How do we separate configuration from application code? * How do we scale a service without rebuilding the whole system? If those questions are not painful yet, Kubernetes may be premature. The first lesson for developers is simple: Kubernetes is not the first step in cloud infrastructure. It is the step you take when container operations become complex enough to justify an orchestration layer. ## The Developer Mental Model Think of Kubernetes as a control system for applications. You describe the desired state. Kubernetes tries to make the actual state match it. If you say, “run three replicas of this API,” Kubernetes schedules Pods across available nodes. If one Pod fails, Kubernetes can replace it. If you update the image version, Kubernetes can roll out the change gradually. If traffic needs a stable endpoint, Kubernetes uses a Service to route requests to the right Pods. This desired-state model is the core idea. A developer does not usually need to understand every Kubernetes internal component on day one. But they do need to understand the main objects they will work with. ## The Core Kubernetes Objects Developers Should Know Kubernetes has many concepts, but the beginner path should start with a few. | Concept | What It Means | Why Developers Care | |---|---|---| | Cluster | The full Kubernetes environment | This is where your workloads run | | Node | A machine inside the cluster | Nodes provide CPU, RAM, storage, and networking | | Pod | The smallest deployable unit | Your containers run inside Pods | | Deployment | A controller for running and updating Pods | This is how you run app replicas and rollouts | | Service | A stable network endpoint for Pods | This is how traffic reaches changing workloads | | Ingress | HTTP routing into the cluster | This is often how web apps become reachable | | ConfigMap | Non-secret configuration | Keeps config separate from container images | | Secret | Sensitive configuration | Stores credentials and tokens, but still needs care | | Namespace | Logical separation inside a cluster | Helps divide environments, teams, or workloads | You do not need to memorize the entire ecosystem before deploying your first application. Learn the objects that match the first workload: Deployment, Service, ConfigMap, Secret, and Ingress. That is enough to understand the basic Kubernetes loop. ## Kubernetes vs Docker Docker and Kubernetes solve different problems. Docker helps you package and run containers. Kubernetes helps you operate containers across a cluster. A developer can use Docker without Kubernetes. In fact, that is often the right starting point. Build the container. Run it locally. Deploy it on a VM. Understand logs, environment variables, volumes, networking, and image updates. Only after that should Kubernetes enter the picture. If you do not understand containers yet, Kubernetes will feel like a maze. If you understand containers first, Kubernetes becomes easier because you know what is being orchestrated. For Raff users, the practical path is usually: * Learn Linux basics * Learn Docker * Deploy one container on a VM * Use Docker Compose for a small stack * Split workloads if needed * Move to Kubernetes when orchestration becomes the problem If you are still at the Docker stage, start with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) before jumping into cluster concepts. ## When a VM Is Enough A VM is enough when your application is small, understandable, and easy to operate without orchestration. Use a VM when: * You have one app or a small stack * Traffic is predictable * Downtime is acceptable or easy to manage * One deployment path is enough * Docker Compose solves the workload cleanly * You do not need multiple replicas across nodes * You do not have a platform team * You want low operational overhead A [Raff Linux VM](/products/linux-vm) is often a better starting point than Kubernetes for early apps because it gives you full control without the cluster overhead. You can install Docker, run the app, configure Nginx, add a database, monitor logs, and understand the full system. There is nothing wrong with this. In fact, one of the mistakes I see teams make is moving to Kubernetes before they have a workload that deserves it. They add a control plane, manifests, ingress rules, resource requests, cluster networking, persistent volume decisions, and monitoring complexity before one VM has become a real bottleneck. That is not engineering maturity. That is premature complexity. ## When Kubernetes Starts to Make Sense Kubernetes starts to make sense when you need the same operational behavior across multiple containers, machines, environments, or teams. Use Kubernetes when: * You run multiple services that need independent scaling * You need rolling deployments across replicas * You need self-healing behavior for failed workloads * You need standardized deployment patterns * You have multiple environments with similar architecture * You need service discovery between internal components * You need resource requests and limits per workload * You need platform-level consistency across teams * You are already operating enough containers that manual management is painful A useful rule: Kubernetes is worth considering when the cost of not having orchestration becomes visible. That cost might appear as deployment risk, inconsistent environments, slow rollouts, poor failure recovery, manual scaling, or too many one-off server scripts. If you are not feeling those problems, do not force Kubernetes just because the industry talks about it. ## Kubernetes Is Not the Same as Microservices Kubernetes and microservices often appear together, but they are not the same thing. You can run a monolith on Kubernetes. You can run microservices without Kubernetes. You can run a modular monolith on VMs for a long time before a cluster becomes useful. This distinction matters because many teams confuse application architecture with infrastructure architecture. A small team should not split its codebase into microservices just because it wants to learn Kubernetes. That usually creates more problems than it solves. Kubernetes helps operate workloads. It does not automatically make a bad service boundary good. It does not fix unclear ownership. It does not remove the need for observability, security, database planning, or deployment discipline. If your team is still deciding whether to split the application itself, read [Monolith vs Microservices for Small Teams](/learn/guides/monolith-vs-microservices-small-teams) before treating Kubernetes as the answer. ## The Cost of Kubernetes Is Mostly Operational Kubernetes has infrastructure cost, but the bigger cost is usually operational. A cluster needs: * Cluster upgrades * Node upgrades * Networking decisions * Ingress configuration * Persistent storage planning * Resource requests and limits * Secrets management * Monitoring and alerting * Image registry workflow * RBAC and access control * Backup and recovery planning * Troubleshooting skills This is why I do not recommend Kubernetes as the default for every small team. A simple VM has fewer moving parts. A multi-VM architecture has more moving parts, but still less than a full cluster. Kubernetes becomes valuable when the workload needs orchestration badly enough to justify that operating surface. If your app is still early, the better investment may be right-sizing the VM, splitting the database, separating workers, or adding a load balancer before adopting Kubernetes. For that decision path, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) and [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud). ## What Developers Should Learn First Developers should learn Kubernetes in layers. Do not start with Helm, operators, service meshes, admission controllers, and cluster autoscaling. Those are useful later, but they are not the first lesson. Start with this sequence: 1. Containers 2. Images 3. Pods 4. Deployments 5. Services 6. ConfigMaps 7. Secrets 8. Ingress 9. Resource requests and limits 10. Logs and rollout debugging That sequence teaches you how an app actually lives inside Kubernetes. The first useful goal is not “master Kubernetes.” The first useful goal is simpler: deploy one containerized app, expose it safely, update it, roll it back, and understand what happened. That is enough to make the platform real. ## A Practical Learning Path Here is the learning path I would recommend to a developer. First, containerize a small app. Use a basic API or web service you understand. Do not start with a complicated production application. Second, run the app with Docker locally. Confirm you understand the image, ports, environment variables, and logs. Third, deploy the same app to a VM. This teaches the difference between local development and real server operation. Fourth, run the app with Docker Compose if it needs a database or cache. This teaches multi-container thinking without a cluster. Fifth, deploy the same app to a local Kubernetes environment such as Kind or Minikube. Now you can compare the Kubernetes model against the Docker model. Sixth, learn Deployments and Services. These are the objects you will touch constantly. Seventh, learn ConfigMaps and Secrets. Configuration management becomes important quickly. Eighth, learn Ingress and TLS. Most real web apps need a safe route into the cluster. Ninth, learn resource requests and limits. This is where Kubernetes starts becoming an operations tool instead of a deployment toy. Tenth, learn how to debug. Use `kubectl get`, `kubectl describe`, logs, events, rollout status, and basic node inspection. That path keeps Kubernetes practical. ## Where Raff Fits Today Raff fits the Kubernetes learning path in two ways. First, Raff VMs are a practical foundation for learning the container and server skills that come before Kubernetes. You can deploy Ubuntu, install Docker, run a small app, test Docker Compose, build a staging environment, and understand the operations baseline before moving into clusters. Second, Raff’s Kubernetes product path is planned around managed container orchestration. The current Kubernetes product page lists a managed control plane, node and pod autoscaling, one-click cluster provisioning, monitoring, security updates, Helm support, operators, and CI/CD integration as expected capabilities. That matters because managed Kubernetes should remove part of the operational burden, especially around the control plane. But developers still need to understand workloads, resources, networking, and deployment behavior. Managed Kubernetes does not remove the need to understand Kubernetes. It removes some of the work required to operate the cluster infrastructure. Until the Kubernetes product is generally available, the most practical Raff path is: * Learn containers on a Raff VM * Run Docker and Docker Compose on Linux * Understand VM sizing and networking * Build small workloads first * Move to Kubernetes when orchestration is the problem That path is healthier than skipping straight to clusters. ## Common Kubernetes Mistakes Developers Make The first mistake is learning Kubernetes before learning containers. If Docker concepts are not clear, Kubernetes will feel unnecessarily difficult. The second mistake is using Kubernetes for one small app that would run perfectly well on a VM. That adds operational overhead without a real payoff. The third mistake is ignoring resource requests and limits. Kubernetes scheduling depends on resource planning. If you never define CPU and memory expectations, the cluster cannot make good placement decisions. The fourth mistake is treating Secrets as a complete security solution. Kubernetes Secrets are part of configuration management, not a full security model. Access control, encryption, network policy, and credential hygiene still matter. The fifth mistake is exposing too much. Services, ingress rules, dashboards, and admin endpoints should be reviewed carefully. Not every internal tool belongs on the public internet. The sixth mistake is skipping observability. If you cannot inspect Pods, logs, events, rollouts, and resource usage, you cannot operate Kubernetes safely. The seventh mistake is assuming Kubernetes fixes application architecture. It does not. If the app has poor boundaries, bad configuration, or fragile deployment behavior, Kubernetes may only make those problems more visible. ## Kubernetes and Security Kubernetes security starts with the same principle as cloud security generally: reduce unnecessary access. A secure Kubernetes setup should consider: * Who can access the cluster * Which users can deploy workloads * Which namespaces separate environments * Which services are public * Which secrets each workload can read * Which images are allowed * How updates are handled * How logs and events are monitored * How network traffic is restricted * How recovery works if a deployment breaks Kubernetes gives you powerful controls, but it also gives you many ways to misconfigure access. For developers, the most important habit is least privilege. A workload should have only the permissions, network access, and credentials it needs. A development namespace should not have production-level privileges. A public ingress should not expose internal dashboards. If your team is still building cloud security fundamentals, start with [Cloud Firewall Rules Explained](/learn/guides/cloud-firewall-rules-explained) and [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals) before adding cluster complexity. ## What This Means for Developers If you are a developer, learn Kubernetes because it teaches how modern cloud-native systems are operated. But do not confuse learning Kubernetes with needing Kubernetes for every workload. Start with Docker. Deploy to a VM. Understand Linux, networking, logs, environment variables, services, storage, and security. Then learn Kubernetes as the next layer. This approach makes you a better engineer because you understand what Kubernetes is abstracting. If you skip the lower layers, Kubernetes becomes a collection of YAML files you copy without understanding. If you learn the lower layers first, Kubernetes becomes a tool you can reason about. That is the difference between “using Kubernetes” and operating it responsibly. ## Final Thoughts Kubernetes matters because container operations eventually become difficult without orchestration. It helps teams deploy, update, scale, and recover workloads across clusters in a more consistent way. But Kubernetes is not the right starting point for every developer or every team. A VM is still the right starting point for many applications. Docker Compose is still enough for many small stacks. Multi-VM architecture can solve many growth problems before a cluster is necessary. The best engineering decision is not to adopt Kubernetes early. It is to adopt Kubernetes when the workload has earned it. Start with a [Raff Linux VM](/products/linux-vm), learn containers with [Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), understand when to split infrastructure with [Single VM vs Multi-VM Architecture](/learn/guides/single-vm-vs-multi-vm-saas-architecture), and follow the [Raff Kubernetes product path](/products/kubernetes) when your workload needs real orchestration. --- ### Ubuntu for Cloud VMs: Why Developers Still Choose It (2026) URL: https://rafftechnologies.com/blog/why-developers-still-love-ubuntu-a-deep-dive-into-the-linux-powerhouse Published: 2025-07-18T00:00:00.000Z Description: Ubuntu for Cloud VMs: Why Developers Still Choose It (2026) Ubuntu is still one of the safest default choices for cloud VMs in 2026 because it gives developers a stable Linux base, a huge package ecosystem, strong cloud image support, and a familiar path from local development to production servers. For Raff Technologies users, Ubuntu works especially well when you need a clean Linux VM for testing, deployment, Docker, APIs, databases, or remote development. Ubuntu is a Debian-based Linux distribution maintained by Canonical and widely used across desktops, servers, and cloud infrastructure. In practice, developers choose Ubuntu because it is predictable: `apt` works the way they expect, documentation is everywhere, security updates are easy to understand, and most deployment tutorials assume Ubuntu or Debian-style commands. I use Ubuntu often when testing server setups because it gives me a repeatable baseline. A fresh Ubuntu VM on Raff lets me confirm whether a setup works on a real cloud server, not just on a local machine with months of old packages and hidden configuration changes. ## Ubuntu Wins Because It Is Predictable Developers do not choose an operating system only because it is popular. They choose it because it reduces surprises. Ubuntu’s biggest advantage is predictability. The commands are familiar, the package names are usually easy to find, and the system layout is close to what most Linux tutorials, GitHub projects, and deployment guides expect. That matters when you are setting up: * Node.js apps * Python backends * Docker containers * Nginx or Caddy reverse proxies * PostgreSQL or MySQL databases * Redis caches * CI/CD runners * Self-hosted tools * Monitoring agents * VPNs and private services For a developer, the value is not theoretical. If you can copy a setup from a reliable guide, understand the commands, and troubleshoot errors quickly, you ship faster. That is why Ubuntu keeps showing up in production workflows. It is not always the most minimal Linux distribution. It is not always the most customizable. But it is often the most practical starting point. ## Ubuntu 24.04 LTS Is the Practical Default For most new cloud VM projects, Ubuntu 24.04 LTS is the strongest default choice. It has a modern package base, long-term support, and broad compatibility with current developer tools. LTS matters because production servers should not feel experimental. You want security updates, stable package behavior, and a release lifecycle that gives your team time to plan upgrades instead of reacting to end-of-life deadlines. On Raff, Ubuntu 24.04 LTS is a natural fit for a [Linux VM](/products/linux-vm) because it gives you a clean server environment with full root access, SSH, NVMe SSD storage, and enough flexibility to run modern workloads. Use Ubuntu 24.04 LTS when you are starting a new project, writing a deployment guide, building a production web server, or creating a repeatable team environment. Ubuntu 22.04 LTS still makes sense for older production stacks that are already tested there. If a project’s dependencies, deployment scripts, or client environment still expect 22.04, stability may matter more than using the newest LTS immediately. ## Developers Like Ubuntu Because the Package Ecosystem Is Huge The `apt` package manager is one of Ubuntu’s biggest strengths. Installing common server tools is usually straightforward, and most major open-source projects document Ubuntu installation steps clearly. That lowers setup friction. A developer can move quickly from a blank VM to a working environment: * Install Nginx or Caddy * Add Node.js, Python, PHP, Go, or Java * Install Docker * Set up PostgreSQL, MySQL, MariaDB, Redis, or MongoDB * Configure UFW firewall rules * Add Certbot for HTTPS * Install monitoring and logging agents * Run application services with systemd This is the practical reason Ubuntu stays popular. The ecosystem around it is massive. When I test tutorials, I care about whether a reader can follow the path without hunting through obscure package names or distribution-specific edge cases. Ubuntu usually gives the smoothest path for that. For example, Raff already has hands-on Ubuntu tutorials such as [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Deploy a Node.js App with PM2 on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04), and [Install PostgreSQL on Ubuntu 24.04](/learn/tutorials/install-postgresql-ubuntu-24-04). ## Ubuntu Is Built for Cloud Workflows Ubuntu works well on cloud VMs because it has strong support for cloud images, SSH access, automation, and headless server operation. A cloud VM is different from a laptop. It needs to boot quickly, accept secure remote access, apply network configuration correctly, and run without a desktop environment. Ubuntu Server is designed for that style of operation. Cloud-init is a major part of this story. It helps automate first-boot configuration, including users, SSH keys, packages, hostnames, and initialization scripts. That makes Ubuntu useful not only for one-off VMs, but also for repeatable infrastructure. This is important for developers and small teams. You do not want every VM to become a hand-built snowflake. You want a baseline you can rebuild, document, and trust. If you are planning repeatable server setup, Raff’s guide to [VM provisioning models with cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click) is a good companion topic. ## Ubuntu Makes Security Easier to Start Ubuntu is not automatically secure just because it is Ubuntu. But it gives you a good starting point. A secure Ubuntu server still needs the basics: * SSH key authentication * Disabled password login where appropriate * UFW firewall rules * Regular security updates * Least-privilege users * Fail2Ban or equivalent protection * Backups and restore testing * Monitoring and logs * Careful secret management The advantage is that these tasks are well documented and widely understood. If you are new to server security, Ubuntu gives you a clear learning path. Raff has a dedicated tutorial for this exact first step: [Secure Your Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). If you are exposing a VM to the internet, that should be one of the first articles you read after deployment. For firewall-specific setup, use [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). UFW is one of the reasons Ubuntu remains approachable for developers who are not full-time Linux administrators. ## Ubuntu Works Well for Docker and Self-Hosting A lot of modern developer infrastructure starts with Docker. Ubuntu is a comfortable base for Docker because the installation path is well documented, the kernel support is strong, and most self-hosting tutorials assume an Ubuntu server. This matters if you are deploying: * n8n * Uptime Kuma * Nextcloud * Gitea * Portainer * Supabase * Coolify * Custom APIs * Internal dashboards * Background workers * Monitoring stacks Ubuntu gives you enough stability for production but enough freshness for modern tooling. That balance is why so many self-hosted projects use Ubuntu 22.04 or 24.04 in their examples. For developers using Raff, this creates a simple path: deploy a VM, install Docker, add the application stack, configure a reverse proxy, secure the server, and then scale or split services when the workload grows. If you are building a self-hosted environment, start with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), then move into service-specific tutorials like [Self-Host n8n with Docker Compose](/learn/tutorials/self-host-n8n-docker) or [Install Coolify on Ubuntu 24.04](/learn/tutorials/install-coolify-ubuntu-24-04). ## Ubuntu Is Beginner-Friendly Without Being Toy Infrastructure Ubuntu has a rare position in the Linux world: it is friendly enough for beginners, but serious enough for production servers. That is why it works across different skill levels. A student can use Ubuntu to learn Linux commands. A freelancer can use Ubuntu to host a client app. A startup can use Ubuntu for staging and production. A DevOps engineer can use Ubuntu as a standard server base. A technical writer can use Ubuntu to test repeatable setup steps. This range is valuable. A team can teach new developers on the same operating system they use for real deployments. That reduces context switching. Ubuntu also makes mistakes easier to recover from because the community is huge. Error messages, package conflicts, firewall issues, Nginx problems, Docker setup errors, and SSH configuration mistakes are usually searchable. That does not replace good engineering, but it does reduce friction. ## Ubuntu Is Not Always the Right Choice Ubuntu is practical, but it is not the right answer for every workload. Choose Debian when you want a more conservative base and maximum simplicity. Choose Rocky Linux or AlmaLinux when you need a RHEL-compatible environment. Choose Fedora when you want newer packages and do not need long production support windows. Choose Alpine when you are optimizing for very small containers or minimal environments. The point is not that Ubuntu wins every comparison. The point is that Ubuntu is often the best default when you need a cloud VM that is easy to deploy, easy to document, and easy to hand off to another developer. If you are choosing between Linux distributions for a Raff VM, start with the workload: * For general web apps, choose Ubuntu 24.04 LTS. * For Docker and self-hosting, choose Ubuntu 24.04 LTS. * For older production compatibility, consider Ubuntu 22.04 LTS. * For RHEL-style enterprise environments, choose Rocky Linux or AlmaLinux. * For minimal container-focused setups, consider Alpine. When you are unsure, Ubuntu is usually the safest first VM. ## Choosing the Right Raff VM for Ubuntu The operating system is only one part of the decision. You also need the right VM size. A small development server does not need the same resources as a production API, database, or CI runner. CPU, RAM, and storage should match the workload rather than the operating system alone. For light testing, learning, small tools, and simple web apps, a smaller General Purpose VM may be enough. For databases, CI/CD runners, build workloads, and production services that need consistent compute, CPU-Optimized VMs are usually a better fit. Raff’s [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) guide explains how to think about CPU, RAM, and storage before deploying. If you are deciding between shared and dedicated compute, read [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) before choosing a plan. You can also compare current plans on the [Raff pricing page](/pricing). ## What This Means for Developers Ubuntu remains popular because it helps developers get from idea to working server quickly. It gives you a predictable Linux base, a large package ecosystem, strong cloud support, simple security defaults, and a huge body of tutorials. On Raff, that makes Ubuntu a practical first choice for cloud VMs, especially when you are testing, deploying, self-hosting, or building repeatable infrastructure. The best way to use Ubuntu is not to treat it as magic. Treat it as a clean baseline. Start with Ubuntu 24.04 LTS. Secure SSH. Configure the firewall. Install only what your workload needs. Document the setup. Add backups. Monitor the server. Resize or split infrastructure when the workload grows. That workflow is simple, but it is also production-minded. ## Final Thoughts Developers still choose Ubuntu because it solves the boring problems well. It boots cleanly, installs packages predictably, supports cloud automation, works with modern developer tooling, and has answers available when something breaks. That boring reliability is exactly what you want from a cloud VM operating system. At Raff Technologies, Ubuntu remains one of the most practical starting points for developers who want a real Linux server without unnecessary complexity. Deploy it, test your workload, secure the basics, and grow from there. For your next step, start with a [Raff Linux VM](/products/linux-vm), secure it with [Ubuntu initial server setup](/learn/tutorials/secure-ubuntu-24-04-server), then install a real workload such as [Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) or [Node.js with PM2 on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04). --- ### What Is MCP? How AI Agents Connect to Cloud Infrastructure URL: https://rafftechnologies.com/blog/model-context-protocol-mcp-the-revolutionary-standard-transforming-ai-integration-in-2025 Published: 2025-05-23T00:00:00.000Z Description: What Is MCP? How AI Agents Connect to Cloud Infrastructure Model Context Protocol, or MCP, is becoming the connection layer between AI agents and real systems: APIs, databases, files, developer tools, and cloud infrastructure. For Raff Technologies users, the important question is not only “what is MCP?” but “where should MCP servers and AI automation tools run safely?” MCP is an open standard that lets AI applications connect to external systems through a consistent interface. Instead of building a custom integration for every AI assistant, tool, database, or API, developers can expose capabilities through MCP servers and let compatible AI clients use them in a more structured way. The practical infrastructure angle is simple: if an AI agent can read data, call tools, or trigger actions, the server that exposes those capabilities must be hosted, secured, monitored, and isolated properly. That is where cloud VMs, private networking, firewall rules, and careful access control become part of the MCP conversation. ## MCP Solves the AI Integration Problem Before MCP, connecting AI tools to real systems often meant building one-off integrations. One assistant needed one custom connector for one database. Another needed a different connector for the same system. Over time, this creates duplicated work, inconsistent security, and fragile automation. MCP changes the pattern. A developer can build an MCP server that exposes a system once, then compatible MCP clients can connect to that server through the same protocol. Think of it this way: * The AI application is the client. * The MCP server exposes tools, data, or prompts. * The external system is the database, API, file store, cloud service, or workflow engine. * The protocol defines how the client and server communicate. This matters because AI agents are becoming more useful when they can interact with real systems. A chatbot that only answers from memory is limited. An AI assistant that can query a database, inspect logs, open a ticket, generate a report, or call an internal API becomes much more practical. ## MCP Is Not Magic Automation MCP does not make infrastructure safe by itself. It only standardizes how AI applications connect to tools and data. That distinction matters. If you expose a powerful internal API through an MCP server, the protocol does not remove your responsibility to secure it. If the server can restart services, query customer data, edit files, or call billing APIs, then authentication, authorization, logging, and least-privilege access become critical. The best way to think about MCP is this: > MCP gives AI agents a structured door into your systems. Your job is to decide where that door is hosted, what it can access, and who is allowed to open it. That is why MCP belongs in the same conversation as cloud security, private networking, and infrastructure operations — not only AI product development. ## How MCP Works in Simple Terms An MCP setup usually has three parts. First, there is an MCP client. This is the AI application or development tool that wants to use external context or actions. Examples can include AI assistants, coding tools, or agent frameworks. Second, there is an MCP server. This is the service that exposes specific capabilities. It may provide access to a database, file system, API, search tool, internal workflow, cloud resource, or documentation source. Third, there is the external system itself. That could be PostgreSQL, GitHub, Slack, a CRM, an internal admin API, a cloud dashboard, or a custom backend service. The MCP server acts as the controlled bridge. Instead of giving an AI assistant unrestricted access to everything, you expose specific tools and resources intentionally. A simple MCP workflow might look like this: * An AI coding assistant asks for context from a repository. * The MCP client sends a request to the relevant MCP server. * The server checks what it is allowed to expose. * The server returns the requested file, metadata, query result, or tool response. * The AI assistant uses that context to help the user. That structure is why MCP is useful. It creates a repeatable model for connecting AI to real systems. ## Why Developers Should Care Developers should care about MCP because it reduces integration work and makes AI tooling more practical. Without a standard protocol, every connection between AI and a tool can become a custom project. With MCP, the goal is to make the connection model more reusable. A team can build or use MCP servers for common systems, then plug them into clients that support the protocol. This is useful for: * Codebase-aware AI assistants * Internal documentation search * Database query assistants * Cloud operations tools * DevOps workflows * Support automation * Data analysis workflows * AI-powered admin dashboards * Custom internal agents For developers, MCP is most interesting when the workflow touches real infrastructure. An assistant that can read deployment logs, query a database, inspect service status, or interact with internal APIs is more useful than one that only generates text. But that usefulness also raises the risk level. The closer an AI system gets to production infrastructure, the more carefully the MCP server must be designed. ## Why Cloud Infrastructure Matters for MCP MCP servers need somewhere to run. For local experiments, a laptop may be enough. For team workflows, internal tools, production-adjacent automation, or long-running agents, local hosting is usually not enough. A cloud VM gives an MCP server a stable environment with predictable networking, operating system control, and separation from a personal machine. That makes it easier to configure access rules, monitor the process, update dependencies, and keep the service available for the team. A [Raff Linux VM](/products/linux-vm) is a practical starting point for MCP server experiments because you can create a clean server environment, install only what the project needs, and isolate the workload from your main application infrastructure. This is especially useful when your MCP server needs to communicate with other cloud services, private APIs, databases, automation tools, or internal dashboards. ## Practical MCP Use Cases for Cloud Teams MCP becomes more interesting when it connects AI agents to infrastructure and developer workflows. Here are practical examples. | Use Case | What the MCP Server Exposes | Why It Helps | |---|---|---| | Log analysis | Application logs or observability API | AI can summarize incidents and identify patterns | | Database assistant | Read-only database queries | Teams can ask operational questions without writing SQL each time | | Deployment helper | CI/CD or release metadata | AI can explain failed deployments or suggest next steps | | Documentation search | Internal docs and runbooks | New team members can find answers faster | | Cloud resource helper | VM, storage, or network metadata | Operators can inspect infrastructure through natural language | | Support workflow | Ticket and customer metadata | Support teams can triage issues faster | | Automation bridge | n8n or internal workflow APIs | AI can trigger controlled workflows | The important word is “controlled.” MCP should expose limited capabilities with clear boundaries. For example, a read-only database MCP server is safer than one that can modify production records. A server that summarizes logs is safer than one that can restart services. ## The Security Problem MCP Introduces MCP security matters because MCP servers can sit between AI agents and sensitive systems. A poorly designed MCP server can expose too much data, execute unsafe commands, leak credentials, or give an AI agent access it should not have. This risk becomes higher when the server connects to infrastructure tools, databases, file systems, or admin APIs. Before deploying an MCP server, ask these questions: * What data can this server access? * Can it only read, or can it also write? * Which users or clients can connect? * Are credentials stored safely? * Are requests logged? * Can actions be audited later? * Is the server reachable from the public internet? * Does the server need private networking? * What happens if the AI client makes a bad request? * Can the server be rolled back or disabled quickly? A safe MCP design starts with least privilege. Expose the minimum set of tools needed for the workflow, then expand only when there is a clear reason. ## Hosting MCP Servers on Raff A Raff VM can host MCP servers for development, testing, internal tools, or production-adjacent automation. The right architecture depends on what the server can access. For a low-risk experiment, you might run one MCP server on a small VM with limited test data. For an internal team tool, you may want a dedicated VM, firewall restrictions, private networking, and stronger monitoring. For a sensitive production workflow, you should isolate the MCP server from public access and expose only narrow, auditable capabilities. A practical Raff setup might include: * A dedicated [Raff VM](/products/raff-vm) for the MCP server * Firewall rules that limit inbound access * SSH key-based administration * Private networking for internal service communication * Separate credentials for each connected system * Read-only permissions where possible * Backups for configuration and workflow data * Logs for audit and troubleshooting If the MCP server connects to private services, a public server with broad access is the wrong model. Use tighter network boundaries and expose only what the workflow actually needs. ## MCP and Private Networking Private networking becomes important when MCP connects AI tools to systems that should not be publicly reachable. For example, an MCP server may need to query an internal API, inspect a database, or talk to a worker service. Those systems should not be opened to the internet just because an AI assistant needs context. A better model is to place the MCP server near the systems it needs to access, then restrict external access to the MCP layer itself. That lets you build a controlled bridge rather than exposing every backend service directly. Raff’s [Private Cloud Networks](/products/private-cloud-networks) product path is relevant here because MCP is fundamentally about controlled connectivity. The safer pattern is not “AI can reach everything.” The safer pattern is “AI can reach one carefully designed service that has limited access to the right systems.” ## MCP and Automation Workflows MCP also fits naturally with automation tools. An AI agent may not need direct access to every system. Sometimes it should trigger a controlled workflow instead. For example, instead of giving an AI agent direct permission to modify infrastructure, you could expose a tool that triggers a predefined workflow: * Create a staging environment * Run a backup check * Generate a deployment report * Open a support ticket * Summarize failed jobs * Run a safe diagnostic script This is a healthier automation model. The AI agent requests a known operation, and the workflow system performs the steps with guardrails. If your team already uses workflow automation, Raff’s article on [n8n self-hosted automation](/learn/guides/n8n-self-hosted-workflow-automation-guide) is a useful companion topic. n8n handles workflow orchestration; MCP can help AI agents interact with tools and workflows through a standardized interface. ## What I Would Test Before Deploying MCP Seriously Before using MCP for anything important, I would test the server in a clean environment. First, test the permissions. Start with read-only access and prove the workflow works before adding write actions. If the server only needs to read documentation, it should not have access to production databases. Second, test failure behavior. What happens if the external API times out, returns bad data, or rejects authentication? The MCP server should fail safely, not expose internal errors or retry dangerous actions. Third, test logging. You should know which client requested which tool, when it happened, and what result came back. If an AI agent performs an action through MCP, you need an audit trail. Fourth, test network exposure. If the MCP server does not need to be public, do not make it public. If it must be reachable, restrict who can reach it. Fifth, test rebuildability. A clean VM should be easy to recreate with documented setup steps. If the server becomes important, the deployment process should not depend on one person’s memory. This is why I prefer testing infrastructure tools on fresh VMs. A clean VM shows whether the setup is actually repeatable. ## When MCP Is a Good Fit MCP is a good fit when your team wants AI tools to interact with real systems in a structured way. Use MCP when: * You need AI agents to access internal tools * You want reusable integrations instead of one-off connectors * You need controlled access to APIs, files, databases, or workflows * You want AI assistants to understand your operational context * You are building developer tools or internal automation * You want to standardize how agents connect to systems Avoid MCP when the workflow is simple enough to solve with a normal API call, scheduled script, or basic automation rule. MCP is powerful, but it still adds another layer to operate. ## What This Means for Raff Users For Raff users, MCP should be viewed as part of the infrastructure stack when it touches cloud systems. A developer can run an MCP server on a VM. A team can place that server near internal tools. An operator can restrict access with firewall rules and private networking. A founder can use MCP to explore AI automation without giving uncontrolled access to production systems. The safest starting point is small: * Pick one useful workflow. * Use a dedicated VM. * Start with read-only access. * Limit network exposure. * Log every request. * Test failure paths. * Add write actions only when necessary. You can start with a [Linux VM](/products/linux-vm), review [Raff pricing](/pricing), and connect the MCP idea to broader cloud automation using [Raff API keys for small-team automation](/learn/guides/raff-api-keys-automation-small-teams). ## Final Thoughts MCP is useful because it gives AI agents a standard way to connect with the tools developers already use. But the real value appears when the protocol is paired with secure infrastructure. The question is not only whether an AI assistant can connect to a tool. The question is whether that connection is limited, observable, recoverable, and hosted in the right place. That is why the cloud layer matters. If MCP servers become part of your automation stack, they deserve the same care as any other infrastructure component: isolation, access control, backups, monitoring, and clear ownership. Start with one MCP server. Keep permissions narrow. Run it in a clean environment. Then expand only when the workflow proves its value. --- ### What is n8n? The Open-Source Automation Tool Built for Developers URL: https://rafftechnologies.com/blog/what-is-n8n-the-open-source-automation-tool-built-for-developers Published: 2025-07-23T00:00:00.000Z Description: What is n8n? The Open-Source Automation Tool Built for Developers What is n8n? n8n is a fair-code workflow automation platform that lets developers connect apps, APIs, databases, and internal tools through visual workflows while still keeping room for custom code. Raff Technologies users usually care about n8n for one reason: it gives you automation power without forcing every workflow into a closed SaaS platform. If you have ever wanted to say “when this happens, run these steps automatically,” n8n is built for that. A workflow can start from a webhook, schedule, app event, form submission, database change, or manual trigger. Then each step passes data to the next node, where you can transform, filter, enrich, route, or send that data somewhere else. I like n8n because it sits in a useful middle ground. It is visual enough for fast workflow building, but technical enough for developers who need custom JavaScript, API calls, credentials, branching logic, and self-hosted control. That combination is why it has become a serious option for founders, DevOps teams, internal tooling builders, and automation-heavy startups. ## n8n Is Not Just Another No-Code Tool n8n looks simple at first because the interface is visual. You drag nodes, connect them, configure credentials, and watch data move between steps. But calling n8n “just no-code” misses the point. Most no-code automation platforms are designed to keep users inside a controlled interface. That is fine for simple workflows, but it becomes frustrating when you need custom logic, internal APIs, private infrastructure, or more control over where your automation data runs. n8n is different because it gives technical users more room. You can use built-in integrations for common tools, but you can also write custom code, call private APIs, transform JSON, build conditional branches, and self-host the whole system on your own infrastructure. That makes n8n especially useful when your automation is not just “send a Slack message when a form is submitted.” It is useful when your workflow needs to behave like a small internal application. ## How n8n Workflows Work An n8n workflow is built from connected nodes. Each node does one job: receive data, transform data, call an API, check a condition, send a message, write to a database, or trigger another action. A simple workflow might look like this: * A webhook receives a new lead from a website form. * n8n checks whether the email domain is valid. * It enriches the lead with company data. * It creates a CRM record. * It sends a Slack notification. * It stores a copy in a database. * It triggers a follow-up email sequence. A more technical workflow might call an internal API, run JavaScript to reshape a payload, check error conditions, and send failed records into a retry path. This is where n8n becomes interesting for developers. The visual editor helps you understand the flow, but the workflow can still include real logic. You are not limited to prebuilt templates or shallow integrations. ## Why Developers Like n8n Developers tend to like n8n for four reasons: control, extensibility, self-hosting, and visibility. Control matters because automation often touches sensitive systems. A workflow may handle customer data, API tokens, internal dashboards, billing events, support tickets, or operational alerts. When that workflow runs on infrastructure you control, you can decide how it is secured, monitored, backed up, and exposed. Extensibility matters because real workflows rarely stay simple. A startup may begin with a form-to-Slack workflow, then add enrichment, filtering, routing, database writes, and error handling. n8n allows that growth without forcing the team to rebuild everything from scratch. Self-hosting matters because some teams do not want every automation running through a third-party SaaS environment. If you want that control, Raff’s [n8n VM](/products/n8n-vm) gives you a dedicated path for running n8n as cloud infrastructure rather than another external subscription. Visibility matters because visual workflows are easier to inspect than hidden scripts. When something breaks, you can open the workflow, inspect the failed step, view the data, and fix the logic. ## n8n vs Zapier, Make, and Similar Tools Zapier and Make are excellent for quick SaaS-to-SaaS workflows. They are often faster for non-technical users who want simple automations between common apps. n8n is usually better when the workflow is more technical, private, or infrastructure-aware. | Need | Better Fit | |---|---| | Quick personal productivity automation | Zapier or Make | | Simple SaaS-to-SaaS workflows | Zapier or Make | | Internal APIs and private tools | n8n | | Custom code inside workflows | n8n | | Self-hosted automation | n8n | | Data-sensitive workflows | n8n on controlled infrastructure | | Developer-owned automation systems | n8n | The decision is not about which tool is universally better. It is about who owns the workflow, where the data runs, and how much control the team needs. If you want a deeper decision framework, Raff’s [n8n self-hosted automation guide](/learn/guides/n8n-self-hosted-workflow-automation-guide) explains when self-hosting makes sense and when a managed automation platform may be enough. ## What You Can Build with n8n n8n is flexible because it works across many types of workflows. It can support internal operations, product automation, customer support, marketing systems, infrastructure tasks, and AI workflows. Common examples include: * Lead routing from forms to CRM systems * Slack or Discord alerts from webhooks * GitHub issue automation * Customer onboarding workflows * Invoice and payment notifications * Database cleanup jobs * API monitoring and alerting * Scheduled reports * Support ticket enrichment * AI content or data pipelines * Backup reminders * Internal approval flows The most useful n8n workflows often start from repetitive team pain. If someone on your team says, “I do this same thing every day,” that is a good candidate for automation. For more ideas, read Raff’s related post: [What Can You Build with n8n? 10 Real Use Cases You Can Deploy Today](/blog/w4rbnhj7kfhe4ww99w75jnal). ## Why Self-Hosting n8n Matters Self-hosting n8n gives you more responsibility, but also more control. When you self-host, you control: * Where the workflow server runs * Which network can access it * How credentials are stored * How backups are handled * Which database n8n uses * How updates are applied * How logs and monitoring work * Which integrations can reach internal systems That control is useful for developers and teams that treat automation as part of their infrastructure, not just a convenience tool. But self-hosting also means you need to operate it correctly. n8n should not be thrown onto a public server with weak authentication, no backups, and no update plan. Automation tools often hold powerful credentials, so security matters. A good self-hosted n8n setup should include HTTPS, secure credentials, firewall rules, strong authentication, regular updates, reliable backups, and a database setup that matches the workload. ## Running n8n on Raff Raff is a natural place to run n8n when you want a cloud VM dedicated to automation. You get a server environment that is separate from your laptop, separate from your production app, and available whenever your workflows need to run. There are two practical paths. The fastest path is to use Raff’s [n8n VM](/products/n8n-vm), which is designed for teams that want a pre-configured automation environment without manually assembling every part. The more hands-on path is to deploy n8n yourself on a [Raff Linux VM](/products/linux-vm). This is useful if you want to learn the full setup, customize the stack, or control the deployment from the first package install. If you want the hands-on version, follow the tutorial: [How to Self-Host n8n on Ubuntu 24.04 with Docker Compose](/learn/tutorials/self-host-n8n-docker). ## What I Would Test Before Using n8n Seriously Before using n8n for important workflows, I would test five things. First, test how credentials are stored and who can access them. Automation systems often connect to email, databases, APIs, CRMs, and internal dashboards. That makes credential security a first-order concern. Second, test failure paths. A workflow that works once is not enough. What happens if an API times out? What happens if a webhook sends malformed data? What happens if the database is temporarily unavailable? Third, test backups. If your n8n workflows matter to your business, you should be able to restore them. Export workflows, back up the database, and confirm recovery before you rely on it. Fourth, test performance under realistic workflow volume. A workflow that runs once per day behaves very differently from a workflow triggered every minute. Fifth, test updates. n8n changes over time, and self-hosted tools need maintenance. Make sure you know how to update safely and roll back if needed. This is where running n8n on a clean VM helps. You can test the setup, document the steps, and rebuild the environment if something goes wrong. ## When n8n Is the Right Tool n8n is a strong fit when your team wants automation that is flexible, developer-friendly, and controllable. Use n8n when: * You need to connect APIs and internal tools * You want visual workflows with custom code options * You care where automation data runs * You want to self-host your workflow engine * You need more complex logic than simple SaaS automations allow * You want developers and operations teams to share workflow visibility * You want automation to become part of your infrastructure Avoid n8n when your needs are very simple and a SaaS automation tool already solves the problem with less maintenance. Self-hosting is powerful, but it should have a reason. ## What This Means for You If you are a developer, founder, or technical operator, n8n can become a serious part of your internal infrastructure. It can connect the tools you already use, automate repetitive work, and give your team more control than closed automation platforms usually allow. The important decision is deployment model. If you only need a few lightweight SaaS automations, a managed automation tool may be enough. If you need custom code, private APIs, internal systems, and stronger control over where workflows run, self-hosting n8n is worth considering. On Raff, you can start with a dedicated [n8n VM](/products/n8n-vm), deploy manually with the [Docker Compose n8n tutorial](/learn/tutorials/self-host-n8n-docker), or read [Why We Made n8n Easy to Launch on Raff](/blog/y8veqrl21voygzmttv4wilk9) for the product-side reasoning. ## Final Thoughts n8n is popular because it gives developers something many automation tools do not: visual workflow building without giving up technical control. It is approachable enough to build workflows quickly, but flexible enough to connect APIs, add code, run private automations, and operate on your own infrastructure. That makes it especially useful for technical teams that want automation to be part of their stack, not a black box outside it. If your team is repeating manual work, connecting tools by hand, or writing small scripts that nobody wants to maintain, n8n is worth testing. Start small. Build one useful workflow. Test failure handling. Secure it properly. Then decide whether n8n should become a permanent part of your automation stack. --- ### Why a 60-Second Server Launch Matters More Than It Sounds URL: https://rafftechnologies.com/blog/why-60-second-server-launch-matters-more-than-it-sounds Published: 2026-04-24T00:00:00.000Z Description: Why a 60-Second Server Launch Matters More Than It Sounds # Why a 60-Second Server Launch Matters More Than It Sounds At Raff Technologies, we take cloud infrastructure seriously. But there's one detail we often emphasize that goes unnoticed by many — the importance of speed in provisioning a server. You may wonder, "Why does it matter if a server takes 60 seconds or a couple of minutes to launch?" In fact, that **60-second launch time** matters a lot more than it sounds. It’s not just a feature. It's a reflection of **how we view the cloud experience** — fast, reliable, and frictionless. Let's explore why a quick server launch has a larger impact on your workflow than you might think. ## Onboarding Without the Wait Getting started with cloud infrastructure is often a hassle. From selecting the right plans to waiting for a server to provision, the early friction can be discouraging. As a founder, I know how important it is to keep things **moving fast**. If you have a small team or are running a solo startup, the **waiting game** can eat into your productivity. You need **instant access to your resources** to quickly test, debug, or iterate on your ideas. Raff Technologies eliminates these barriers. With our **60-second server launch**, you don’t waste time staring at loading screens. Instead, you can **get to work immediately**. Our customers love that **speed**. Whether they’re deploying a simple web app, testing a new feature, or tweaking a staging environment, the **instant provisioning** means that no matter what, **their virtual machine (VM)** is up and running in a minute. ## Rapid Iteration with No Roadblocks In the world of cloud development, **speed equals iteration**. The faster you can deploy a test server or a new environment, the faster you can measure, adjust, and optimize. By eliminating long wait times, Raff allows your team to deploy, test, and **iterate** without the **delays**. For startups, small teams, or individual developers, this is incredibly powerful. You no longer need to wait for **long server provisioning times** to try out new ideas or features. The beauty of having a server up and running in 60 seconds is that it enables faster **feedback loops**. The quicker you can deploy and get feedback, the faster you can iterate. At Raff, that **instant deployment** allows you to push changes, test new features, and experiment without the infrastructure getting in your way. ## Minimizing Friction at Every Step One of the biggest barriers for developers working with cloud infrastructure is **friction**. Whether it’s waiting for a server to spin up or navigating through complex dashboards and configurations, every second of friction slows down progress. At Raff, we’ve built our platform to minimize that friction. By providing **instant provisioning** and an easy-to-use interface, we ensure that **you spend less time managing infrastructure** and more time building products. If you’re constantly waiting for resources to be provisioned, it’s easy to feel like you’re losing control over your own projects. But with Raff, we give you the tools to **scale and deploy without hesitation**, keeping you in the driver’s seat of your project’s momentum. ## The Business Impact of Speed Behind every server launch, there’s an **opportunity cost**. A slow launch time might not seem like much on the surface, but when you multiply that delay by every instance your team launches, it adds up. Every minute wasted provisioning servers is **a minute you can’t be testing, building, or iterating**. By reducing the time it takes to get a server up and running, you gain more control over your team’s workflow, helping you execute faster and more efficiently. This translates directly into **higher productivity, faster innovation**, and **reduced overhead costs**. At Raff, we believe that every second counts. That’s why we’ve made our platform not just fast — but **predictably fast**. Our **60-second server launches** ensure that your team spends more time creating and less time waiting for infrastructure. ## Conclusion: It’s All About Efficiency A **60-second server launch** might seem like a small feature, but it’s actually a reflection of our overall approach: **Raff Technologies is built for efficiency**. Whether you're a solo developer, a small team, or a larger organization, having infrastructure that’s **simple, fast, and scalable** isn’t just a luxury — it’s essential for any team looking to move quickly, scale efficiently, and deliver their product without delays. This is why at Raff Technologies, **speed is at the heart of everything we do**. From the initial launch to scaling as you grow, we ensure that the **cloud infrastructure supports your business needs** — not the other way around. So the next time you need to launch a server, you’ll know that with Raff, it will be **up and running in 60 seconds**, giving you more time to focus on what really matters — building something amazing. --- ### What We Learned Testing Cloud-Init Templates Across Ubuntu, Debian, and Rocky Linux URL: https://rafftechnologies.com/blog/what-we-learned-testing-cloud-init-templates Published: 2026-04-22T00:00:00.000Z Description: What We Learned Testing Cloud-Init Templates Across Ubuntu, Debian, and Rocky Linux Cloud-init templates are only as good as their first boot behavior, and the differences between Ubuntu, Debian, and Rocky Linux are real enough to affect reliability. At Raff Technologies, this matters because a template that looks clean in the image pipeline can still behave differently once it has to process metadata, inject SSH keys, bring networking up, and hand control back to the user on a fresh VM. That is what makes cloud-init testing more interesting than it first sounds. You are not only testing whether an operating system supports cloud-init. You are testing whether the distribution’s defaults, packaging choices, boot order, and image state produce a first boot that feels predictable instead of fragile. Raff already has a live guide on [VM provisioning models: cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click), but this post is narrower on purpose. I want to focus on what changed when the same cloud-init intent met three different Linux families. > **Editor note:** Before publishing, add one real Aybars-tested observation here. This topic needs a genuine tested-and-verified signal, such as one specific first-boot difference you reproduced on Raff VMs across Ubuntu, Debian, and Rocky Linux. Your content guide is explicit that this should not be fabricated. ## The Important Lesson: “Supports cloud-init” Is Not Specific Enough The first useful lesson is that “supports cloud-init” is too broad to be operationally helpful. On paper, Ubuntu, Debian, and Rocky Linux can all participate in the same provisioning model. In practice, the thing that matters to operators is not whether cloud-init exists. It is whether the image behaves cleanly under the exact first-boot sequence your platform expects: user-data processing, key injection, hostname handling, package readiness, metadata access, and network availability. That difference matters because cloud-init is not a feature you admire in isolation. It is part of a chain. If one link in that chain is slightly off — networking comes up later than expected, package state is older than expected, image identity is not fully cleaned, or the default user behavior is inconsistent — the template can still “work” while creating more uncertainty than it should. I think that is the right frame for cloud-init testing. The goal is not to prove compatibility. The goal is to remove ambiguity from first boot. ## Ubuntu Usually Feels Like the Reference Case Ubuntu often feels like the baseline many people subconsciously expect cloud-init to match. That is not because other distributions are worse. It is because Ubuntu cloud images are so common in cloud documentation, examples, and user assumptions that many operators begin to treat Ubuntu behavior as the default shape of cloud-init itself. When something works smoothly there, it feels normal. When another distribution behaves differently, it feels like an exception even if that behavior is technically valid. That matters in template testing because Ubuntu can hide a bad habit: assuming that a template design proven once on Ubuntu will carry over to Debian or Rocky Linux without friction. In reality, Ubuntu often becomes the easiest place to build false confidence. ## Debian Often Looks Similar Until the Edges Matter Debian is close enough to Ubuntu that teams often expect a nearly identical first-boot experience. Sometimes that is true. Sometimes it is true only until your assumptions get more specific. This is where image hygiene, default package state, and the surrounding boot flow start to matter more. If your template depends on a certain package being present, a particular user expectation, or a certain timing assumption around initialization, Debian can expose how Ubuntu-specific your “generic” template really was. That is not a criticism of Debian. It is exactly why testing matters. A good cross-distribution cloud-init template should not rely too heavily on implied defaults. The more your provisioning logic depends on what “usually happens,” the more likely you are to discover that one distribution interprets “usually” a little differently than another. ## Rocky Linux Changes the Conversation More Than People Expect Rocky Linux often changes the testing mindset because it pushes the template conversation farther away from Debian-family assumptions. That is useful. It forces you to stop thinking only about user-data syntax and start thinking about the entire image context: package ecosystem, boot behavior, network interface expectations, service readiness, and whether the VM still feels predictable once the first cloud-init run has finished. In other words, Rocky Linux tends to expose whether your cloud-init template is actually cross-platform or simply cross-your-favorite-two-distros. That is one reason I like including Rocky Linux in template validation even when the expected customer usage is weighted toward Ubuntu. It is a good way to find assumptions that were never as portable as they looked inside the pipeline. ## Where First Boot Usually Breaks The most useful cloud-init failures are rarely dramatic. They are usually small breakpoints that make the VM feel less trustworthy than the template author intended. ### Metadata timing and network readiness If networking does not come up in the order your template expects, cloud-init can still run in a way that feels incomplete or inconsistent. This is especially important when the provisioning flow expects metadata-driven values to be available early and reliably. ### SSH key and user assumptions A cloud-init template that assumes too much about the default user model can become fragile across distributions. This is one of the fastest ways for a template to feel “fine in testing” and then generate first-login confusion later. ### Package and service timing If your first-boot logic expects package operations or service starts to behave identically across distributions, you may be treating the distro family as an implementation detail when it is actually part of the provisioning contract. ### Image state that was not cleaned properly This is one of the quietest causes of unreliable first boot. A template can pass a quick launch test while still carrying identity or initialization state that should not survive image publication. Rocky Linux’s image-builder perspective makes this especially clear: image defaults and generalization are part of reliability, not a cleanup step you can treat as secondary. The common thread across all of these is simple: first-boot reliability depends on more than cloud-init syntax. ## Image Defaults Matter More Than Template Authors Want to Admit I think this is the most important lesson in the whole topic. People like to talk about cloud-init as though the template itself is the main variable. In real environments, the underlying image defaults often matter just as much. If the base image is inconsistent, carries stale package assumptions, or boots with different service expectations than your template logic assumes, then the user-data layer ends up taking the blame for problems it did not create on its own. That is why cloud-init testing belongs next to image quality, not separate from it. A template is not floating above the operating system. It is landing on a very opinionated starting state. If that starting state differs between Ubuntu, Debian, and Rocky Linux — and it does — then the template author has to decide whether to normalize those differences or design around them explicitly. The worst option is pretending they are not there. ## What We Actually Want From a Reliable Cloud-Init Template For me, a reliable cloud-init template should do five things well: * process metadata and user-data without timing surprises * inject the correct user access path cleanly * behave predictably on first boot and not only after a reboot * avoid distro-specific assumptions unless they are declared clearly * fail in a way that is diagnosable when something goes wrong That last point matters more than teams admit. You do not need every cloud-init run to be perfect. You do need failures to be understandable. A template that fails transparently is much easier to improve than one that “sort of worked” and left the user with a machine that feels half-initialized. ## Why This Changes How I Think About Standardization This is where the practical value shows up. A lot of teams think standardization means reducing everything to one template. I think good standardization is more nuanced than that. Sometimes the more reliable strategy is not one universal template across all Linux families. Sometimes it is a shared provisioning intent with distro-aware implementation details. That approach usually produces fewer false assumptions and a cleaner first-boot experience. It also fits how real infrastructure evolves. Raff supports multiple operating systems and VM use cases, from Ubuntu and Debian to Rocky Linux, while also giving users platform features like Linux VMs, snapshots, backups, web console access, and private networking. That means reliability is not just about the distro. It is about how the distro, the image, the provisioning model, and the recovery model behave together once the VM is live. The current public product reference also makes it clear that Linux VMs are part of a broader stack that includes snapshots, backups, private networking, and custom OS support, which is exactly why template predictability matters so much in practice. The more distributions you want to support confidently, the less you can afford to mistake “same YAML” for “same outcome.” ## What This Means for You If you use cloud-init templates across multiple Linux distributions, the right question is not “does cloud-init work here?” The better question is “does first boot behave consistently enough here that I would trust this template in front of a real user?” That is the standard I would use. Test your templates across the distributions you actually intend to support, not just the one that was easiest to prototype. Pay close attention to metadata timing, SSH access, package assumptions, and whether the image was generalized properly before publishing. If you are thinking through provisioning models more broadly, start with our guide to [cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click), then pair that with [Linux VMs](/products/linux-vm) as the practical deployment layer. That is the real lesson from cross-distro cloud-init testing: reliability does not come from cloud-init alone. It comes from how well the template and the image agree about what first boot is supposed to do. --- ### Golden Images vs Cloud-Init vs One-Click Templates for MSP Standardization URL: https://rafftechnologies.com/blog/golden-images-vs-cloud-init-vs-one-click-templates Published: 2026-04-21T00:00:00.000Z Description: Golden Images vs Cloud-Init vs One-Click Templates for MSP Standardization # Golden Images vs Cloud-Init vs One-Click Templates for MSP Standardization When managing client environments, **Managed Service Providers (MSPs)** face constant challenges related to **standardization**, **repeatability**, and **onboarding speed**. One of the most important decisions MSPs must make is how to streamline their server provisioning process. Whether you're creating a base image for your virtual machines (VMs), automating post-deployment tasks, or deploying an entire app stack in one go, it’s crucial to find the right method for your infrastructure. This post compares **Golden Images**, **Cloud-Init**, and **One-Click Templates**, highlighting the benefits and tradeoffs of each approach. Let’s dive into the details and see how they stack up for MSP standardization. ## 1. **Golden Images: The Traditional Approach** A **Golden Image** is a pre-configured VM image that contains the exact state you want to replicate across multiple instances. This image includes the OS, necessary packages, and configuration settings. It’s the most traditional approach to server standardization and has been used for years by MSPs for its reliability and simplicity. ### **Benefits of Golden Images:** - **Consistency:** Every new server deployed from a Golden Image is identical, ensuring repeatability. - **Simplicity:** Once an image is created, it can be quickly deployed across any number of machines with minimal setup. - **Speed:** You don’t have to reconfigure the server each time—it’s already “done.” ### **Drawbacks:** - **Manual Updates:** Whenever a software or configuration change is needed, the Golden Image must be updated and redeployed, leading to manual processes. - **Scalability Issues:** With large-scale operations, maintaining and updating Golden Images can become cumbersome. In essence, Golden Images are a great choice for smaller operations or environments where consistency is key, but for large-scale setups, this approach can start to feel limiting. ## 2. **Cloud-Init: Automating the First Boot** **Cloud-init** is a tool that allows for the automated configuration of servers at the first boot. It’s a standard in cloud environments like AWS, GCP, and Azure. Unlike Golden Images, Cloud-init allows for more dynamic provisioning. You can specify configuration settings such as networking, SSH keys, and software installation at runtime. ### **Benefits of Cloud-Init:** - **Flexibility:** Cloud-init scripts are executed at the first boot of the machine, allowing you to configure the server in real-time, tailored to each deployment. - **Automated Setup:** With Cloud-init, you can automatically configure the environment without having to manually intervene in each server’s setup. - **Scalability:** Cloud-init works particularly well in cloud environments, allowing MSPs to spin up hundreds or thousands of instances without manually creating Golden Images for each one. ### **Drawbacks:** - **Complexity:** Writing and managing Cloud-init scripts can get complicated as the configuration becomes more customized and varied. - **Dependence on Cloud Providers:** Cloud-init is tightly integrated with cloud providers, which can limit its usage in on-premise environments. Cloud-init offers much more flexibility than Golden Images, making it a popular choice for cloud-centric environments where servers need to be dynamically configured at boot. ## 3. **One-Click Templates: The Simplified Deployment Solution** **One-Click Templates** are pre-configured application stacks that can be deployed with just a single command or click. They go beyond the base OS setup and often include application installation, configuration, and even integration with other services. ### **Benefits of One-Click Templates:** - **Instant Deployment:** These templates are the fastest way to deploy fully functional applications, including all dependencies and configurations. - **Comprehensive Configuration:** One-click templates can configure everything, from the OS to the application level, including services, networking, and more. - **No Maintenance:** Unlike Golden Images, One-Click Templates are typically maintained by the platform, reducing the need for constant updates on your part. ### **Drawbacks:** - **Limited Customization:** While one-click templates are fast, they might not be as flexible as Cloud-init for custom configurations. - **Not Always Transparent:** You may not always have visibility into how certain settings are configured, which can cause issues for MSPs who need to maintain fine-grained control. One-click templates are fantastic for MSPs who need to deploy entire environments quickly and without hassle. They are particularly useful when you need a standardized environment quickly, like for testing or staging, but they might not be as flexible as Cloud-init for more complex use cases. ## **What’s Right for Your MSP?** As MSPs scale and handle more clients, the question of standardization becomes even more critical. Here’s a quick comparison: | **Method** | **Best For** | **Pros** | **Cons** | |--------------------|----------------------------------------------------|--------------------------------------------------------|-----------------------------------------| | **Golden Images** | Simple, repeatable deployments | Consistency, speed, reliability | Manual updates, scalability limits | | **Cloud-Init** | Dynamic cloud infrastructure | Flexibility, automated provisioning, scalability | Complexity, cloud-specific | | **One-Click Templates** | Fast, standardized full-stack deployments | Speed, simplicity, fully configured stacks | Limited customization, less control | ## **What This Means for You** For MSPs, the choice between **Golden Images**, **Cloud-init**, and **One-Click Templates** ultimately depends on your needs for **scalability**, **flexibility**, and **management complexity**. - **Golden Images** are best suited for smaller, predictable environments where changes are minimal. - **Cloud-init** is ideal for MSPs working with cloud infrastructures who need dynamic, real-time provisioning. - **One-Click Templates** are perfect for fast, repeatable app stack deployment but may lack flexibility for highly customized environments. At **Raff Technologies**, we support all three approaches through flexible **VM configurations**, **private networking**, and **automated scaling** to help MSPs deploy cost-effective, standardized environments across thousands of clients. --- ### Why SSH Key Setup Still Breaks for New Users (And How We Test It) URL: https://rafftechnologies.com/blog/why-ssh-key-setup-still-breaks Published: 2026-04-20T00:00:00.000Z Description: Why SSH Key Setup Still Breaks for New Users (And How We Test It) SSH key setup still breaks for new users for one simple reason: the setup itself is not hard, but the failure modes are unforgiving. One wrong username, one misplaced public key, or one permission bit that is too open can turn a five-minute security improvement into a lockout. On a fresh cloud VM, that feels much worse than it should. At Raff Technologies, this matters because SSH access is the first real trust boundary most users touch. Before you install Docker, open a firewall rule, or deploy an app, you need a login path that is secure and predictable. Our existing tutorial on [setting up SSH keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04) covers the happy path. This post is about the part that usually gets less attention: why the happy path falls apart for new users, and how to test it like a real onboarding flow instead of assuming it will work because the commands look right. SSH key authentication is a login method that uses a private key on your device and a matching public key on the server. OpenSSH reads allowed user keys from the configured `AuthorizedKeysFile`, which defaults to `.ssh/authorized_keys` in the user’s home directory. That sounds simple, but it means SSH key login depends on several things being true at the same time: the right user account, the right key pair, the right file path, and the right permissions. We already cover the correct setup flow in our SSH tutorial and server hardening tutorial. This post is narrower on purpose. I wanted to focus on the specific mistakes that keep turning “I added my key” into “why am I still getting `Permission denied (publickey)`?” > **Editor note:** Before publishing, add one short Aybars-tested box here with real internal observations, such as the top 3 failure cases reproduced on a fresh Ubuntu 24.04 VM and how long each took to resolve. ## The Biggest Problem Is Usually Not the Key New users often assume that an SSH key problem means key generation failed. In reality, the key pair is usually fine. The failure is more often around context: the wrong login user, the key being copied to the wrong account, or the client offering a different private key than the one the server expects. That is why SSH troubleshooting feels weirdly frustrating. The commands look familiar. The server is online. The key exists. But one tiny mismatch between those pieces is enough to make the entire login fail. If you zoom out, most SSH key onboarding issues fall into four buckets: * you are connecting as the wrong username * the matching public key is not in the target user’s `authorized_keys` * file ownership or permissions are too open * you disabled the fallback path before verifying the key path actually worked The reason this hits beginners especially hard is that all four can produce nearly the same emotional result: “SSH is broken.” ## Wrong Username Is More Common Than People Admit This is the easiest mistake to make and one of the least obvious when you are new. A lot of people generate a key correctly, copy it correctly, and still fail because they connect to the server as the wrong user. They log in as `root` when the key was installed for `sammy`, or they use a new sudo user while the public key still sits under another account’s home directory. OpenSSH does not care that the server has your public key somewhere. It cares whether the public key is present for the exact account you are trying to log in as. That sounds obvious after the fact, but for new users it is one of the most common reasons the key setup “looks right” and still fails. Current SSH troubleshooting docs from other cloud providers still call out this exact pattern because it keeps happening in practice. This is why I think SSH tutorials should always make the account boundary more explicit than they usually do. “Copy your key to the server” is incomplete advice. The real instruction is “copy your public key to the home directory of the exact account you will use over SSH.” ## Permissions Are Small Details With Big Consequences The second big trap is permissions. SSH is strict for good reasons. If the `.ssh` directory or the `authorized_keys` file is too open, OpenSSH can reject them because loose permissions undermine the trust model around key-based authentication. Troubleshooting guides still converge on the same basic fixes: restrictive permissions on the home directory, `.ssh`, and `authorized_keys`; correct ownership; and confirmation that the server is actually reading the expected file. This is also where beginners get tripped up by advice that is technically right but operationally incomplete. They are often told: * set `~/.ssh` to `700` * set `authorized_keys` to `600` * make sure the files are owned by the target user That advice is correct. But what is missing is the reason it matters. SSH is not only checking that the key exists. It is checking whether it can trust the place where that key lives. That is why permission errors feel confusing. The key itself may be perfectly valid. The login still fails because the server has decided the environment around the key is not safe enough. ## The Matching-Key Problem Is Usually Invisible Another common failure is using the wrong private key on the client. This is especially easy to do on laptops and workstations where multiple keys already exist. You may generate a new Ed25519 key, add the public half to the server, and then discover that your SSH client is still offering an older RSA key or a completely unrelated identity loaded in your agent. That makes the server-side setup look broken when the real issue is that the client never presented the matching key in the first place. This is why I like treating SSH onboarding as a two-sided test: 1. verify the server has the right public key for the right user 2. verify the client is actually offering the corresponding private key If you only test the server side, you can lose a surprising amount of time debugging the wrong machine. ## New Users Disable the Safety Net Too Early This is the mistake that turns a minor issue into a support problem. A lot of first-time users follow the secure instinct of disabling password authentication quickly. In principle, that is a good move. Raff’s own SSH key tutorial recommends verifying key-based auth and then disabling password login, and its conclusion explicitly points users to the Raff web console as an emergency fallback if they ever lock themselves out. :contentReference[oaicite:8]{index=8} But in practice, people often disable the fallback before they have tested enough things: * can I open a second SSH session before closing the first one? * can I log in with the new non-root user? * does the client use the correct identity automatically? * do I still have console-based recovery if SSH fails? This is where cloud onboarding needs a slightly different mindset from local Linux tutorials. On a VM, distance amplifies mistakes. A typo in `sshd_config` is no longer just a typo. It is potentially a lost access path. ## The Recovery Path Matters as Much as the Setup Path This is the part many guides treat as an afterthought, but I think it deserves equal weight. A good SSH onboarding flow does not just prove that the secure login path works. It also proves that recovery is available if it stops working. Other providers still document recovery consoles for exactly this reason, and Raff already exposes the same logic in its own SSH tutorial: if you lose SSH access, the browser-based web console gives you a way back in without depending on port 22. :contentReference[oaicite:9]{index=9} That changes the emotional shape of SSH hardening. You can be strict without being reckless. I think that is one of the biggest gaps in beginner SSH education. Too many people are taught only the “secure path” and not the “recoverable path.” In production, you need both. ## How I Would Test SSH Key Onboarding Properly If I were turning SSH key setup into a repeatable onboarding test, I would not stop at “the command completed.” I would test it like this: ### 1. Validate the identity path Confirm the target username before copying the key. Make sure the public key lands in the actual account that will be used for SSH. ### 2. Validate the file path Confirm the public key is in the expected `authorized_keys` file for that exact user, not just somewhere on the server. OpenSSH’s default lookup behavior is simple, but only if you keep the user-to-file mapping simple too. ### 3. Validate ownership and modes Check the ownership and permissions of the home directory, `.ssh`, and `authorized_keys`. Do this before touching `sshd_config`, not after the login fails. ### 4. Validate the client side Use verbose SSH output and confirm the client is offering the identity you think it is offering. When a machine has several keys, assumption is the enemy. ### 5. Validate recovery Before disabling passwords or closing the original session, confirm you still have a recovery path through the cloud console. That sequence is slower than “just follow the commands,” but it is much better onboarding. It turns SSH key setup from a checklist into a testable access workflow. ## Why This Still Matters on Small Teams Some people treat SSH key mistakes as beginner issues that disappear once a team gets serious. I do not think that is true. These failures keep showing up because small teams move quickly, reuse snippets, create users under time pressure, and harden servers while also trying to ship something else. The issue is not lack of intelligence. It is that SSH combines security, Linux permissions, user context, and remote recovery in one narrow path. That path is easy to get 95% right and still fail. That is exactly why this topic belongs on Raff’s blog rather than only in a step-by-step tutorial. Tutorials teach the correct path. Blog posts like this help explain why the correct path still breaks in real life. ## What This Means for You If you are new to cloud servers, the biggest improvement you can make is to stop treating SSH key setup as a single command sequence and start treating it as an access test. That means: * confirm the username first * confirm the matching key pair second * confirm file ownership and modes third * confirm recovery before you disable the old path If you want the clean setup flow, start with our tutorial on [setting up SSH keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04). If you are designing a broader access model, pair it with [Bastion Host vs VPN vs Public SSH](/learn/guides/bastion-host-vs-vpn-vs-public-ssh) and [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). And if you are still at the very start, launch a [Raff Linux VM](/products/linux-vm) and test your SSH path before you install anything else. That is still the safest order of operations. --- ### What We Check Before Publishing a One-Click App Template URL: https://rafftechnologies.com/blog/what-we-check-before-publishing-one-click-app-template Published: 2026-04-20T00:00:00.000Z Description: What We Check Before Publishing a One-Click App Template A one-click app template is only useful if it keeps its promise after the first click. At Raff Technologies, we do not treat “install completed” as the bar for publishing. We treat rerun safety, sane defaults, credential clarity, and recovery as part of the release criteria. That matters because a one-click deployment is not just a faster installer. It is a product surface. When someone launches an app template, they are trusting that the platform made a long list of decisions for them: which ports to expose, where data should live, how secrets are created, what happens on reboot, and whether the application is still understandable after the first login. We already explain the broader provisioning decision in our guide to [cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click). This post is narrower on purpose. I want to focus on the part users do not always see: what we check before we feel comfortable putting a template in front of someone who expects it to work without a troubleshooting session. ## The First Install Is Not Enough The first successful install can be misleading. A template may work perfectly on a clean machine and still be risky to publish. The real question is whether it behaves predictably once reality begins: someone restarts the VM, reruns part of the installer, changes a domain later, or decides to move from “testing this” to “actually keeping this online.” That is why install idempotency matters so much. In practical terms, idempotency means a deployment process can be repeated without creating duplicate resources, broken state, or contradictory configuration. I do not expect every one-click template to be fully rerunnable from zero in every possible scenario. But I do expect it to fail cleanly, detect existing state properly, and avoid turning a second run into a repair job. A pattern that shows up often in template work is that the hardest problems are not in the main application. They are in the layer around it. The app starts, but the second run creates a second admin user. The service boots, but a reverse-proxy config gets duplicated. The container launches, but the volume path changes in a way the user does not notice until data disappears after an update. That is why “works once” is never enough. ## Default Ports Are Not Small Details Port choices look like implementation details until they collide with real usage. A one-click template is making an opinionated decision about exposure. If it binds directly to a common port, opens too much to the public internet, or assumes the user will never run another service on the same machine, the setup feels simple only until the second workload arrives. I think of default ports as a product decision, not a low-level technical choice. A good template should make it easy to understand: * which service is public * which service should stay internal * whether a reverse proxy is involved * what happens if the chosen port is already in use * how the user changes the port later without breaking the app This is where simple templates often become messy. The application itself is fine, but the network story is vague. That creates support questions that feel avoidable in hindsight. For one-click apps, I would much rather see a template make one clean exposure decision than try to be clever. A smaller number of explicit paths is easier to explain, easier to secure, and easier to recover when something goes wrong. If the deployment model benefits from isolation, that should be obvious from the start, especially when the app may later sit alongside other workloads on a [Linux VM](/products/linux-vm) or behind private networking. ## Credentials Should Be Clear, Not Clever Credential handling is one of the easiest ways to make a polished template feel unsafe. The user needs to know three things immediately after deployment: * what credential was created * where it is stored or shown * what they are expected to rotate or change first That sounds basic, but this is where one-click app experiences often fall apart. Some setups generate a password but bury it in a log. Others create multiple credentials without clearly separating app login, database access, and system-level access. The install technically works, but the first-login experience feels ambiguous. I prefer templates that are boring in the best possible way. If a secret is generated, it should be surfaced once, clearly. If the application creates an admin account, that path should be obvious. If there are post-deploy actions the user must take, those steps should be impossible to miss. The more “magic” a template uses around credentials, the more likely it is to confuse the exact person the template is supposed to help. This is also where the surrounding platform matters. If recovery or inspection is needed, the user should not have to guess how to get back into the machine. That is why I see browser-based recovery access as part of the quality story around app templates, not as a separate convenience feature. ## Upgrade Safety Starts on Day One A one-click template is easy to admire on launch day. The harder question is whether it still behaves like a product after the first update. For me, upgrade safety is not a future optimization. It is a publishing requirement. Before a template goes live, I want to know what happens when: * the app version changes * the container image changes * the service restarts * the VM reboots * a schema migration appears * the user expects their data to still be there afterward A template that hides all of that behind a clean first screen may look great in a demo, but it creates the wrong kind of surprise later. This is why storage paths, named volumes, service files, and config locations matter so much. They define whether the deployment can survive beyond the first session. A user should not need to reverse-engineer the app layout just to understand what must be backed up or what will persist after an upgrade. I think this is one of the biggest differences between “installer thinking” and “template thinking.” An installer tries to get software onto a machine. A publishable template should help the user keep that software alive, understandable, and recoverable. ## We Verify the First 15 Minutes, Not Just the First Click A lot of app-template QA focuses too narrowly on the deployment event itself. I think the more useful test is the first 15 minutes after deployment. That is where real clarity shows up. Can the user reach the app without guessing? Is the first-login path obvious? Are the credentials discoverable? Is the public endpoint where they expect it to be? Does the template leave behind a clean mental model of what just happened? I like to think of this as user-first verification rather than pure deployment verification. The deployment can be technically correct and still fail the user. A container starts, a service is active, and the health check turns green — but the person behind the screen is still confused about what to do next. That is not a good one-click experience. The templates that feel strongest are usually the ones that reduce explanation debt. They do not only work. They make their own structure legible. ## What We Treat as a Release Blocker There are a few issues I would treat as release blockers immediately. If the installer behaves unpredictably on a second run, that is a blocker. If the template exposes ports in a way that is hard to understand or easy to misuse, that is a blocker. If the initial credentials are unclear, inconsistently stored, or too easy to lose, that is a blocker. If a reboot changes behavior unexpectedly, if persistent data is not obviously persistent, or if the upgrade story is “we will figure that out later,” that is a blocker too. This may sound strict, but I think one-click products need that strictness. The entire value proposition is reduced friction. If the friction is merely postponed until five minutes later, the product has not actually done its job. ## Why This Matters More Than It Sounds It is easy to think of one-click apps as a convenience layer. I do not think that is quite right. They are a trust layer. When someone uses a one-click deployment, they are delegating decisions to the platform. They are accepting someone else’s opinions about app structure, networking, storage, defaults, and recovery. That is why template publishing standards matter so much. They determine whether the platform feels dependable or merely fast. On Raff, that matters because one-click applications sit inside a broader cloud experience built around virtual machines, storage, networking, snapshots, backups, and recovery paths. The template does not live on its own. It lives inside the user’s actual infrastructure decisions. That means the bar should be higher than “the app launched.” ## What This Means for You If you are using one-click apps, the most useful question is not “Can this install fast?” The better question is “Will this still make sense after I stop looking at the deployment screen?” That is the standard I would use when evaluating any template. Look for rerun safety. Look for clear defaults. Look for a visible credential story. Look for persistence that survives reboots and updates. And look for a deployment model that is still understandable once the first launch is over. If you want the broader framework behind that decision, start with our guide to [cloud-init, custom images, and one-click apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click). If you are evaluating the product side of the experience, explore [Raff Apps](/products/raff-apps). And if recovery matters to your workflow, read how our [browser VNC console changes VM recovery](/blog/access-your-vm-anywhere-with-our-new-vnc-console). That is the real standard I would use for publishing a one-click app template: not just “it deploys,” but “it stays understandable after deployment.” --- ### What We Learned Benchmarking Caddy vs Nginx on Small Cloud VMs URL: https://rafftechnologies.com/blog/what-we-learned-benchmarking-caddy-vs-nginx Published: 2026-04-20T00:00:00.000Z Description: What We Learned Benchmarking Caddy vs Nginx on Small Cloud VMs When people compare Caddy and Nginx, the conversation usually gets pulled toward ideology. One side says Nginx is the battle-tested default. The other says Caddy makes HTTPS feel like it belongs in this decade. After looking at both through the lens that actually matters on a small VM, I think the more useful question is simpler: which one gets a real app online with less friction, less overhead, and fewer opportunities to create your own incident? At Raff Technologies, that is the part I care about most on small cloud VMs. A 1 GB or 2 GB machine does not give you much room for unnecessary complexity. On a bigger server, you can afford extra moving parts and still feel fine. On a smaller VM, every extra daemon, every manual TLS step, and every late-night certificate problem feels heavier than it should. We already have a broader conceptual guide on [Caddy vs Nginx](/learn/guides/caddy-vs-nginx-reverse-proxy), plus hands-on tutorials for [installing Caddy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04), [installing Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), and [securing Nginx with Let’s Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). This post is narrower on purpose. I wanted to stay focused on what changes when the machine is small, the team is busy, and the reverse proxy is just one part of a real deployment. ## The Test That Actually Matters on a Small VM If you are serving millions of static requests per minute from a single node, the answer is easy: raw web server efficiency matters a lot, and Nginx has earned its reputation for a reason. But that is not the workload most small cloud VMs are running. Most small VMs are doing one of these jobs: * sitting in front of a single application * terminating HTTPS for an internal tool * serving a lightweight SaaS frontend * proxying traffic to Docker containers * exposing a staging environment * fronting an admin dashboard or API In those situations, I do not think the best first question is, “Which one wins the benchmark chart?” I think the better first question is, “Which one gets me to a safe, boring, maintainable default faster?” That is where the comparison becomes more interesting. > **Editor note:** Before publishing, add one small same-hardware results box here: 1 GB and 2 GB Raff VM, idle RSS, time to first HTTPS, static-file requests/sec, and reverse-proxy p95 latency. ## The First Surprise Was Not Performance The first surprise was that the practical difference showed up before any synthetic benchmark mattered. Caddy gets to a secure default very quickly. The biggest reason is not magic performance. It is the fact that HTTPS is part of the default experience, not a second project you remember to complete later. On a small VM, that changes the operational shape of the deployment immediately. With Caddy, the cleanest path is usually one service, one config file, and one domain pointed to the box. That sounds like a small convenience until you remember how many real deployments stall between “the app responds on port 3000” and “the app is actually online, encrypted, and renewable without babysitting.” Nginx can absolutely get you to the same destination. It has done that for years, and it does it well. But on smaller teams and smaller servers, the difference is that Nginx often asks you to think in two layers: first the web server, then the certificate workflow. That is not a flaw. It is just a different operating model. What changed my view on small VMs is this: setup friction is not only a productivity issue. It becomes a reliability issue. The more pieces you have to remember on day one, the more chances you create for day thirty to go wrong. ## Where Nginx Still Pulls Ahead This is the part where I do not think it helps to pretend both tools are equal at everything. They are not. Nginx still feels like the stronger default when you care about squeezing the most out of limited resources. If you are running on a very small machine and want the leanest possible footprint around a simple static or proxy workload, Nginx has a strong case. That matters most on the smallest VM sizes, where memory headroom is not theoretical. It is the difference between “everything feels fine” and “why is the box swapping under light load?” It also matters when the reverse proxy is doing more than simply passing traffic through. If your deployment needs more mature fine-grained control over request routing, traditional tuning patterns, or you already know the Nginx config model well enough to move quickly inside it, Nginx remains a very sensible choice. This is the trap I think people fall into: they hear that Caddy is simpler and assume that simplicity automatically makes Nginx obsolete. It does not. Simplicity is an advantage only when it solves a problem you actually have. If your problem is “I need the most familiar and efficient reverse proxy possible on a small machine,” Nginx is still hard to argue against. ## Why Caddy Feels Modern Faster What Caddy gets right is not just syntax. It is the order of operations. On small VMs, especially ones deployed by developers instead of full-time ops teams, the fastest path to a secure default often wins in practice. Caddy feels modern because it treats HTTPS as the baseline, not as a separate hardening task. That changes the emotional shape of deployment. You stop thinking, “I still need to finish TLS,” and start thinking, “The secure edge is already part of the service.” That matters more than many people admit. A lot of small-VM projects are not failing because their reverse proxy cannot handle enough traffic. They are failing because the deployment path becomes fragile: certificate renewal gets missed, redirects are inconsistent, the proxy config drifts from the app config, or the operator forgets which piece owns the public edge. Caddy reduces that risk by compressing more of the secure-by-default path into the server itself. I would also add that the configuration model helps more than benchmarks usually capture. On smaller teams, readability is a feature. A config you can scan in seconds is easier to maintain than one you have to mentally parse every time you open it. ## When the Simpler Config Wins There is a certain kind of workload where I would choose Caddy first without much debate. I would choose Caddy first for: * a single app on one VM * internal tools exposed to a team over HTTPS * dashboards and admin panels * lightweight APIs * prototypes that need to become production quickly * client proof-of-concept environments * small staging stacks where the point is to move cleanly, not to hand-tune everything In those cases, the simpler config is not just “nice.” It shortens the distance between deploying the app and trusting the deployment. That is a good trade. On Raff, this becomes especially practical because small workloads do not have to start on oversized infrastructure. If you are validating an app, a dashboard, or a lightweight service, you can start on a small [Linux VM](/products/linux-vm), keep the edge simple, and resize later if the workload grows. ## When I Would Still Pick Nginx First I would still pick Nginx first when the environment already speaks Nginx fluently. That includes: * teams with existing Nginx standards and templates * stacks that already depend on Nginx-centric patterns * memory-sensitive workloads on the smallest VM sizes * environments where you want maximum familiarity during debugging * situations where the reverse proxy layer will become more complex over time There is also a human factor here that is worth saying out loud: the best reverse proxy is often the one your team can operate confidently at 2 AM. If the team already knows Nginx deeply, switching to Caddy for elegance alone is not always a net win. Operational confidence is part of performance too. ## The Real Decision on a Small VM The most useful lesson from this comparison is that Caddy and Nginx are not competing only on throughput. They are competing on what kind of work you want the operator to do. Nginx asks for more explicit control and tends to reward that with lean performance and a mature operational model. Caddy asks for less ceremony and rewards that with faster secure defaults and less TLS-related friction. On a small cloud VM, that makes the choice feel less philosophical and more economic. If the machine is tiny and the app is simple, Nginx may buy you more breathing room. If the team is small and the goal is to get to a clean HTTPS deployment with fewer moving parts, Caddy may buy you something even more valuable: fewer chances to make a routine deployment messy. ## What This Means for You If you are deploying a single modern app and want the fastest path to a secure, readable reverse proxy, I would start with Caddy. If you are optimizing for the leanest footprint, already know Nginx well, or expect the edge layer to grow more complicated over time, I would start with Nginx. That is the practical answer. Not “Caddy is the future” and not “Nginx is always better.” Just this: on small cloud VMs, the right choice depends on whether your constraint is machine efficiency or operator attention. And in real deployments, both constraints are real. If you want the broader decision framework first, read our [Caddy vs Nginx guide](/learn/guides/caddy-vs-nginx-reverse-proxy). If you already know which direction you want to go, follow the setup path for [Caddy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04) or [Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), then add HTTPS with our [Let’s Encrypt for Nginx tutorial](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). If you still do not have the server yet, start with a [Raff Linux VM](/products/linux-vm) and keep the first deployment as simple as possible. That is usually where the best decisions get made. --- ### Why Small Teams Should Not Start With AWS by Default URL: https://rafftechnologies.com/blog/why-use-raff-instead-of-aws-a-better-way-to-launch-learn-and-build Published: 2025-05-12T00:00:00.000Z Description: Why Small Teams Should Not Start With AWS by Default ## Most startups should not start on AWS by default Most startups should not start on AWS by default. Not because AWS is weak, but because early teams usually need fast deployment, clear pricing, and infrastructure they can understand without turning cloud setup into a second product. For a lot of MVP-stage companies, AWS solves a later-stage problem before the current-stage problem is even clear. That is the real issue. AWS is one of the most capable cloud platforms in the world, but capability is not the same thing as fit. If your team is trying to launch an MVP, spin up a staging environment, run a client demo, or ship a small production app, the biggest risk is often not a lack of services. It is losing time and attention to infrastructure complexity before the product has earned it. At Raff Technologies, this is one of the patterns I keep hearing in conversations with smaller teams: they are not asking for a giant service catalog. They are asking whether they can launch quickly, know what they are paying for, and stay in control as the workload grows. That is a very different buying question from the one AWS was built to dominate. ## AWS is powerful, but power is not the same thing as a good starting point This is where I think a lot of startup infrastructure advice becomes misleading. AWS is powerful in exactly the ways a giant platform should be powerful. It has depth, breadth, regional scale, managed services, policy layers, and enough optionality to support companies at every stage. That is why it became the default answer in so many cloud conversations. But default is not the same as correct. For a small team, the cost of AWS is not only the invoice. It is the number of choices you have to make before useful work begins. Which service? Which instance family? Which storage shape? Which networking pattern? Which identity model? Which future abstraction do you need to plan around now so you do not regret the first decision later? A mature infrastructure team may see that as flexibility. A startup team often experiences it as overhead. That is why I think the better question is not “Is AWS powerful enough?” Of course it is. The better question is “Does this team need that much platform before it has even validated the product or workflow?” ## Startups usually need momentum first, not maximum optionality This is the part I care about most. A lot of MVP-stage teams think they are buying future-proofing when they start with a huge platform. What they are often buying is hesitation. They hesitate before launching a second environment. They hesitate before running a heavier test workflow. They hesitate before trying something temporary because they are not sure what it will cost or what it will touch. They hesitate because the infrastructure already feels like a system that must be respected, not a tool that helps them move. That is bad economics for an early product. At MVP stage, the company usually does not win because it made the most expandable infrastructure decision on day one. It wins because it learned quickly, shipped clearly, and avoided burning its best people on problems that did not matter yet. That is why I think small teams should optimize for: - understandable compute - clear pricing - simple deployment paths - practical storage - basic private networking when needed - and an upgrade path that grows with the workload instead of ahead of it That is a very different priority stack from “buy the cloud with the most services.” ## The wrong starting cloud creates hidden costs The biggest AWS cost for a small team is often not a billing line item. It is operational attention. A team without a dedicated platform engineer is already balancing product work, debugging, deployment, customer feedback, maybe sales demos, maybe internal tooling, maybe some support load. In that environment, cloud infrastructure should remove cognitive drag, not add it. But a broad platform can create drag in quiet ways: - onboarding takes longer - debugging requires more platform context - internal documentation gets heavier earlier - staging and production decisions become harder than they should be - pricing gets harder to explain to non-technical people - and every “simple” change turns into three architecture questions None of that means AWS is bad. It means the platform can ask for more operational maturity than an early team actually has. That mismatch is expensive, even when the invoice is still manageable. ## What small teams usually need first If I strip away the cloud branding and look at how early teams actually operate, the first needs are usually not exotic. They need: - one or two reliable environments - predictable VM-style compute - fast storage - a simple mental model for deployment - backups or snapshots when the workload becomes worth protecting - private networking only when the application or workflow really needs it - pricing they can explain without turning every deployment into a finance exercise That is why I still think a focused cloud platform is often the better first move. Start with the infrastructure you can understand. Use it to validate the product. Keep the architecture portable. Then add complexity when the workload proves it deserves more. That is a much healthier progression than starting with hyperscale assumptions and hoping the product catches up. ## When AWS is actually the right answer I do not think this should be an anti-AWS argument. That would be lazy. AWS is absolutely the right answer in some situations. If your team already knows AWS well, the learning curve cost is lower. If you need a specific managed service ecosystem from day one, the case changes. If your customer requirements already include enterprise security patterns, regional distribution, or provider-specific integrations, AWS may be the practical fit. If infrastructure itself is part of your competitive advantage, then platform depth can be worth the attention it demands. Those are real reasons. What I object to is not choosing AWS. It is choosing AWS automatically, before the workload or team has justified it. That is a very different position. ## The better startup question is not “Which cloud is best?” It is: **What is the simplest infrastructure that lets us ship confidently this quarter?** That question usually leads to better answers. If the honest answer is: - one app server - one database - one staging environment - basic storage - and a clear path to add more when the load increases then the best starting cloud is usually the one that makes that setup easiest to launch, easiest to price, and easiest to understand. If the honest answer is: - many managed services - broad internal platform patterns - strict provider integrations - or global infrastructure from the beginning then yes, AWS may be the right first decision. The problem is that a lot of startups answer the second question because it sounds more serious, even when they are actually living in the first one. ## Simplicity is not a step backward I think some founders worry that choosing a simpler cloud path means they are thinking too small. I see it differently. A simple starting point is often the more disciplined decision because it forces the team to earn complexity instead of inheriting it too early. That does not block growth. It usually improves it. A clean VM-based start is easier to reason about. A clean VM-based start is usually easier to migrate later than a stack built on too many provider-specific assumptions. A clean VM-based start gives the team better visibility into what the application actually needs before the architecture becomes expensive to change. That is not anti-scale. That is scale in the right order. ## What This Means for You If you are choosing cloud infrastructure for an MVP or an early SaaS product, I would keep the rule simple: Do not buy hyperscale complexity before your workload actually needs it. Start with the infrastructure your team can operate with confidence. Keep the architecture understandable. Let real usage, not startup anxiety, decide when you need more services, more abstraction, or more platform depth. For a lot of teams, that means starting with a straightforward [Linux VM](/products/linux-vm), understanding the actual pricing shape on the [pricing page](/pricing), and getting clearer about environment discipline with a guide like [Dev vs Staging vs Production in the Cloud](/learn/guides/dev-staging-production-cloud-environments). If your team is self-hosting tools or lightweight apps, a practical deployment path matters much more than platform prestige. That is the lens I would use. Not “Which cloud sounds strongest?” But “Which cloud helps this team move now without paying the complexity tax too early?” Because for most startups, the first cloud decision should not be about maximum possibility. It should be about minimum friction. --- ### Why We Include Unmetered Bandwidth on Every Plan URL: https://rafftechnologies.com/blog/why-we-include-unmetered-bandwidth-on-every-plan Published: 2026-03-26T00:00:00.000Z Description: Why We Include Unmetered Bandwidth on Every Plan The easiest cloud bill to trust is the one you can explain before it arrives. That sounds obvious, but it is surprisingly rare in infrastructure. Teams compare vCPU counts, RAM, and storage tiers in detail, then treat bandwidth as a footnote until the workload becomes real. By then, it is no longer a footnote. It is a source of hesitation, over-engineering, and sometimes outright fear about what a successful month might cost. That is one of the reasons we include unmetered bandwidth on every Raff plan. We did not make that decision because the phrase looks good on a pricing page. We made it because bandwidth overage billing creates the wrong behavior in the teams we are trying to help: they test less confidently, scale more cautiously, and design around invoice anxiety instead of application needs. ## The problem with bandwidth caps is not only financial Most people hear “unmetered bandwidth” and think “nice, that helps me save money.” Sometimes it does. But the bigger point is operational. A metered or tightly capped bandwidth model changes how teams behave. It makes them second-guess things they should be able to do comfortably: - serving more users after a launch - pushing more assets during a marketing campaign - shipping a media-heavy demo - running staging environments that mirror production - exposing APIs or dashboards without guessing whether normal usage will trigger a pricing surprise That is the real issue. A bandwidth cap is not just a number in the billing model. It is a design constraint that can show up before you are technically ready to think about it. From a risk perspective, that is unhealthy. Developers should spend their attention on performance, availability, and correctness. They should not have to translate every traffic spike into a pricing stress test. ## Why this matters more for smaller teams Large organizations usually have more tolerance for billing complexity. They may not like it, but they often have FinOps processes, multi-layer approvals, or internal controls that can absorb the mess. Smaller teams usually do not. Startups, solo developers, agencies, early product teams, and technical founders tend to operate with tighter margins and fewer people. In that environment, predictability matters more than elegance. A simple cost model is not a convenience feature. It is part of whether the platform feels usable under real pressure. This is why we think bandwidth policy belongs in the first infrastructure conversation, not the last one. If a team is trying to pick a cloud platform and can explain the compute price but not the traffic economics, that is already a warning sign. ## Unmetered is not the same thing as “infinite” This is an important distinction, and I would rather say it clearly than let the term become fuzzy. Unmetered bandwidth does not mean the laws of physics disappeared. It means the provider is not charging you in a granular transfer-based way that turns normal traffic growth into a line-item trap. It is about billing model and predictability, not fantasy infrastructure. That difference matters because the cloud industry often uses traffic language loosely. “Unlimited,” “unmetered,” and “included” are not always used with the same discipline. We prefer clarity here because vague promises create the same trust problem as vague pricing. The point is not to imply there are no network realities. The point is to remove a category of billing volatility that makes cloud decisions harder than they need to be. ## Why we think this is also a reliability decision My perspective on this is shaped by security and operational risk more than marketing. When teams fear traffic costs, they sometimes make defensive architecture decisions for the wrong reason. They avoid realistic staging. They reduce visibility. They compress or strip useful functionality too early. They hesitate to expose features because a successful response could feel financially ambiguous. That is not a stable way to operate. A safer infrastructure model is one where the normal, healthy use of the application does not feel like a billing threat. If users arrive, assets are served, and APIs are used, the team should be thinking about uptime, latency, and abuse prevention — not wondering whether this week’s traffic pattern quietly changed the business model. That is why I see unmetered bandwidth as partly a reliability choice. Predictable traffic economics reduce the chance that teams design around fear instead of engineering reality. ## Why we included it across every plan We made the decision across the plan lineup because the teams who benefit most from predictable bandwidth are often the teams least equipped to absorb surprises. If unmetered bandwidth only existed on premium tiers, it would fail the exact audience it is supposed to help. The early-stage team validating a product, the developer shipping a side project, the agency hosting a client build, and the startup trying to keep one environment simple all need predictability before they need sophistication. That logic is consistent with how Raff presents the platform publicly today. The pricing page highlights unmetered bandwidth alongside transparent pricing, 14-day money-back guarantee, and 24/7 support, while the broader site emphasizes fast deployment, Linux and Windows VM options, and modern AMD EPYC plus NVMe-backed infrastructure. Those signals all point in the same direction: reduce friction where smaller teams feel it most. ## What this changes in real infrastructure decisions When bandwidth is predictable, teams make cleaner decisions. They can choose a VM based on compute and memory needs instead of trying to compensate for a transfer cap they may or may not hit later. They can set up staging environments with fewer mental reservations. They can launch marketing pages, dashboards, internal tools, or early SaaS products without introducing bandwidth math into every deployment conversation. It also improves the way teams think about growth. A healthy cloud model should not punish success psychologically. If traffic starts rising because something worked, the primary questions should be: - do we need more application capacity? - do we need a caching layer? - do we need a reverse proxy or a load balancer? - do we need better monitoring? Those are good engineering questions. “Can we afford our users showing up?” is not. ## Where unmetered bandwidth does not replace good architecture This is also worth saying clearly. Unmetered bandwidth is not a substitute for proper design. You still need sensible application architecture, caching where appropriate, careful exposure of public services, and a realistic understanding of your workload. If you run a noisy design, a chatty application, or a badly optimized media path, unmetered bandwidth does not magically make that wise. It simply removes one billing distortion from the decision. In other words, the goal is not to encourage sloppy usage. The goal is to let teams optimize for performance and resilience without an avoidable transfer-metering penalty hanging over ordinary operations. ## This choice reflects who Raff is built for The strongest infrastructure decisions usually tell you who the product is trying to help. For us, unmetered bandwidth is part of a broader pattern. It sits alongside simple VM pricing, straightforward deployment, backups and snapshots, private networking, and a platform shape that makes sense for developers, startups, and smaller teams that need real infrastructure without hyperscale complexity. That does not mean Raff is the right fit for every workload. Some teams need larger service catalogs, more global regions, or deeper platform abstraction. That is a legitimate reason to choose another provider. But for the audience we care about, predictability is not a secondary feature. It is part of whether the platform feels usable and trustworthy in the first place. ## What This Means for You If you are evaluating cloud infrastructure, do not treat bandwidth policy as a minor footnote on the pricing page. Treat it as a product philosophy signal. A platform’s bandwidth model tells you a lot about how it expects customers to behave, what kinds of surprises it thinks are acceptable, and whether normal traffic growth will feel like progress or risk. That is why we include unmetered bandwidth on every Raff plan. It helps keep cloud decisions grounded in engineering reality instead of billing anxiety. If that matters to your team, start with [Raff pricing](/pricing), compare it to how you currently think about traffic costs, and then map that against the kind of workload you actually run on [Raff VMs](/products/raff-vm). If your architecture is starting to grow, pair that with our guide on [Load Balancing Explained](/learn/guides/load-balancing-explained) so your next scaling decision is driven by application needs, not invoice fear. --- ### Why We Think Pricing Simplicity Is a Product Feature URL: https://rafftechnologies.com/blog/why-we-think-pricing-simplicity-is-a-product-feature Published: 2026-04-19T00:00:00.000Z Description: Why We Think Pricing Simplicity Is a Product Feature ## Pricing is one of the first parts of the product people actually feel We think pricing simplicity is a product feature because pricing changes behavior. Not just buying behavior. Usage behavior. A lot of infrastructure companies still talk about pricing as if it lives outside the product, like it starts after the user has already made the technical decision. I do not think that is true. In cloud, the pricing model affects how confidently a team launches, tests, scales, duplicates environments, and explains spend internally. That means pricing is not just a finance topic. It is part of the user experience. At Raff Technologies, this is one of the ideas we keep coming back to. A product can be technically strong and still feel stressful to use if the pricing model is hard to predict. A team can like the dashboard, like the performance, and still hesitate before doing normal things because they do not trust what the bill will look like afterward. That hesitation is not a billing issue in isolation. It is a product issue. ## The problem is not only high pricing This is the first distinction I think matters. A pricing model can be expensive and still feel understandable. A pricing model can be cheap and still feel risky. That is why I do not think “simple pricing” means “lowest price wins.” It means the customer can build without doing mental accounting all day. If a team cannot answer basic questions like: - what this server will cost, - what changes the bill, - what happens when usage grows, - or whether a normal product decision might trigger an unexpected charge, then pricing is creating product friction. In cloud infrastructure, friction changes architecture. A founder delays a staging environment. A developer avoids spinning up something useful. A team underuses the platform because uncertainty feels more dangerous than limitation. That is not a finance-side effect. That is the product experience shaping engineering behavior. ## Confusing pricing makes teams build differently I think this is one of the least discussed truths in cloud. When pricing is too layered, too conditional, or too hard to explain, teams stop optimizing for what the product needs. They start optimizing for what the invoice might punish. That creates the wrong kind of discipline. Instead of healthy discipline like: - cleaning up unused environments, - sizing workloads properly, - or improving release safety, you get defensive discipline: - avoiding useful experiments, - delaying infrastructure upgrades, - treating growth like a billing risk, - or building around price anxiety instead of operational clarity. This is especially harmful for smaller teams. A large company may have enough budget, procurement support, and internal process to absorb pricing complexity for a while. A startup usually does not. For a startup, unclear pricing quickly becomes decision friction. And decision friction is expensive. That is why I think pricing simplicity is more than a trust signal. It is a productivity feature. ## The best pricing models reduce cognitive overhead This is the product design angle I care about most. Good infrastructure products do not only reduce technical effort. They reduce cognitive effort. You already ask a team to think about: - deployments, - environments, - reliability, - backups, - access, - monitoring, - performance, - and customer expectations. If pricing adds a second layer of complexity on top of all that, the product is increasing mental load right where teams need confidence. I think that is one reason pricing simplicity matters so much for cloud products. It reduces one of the most common silent costs in infrastructure: uncertainty. And uncertainty changes behavior more than most providers admit. A predictable platform feels safer to adopt. A predictable platform feels easier to explain internally. A predictable platform feels easier to grow on. That is product work. ## Simplicity is not a marketing word if it changes workflow A lot of companies use “simple” as branding. I am less interested in the word itself than in the effect. Does the pricing model make a startup more comfortable creating a staging environment? Does it make a small team less nervous about success? Does it make cloud infrastructure easier to budget without needing a specialist to decode the bill? Does it help an engineering lead explain spend to the founder without turning every technical choice into a finance conversation? If yes, simplicity is not just a message. It is functionality. That is why I see simple pricing in the same category as: - clean provisioning, - understandable VM sizing, - predictable networking behavior, - or clear backup options. All of those reduce hesitation. And infrastructure products become better when they reduce hesitation in the right places. ## Pricing should match how real teams actually use cloud This is where I think cloud pricing gets disconnected from reality. A lot of billing models make sense internally to the provider. They are easy to segment, meter, and package. But that does not mean they match how customers think or work. Real teams do not wake up asking: - which pricing dimension is easiest for the provider to calculate? They ask: - can I deploy this safely? - can I keep this environment alive without regret? - can I scale this without rethinking the whole platform? - can I trust that normal usage will stay normal on the bill too? That is why we think pricing should be evaluated like any other product design decision: not only by whether it is mathematically valid, but by whether it supports the customer’s real workflow. A pricing model that keeps people cautious in the wrong places is not helping the product, even if it looks sophisticated from the provider side. ## Why this matters even more for startups and small teams Smaller teams feel pricing friction faster. They do not have a separate finance team translating cloud cost into business language. They do not have endless room for duplicate environments, pricing surprises, or layers of managed overhead they cannot fully justify. They are making infrastructure choices while also shipping product, talking to customers, and trying not to run out of time. That is why startup-friendly infrastructure is not only about lower entry cost. It is also about lower uncertainty. A team should be able to understand the cost of getting started, the likely shape of growth, and the consequences of normal usage without feeling like every decision needs a billing risk assessment first. That is why I think pricing clarity is a product feature in exactly the same way onboarding clarity is a product feature. It changes whether the user feels ready to move. ## What this means for how we think about Raff This is one of the reasons we do not see pricing as separate from the rest of the product. If a pricing model makes a good infrastructure workflow feel stressful, then the product is not as strong as it looks. If the pricing model makes teams more confident to build, test, and scale, then it is doing real product work. That does not mean every pricing decision is easy. It does mean the standard should be clear. We should ask: - does this reduce billing anxiety or increase it? - does this help a team plan or make them hesitate? - does this reflect how smaller teams actually use cloud? - does this support trust, not just conversion? Those are product questions, not just commercial ones. And I think more infrastructure companies should treat them that way. ## What This Means for You If you are choosing infrastructure, I would look beyond the headline rate and ask a more useful question: **What kind of behavior does this pricing model push us toward?** Does it make your team more confident? Does it make testing easier or more stressful? Does it help you understand growth? Does it let you explain spend without turning every technical decision into a budgeting argument? If the answer is yes, that pricing model is doing more than billing. It is helping the product feel usable. And if the answer is no, even a technically strong platform can feel harder to adopt than it should. That is why we think pricing simplicity is a product feature. Not because it sounds good in a headline. Because in cloud, the way you charge people changes the way they build. --- ### Why One Good VM Still Beats a Fancy Stack for Early SaaS URL: https://rafftechnologies.com/blog/why-one-good-vm-still-beats-a-fancy-stack-for-early-saas Published: 2026-04-19T00:00:00.000Z Description: Why One Good VM Still Beats a Fancy Stack for Early SaaS ## Most early SaaS teams do not have a scaling problem They have a complexity problem. That is why I still think one good VM beats a fancy stack for a lot of early SaaS companies. Not forever. Not for every workload. Not because distributed systems are bad. But because most early teams are not losing time to a lack of orchestration. They are losing time to unclear environments, messy deploys, weak sizing decisions, fragile recovery, and infrastructure choices that were made for a future version of the company that has not actually arrived yet. At Raff Technologies, this is one of the patterns I keep coming back to: smaller teams usually get more leverage from infrastructure they can understand end to end than from infrastructure that looks advanced on a diagram. A clean VM setup with clear ownership, safe release habits, backups, and the right amount of headroom is often a better business decision than adopting a “modern stack” too early and then paying the operational tax for the next twelve months. ## A fancy stack often solves tomorrow’s problem by creating today’s This is the part I think startups underestimate. A fancy stack sounds responsible because it looks like preparation: - multiple services - multiple environments - managed layers everywhere - orchestration - extra network complexity - more tooling around deploys, observability, and service boundaries And sometimes that is exactly the right move. But the default assumption that “more advanced equals more ready” is where a lot of early SaaS teams go wrong. A fancier architecture usually means: - more places for config drift - more infrastructure to patch - more things to learn before debugging - more money tied up in duplication - more moving parts between code and customer value That trade can absolutely be worth it when the workload demands it. The problem is that most early SaaS products do not demand it yet. So instead of buying clarity, the team buys overhead. ## One VM is not “simple” if it is being used carelessly This is where I want to be precise. I am not arguing that early SaaS should stay naive. A single VM is only an advantage when it is used well: - the environment is understood - the deployment flow is repeatable - the database is handled responsibly - access is controlled - backups exist - recovery is not just a theory - the workload is actually sized correctly That last part matters more than people think. A badly sized single VM is not a clever startup move. It is just a small bottleneck with branding. But a well-sized VM with a clean release path, a clear boundary between staging and production, and good operational discipline can carry far more than many teams expect. This is one reason I keep seeing the same sequence make sense for early companies: - start with one well-run VM - make the environment predictable - separate staging when the risk becomes real - resize when the workload proves you need it - split services only when one box is genuinely becoming the wrong boundary That progression is not glamorous, but it is healthy. ## The wrong first upgrade is usually architectural When an early SaaS team starts feeling pain, the first instinct is often to upgrade the shape of the system. Maybe that means: - moving to multiple servers early - adding Kubernetes before deploy discipline exists - adopting managed services for everything - separating components before they are actual bottlenecks - or treating “future-proofing” as a reason to increase complexity immediately I think that is often the wrong first move. The better question is: **what is actually failing first?** If deploys are risky, fix the deploy path. If the server is undersized, fix the server size. If production and staging are blurred, fix the environment boundaries. If one workload is hurting another, then maybe it is time to split services. If one node truly becomes the wrong operational boundary, then yes, move beyond one VM. But the point is that architecture should follow proven pressure, not generalized anxiety. That is what early SaaS teams need most: infrastructure decisions made in response to real bottlenecks, not infrastructure decisions made to imitate a later-stage company. ## One good VM is often better for product velocity This matters just as much as cost. A lot of startup infrastructure conversations focus on scaling and reliability, which makes sense. But early SaaS also lives or dies on shipping speed. And a system the team understands well is usually a faster system to ship on. One good VM often wins here because: - the deployment path is shorter - the blast radius is easier to reason about - the team can debug issues without switching mental models constantly - cost is easier to understand - environment drift is lower - ownership is clearer That does not mean one VM is a permanent strategy. It means it is often the best **phase-appropriate** strategy. And phase-appropriate infrastructure is usually better for a startup than impressive infrastructure. ## Startups often buy reliability in the wrong order This connects to something I keep seeing more broadly. Teams do not usually fail early reliability because they stayed too simple for one month too long. They fail it because they added complexity before they added order. A bigger stack does not automatically create: - safer releases - clearer access control - better backups - better recovery - or stronger production discipline In many cases, it just makes the original weaknesses harder to see. That is why I think one good VM can be the more reliable choice in early SaaS. Not because it has more redundancy. But because it makes the real weaknesses visible sooner, and gives the team a chance to fix them before those weaknesses get hidden under platform layers. The less glamorous truth is that a clean environment, clear ownership, and safer release habits do more for early reliability than a lot of “serious” architecture ever will. ## The economics matter too This is where the blog gets intentionally contrarian. A lot of teams overpay for infrastructure not because they need more compute, but because they add more categories of infrastructure than their product currently benefits from. That can mean: - multiple always-on environments - premium managed layers before the workload is stable - orchestration before the team can operate it honestly - extra networking complexity before real private boundaries are needed - and duplicate services that exist mainly to create emotional comfort A single VM is often the better economic choice because it forces clearer thinking: - what actually needs to run, - what actually needs isolation, - what actually needs high availability now, - and what can still stay simple without increasing unacceptable risk. That does not only protect spend. It protects attention. And for an early SaaS team, attention is usually the scarcer resource. ## Simplicity is not anti-growth This is the objection I would expect. “If we stay on one VM too long, are we not just postponing the real architecture work?” Sometimes, yes. But postponing unnecessary complexity is not failure. It is often good judgment. The real mistake is not simplicity. The real mistake is staying simple **after the evidence changes**. If the product reaches the point where: - one server is clearly the bottleneck - environments need stronger separation - one workload is hurting another - uptime expectations require stronger traffic distribution - or the team truly needs a cluster model then the answer changes. But the answer should change because the workload changed, not because the startup wants to look more advanced. That is the distinction I care about most. ## What This Means for You If you are building an early SaaS product right now, I would ask a simple question: **Are you underbuilt, or just under-disciplined?** Those are very different problems. If your current setup is failing because one VM is truly the wrong boundary, that is useful evidence. Act on it. But if the real problems are: - messy releases - weak staging discipline - unclear secrets handling - no recovery confidence - or a server that is simply mis-sized then a fancier stack is probably not your first fix. For a lot of teams, the better move is still: - one well-run [Linux VM](/products/linux-vm) - a real staging boundary when it becomes necessary - clearer production access rules - backups that are actually usable - and infrastructure upgrades that happen one honest bottleneck at a time That is also why I think topics like [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size), [Single-Server vs Multi-Server Architecture](/learn/guides/single-server-vs-multi-server-architecture), and [SaaS Infrastructure Cost Breakdown](/learn/guides/saas-infrastructure-cost-breakdown) matter so much. They look less advanced than Kubernetes debates, but for early SaaS they are often much more important. One good VM is not a rejection of growth. It is a refusal to pay the complexity tax before the business actually owes it. --- ### What We Learned from Teams Migrating Off Overcomplicated Setups URL: https://rafftechnologies.com/blog/what-we-learned-from-teams-migrating-off-overcomplicated-setups Published: 2026-04-19T00:00:00.000Z Description: What We Learned from Teams Migrating Off Overcomplicated Setups ## The problem was usually not scale A surprising number of teams do not migrate because they outgrew simple infrastructure. They migrate because they outgrew **complicated infrastructure that was solving the wrong problem**. That is one of the clearest patterns we keep seeing. A team comes in expecting the story to be about scale, performance, or some advanced architecture requirement. But when you look closely, the issue is often something else: too many layers, too many moving parts, too many decisions made for a future version of the company that never actually arrived. At Raff Technologies, that has changed the way I think about infrastructure maturity. A lot of smaller teams are not struggling because they stayed too simple. They are struggling because they became complex before complexity was economically or operationally justified. The most interesting part is that these setups often look impressive on paper. Multiple services. Multiple environments. Managed layers everywhere. Extra networking. Extra deployment steps. More dashboards. More “platform.” But the daily experience behind that architecture is usually less impressive: slower iteration, higher fixed cost, weaker clarity, and a team that no longer feels sure which parts of the system are actually necessary. That is why I think overcomplicated setups are one of the most expensive forms of startup infrastructure waste. Not because complexity is always bad. Because complexity is expensive when it arrives before the business has earned it. ## Most teams were not overpaying for compute This is the first thing that stands out. When people talk about cloud waste, they often imagine oversized servers, unused storage, or expensive managed services. Those absolutely matter. But in a lot of migrations, the bigger issue is not a single bad line item. It is the cost of a whole system that became harder to reason about. The team is paying for: - more environments than they really use, - more services than they can explain clearly, - more deployment steps than they can trust, - and more architecture than their product actually needs. That is a different kind of overpayment. It shows up in money, yes. But it also shows up in time, release confidence, and the number of operational questions that start with “Wait, why do we even have this?” That is where overcomplication becomes dangerous. It does not only raise the bill. It makes the system feel heavier than the stage of the company. And once that happens, every future infrastructure decision gets harder. ## The setups were often designed for hypothetical scale This is probably the most common pattern. A team builds for what they think a serious company should look like: - multiple layers of separation, - more managed services than they can operationally justify, - orchestration before orchestration is necessary, - duplicated environments before release discipline exists, - or service boundaries that make the diagram cleaner but the workflow slower. The intention is usually good. Nobody is trying to waste money on purpose. They are trying to avoid future pain. But in practice, that future-proofing often creates present-day drag: - longer deployment paths - harder debugging - weaker cost visibility - more idle infrastructure - and a system that the founding team no longer fully understands end to end That is the point where “planning ahead” turns into operational debt. I think this is one of the biggest traps in cloud infrastructure. Teams assume the responsible thing is to build for scale before scale exists. Sometimes that is right. But much more often, the responsible thing is to build for **clarity**, then scale in steps once the bottleneck is real. ## The expensive part was usually duplicated confidence One of the clearest patterns is environment sprawl. A team has: - production, - staging, - preview infrastructure, - extra internal testing environments, - duplicate service layers, - and sometimes multiple versions of the same workflow just because no one wants to break the original one. On paper, this looks like maturity. In practice, it is often duplicated uncertainty. The team is not paying for reliability. It is paying for several slightly different versions of the same risk. And because those environments drift over time, the extra infrastructure does not always produce extra confidence. It just produces extra overhead. That is why I think environment duplication is often misunderstood. More environments are not automatically safer. They are only safer when the release process, ownership, and purpose of each environment are clear. Otherwise, the startup is paying to maintain infrastructure that mostly exists to reassure the team emotionally, not to reduce a real operational risk. ## Managed services were often chosen too early This is another recurring theme. Managed services can absolutely be the right choice. They are often the right choice. But we also keep seeing teams that adopted managed layers before the workload was stable enough to justify the premium, or before the team even knew which part of the stack needed abstraction and which part just needed a better workflow. The result is usually one of these: - the service is convenient, but overbuilt for the actual workload - the service cost multiplies across environments faster than expected - the pricing model becomes harder to reason about than the workload itself - or the team is still doing workaround engineering on top of a product that was supposed to reduce operational effort That is the part people miss. A managed product is not expensive only when the monthly bill is high. It is expensive when the team pays a premium **and still carries awkwardness**. That is why managed services are not automatically the wrong decision, but they are also not automatically the mature decision. The mature decision is the one that matches the workload and the team’s actual operating reality. ## Complexity was often hiding weak fundamentals This is the most uncomfortable pattern, but probably the most important one. A lot of overcomplicated setups were not overcomplicated because the workload truly demanded it. They were overcomplicated because the basics underneath were still weak. Instead of fixing: - unsafe release workflows, - weak staging discipline, - poor secret handling, - unclear access control, - or fuzzy recovery planning, the team added more layers. This creates a strange effect. The system looks more advanced, but the core risks are still there. In some cases, they get harder to see because the architecture is now large enough to distract from them. I think this is one of the reasons simpler setups often feel so much better after migration. It is not only that the bill becomes easier to justify. It is that the real problems become visible again. And once the real problems are visible, the team can fix the right things in the right order. ## The teams that benefited most were not the smallest This is worth saying clearly. This is not just a story about tiny startups that should have stayed on one VM forever. Some of the strongest cases for simplification come from teams that were already real: - they had customers, - they had traffic, - they had production workflows, - and they had reasons to care about reliability. But they were still carrying infrastructure designed for a larger or more operationally mature version of themselves. That is why this topic matters. Simplification is not immaturity. Sometimes simplification is the most mature move a team can make. It means the company is finally willing to ask: - what is actually serving the product, - what is just serving our anxiety, - and what are we maintaining because it is useful versus because it once sounded right? Those are very different categories. ## What usually improved after migration The most immediate improvement was not always lower cost, even though cost often improved. The first big improvement was usually **clarity**. The team understood: - where the application actually ran, - what needed to stay private, - which environment did what, - where the bottleneck really lived, - and which services were truly essential. After that, other gains usually followed: - simpler deployment paths - easier debugging - fewer duplicate systems - better predictability in cost - and stronger confidence when making the next infrastructure decision That sequence matters. Cost reduction is nice. Operational confidence is better. Because once a team gets operational confidence back, it stops making infrastructure decisions from a place of fear. ## What This Means for You If your current setup feels heavier than your company stage, I would not start by asking how to optimize the bill. I would start by asking a more direct question: **What are we paying for that no longer creates confidence, speed, or control?** That usually leads to better answers. Look for: - environments that exist without a clear purpose - managed products that still require too many workarounds - service boundaries that make the system harder, not safer - duplicated infrastructure that adds cost but not clarity - and architecture choices made for a hypothetical future instead of a current bottleneck If you find those patterns, the answer may not be “scale harder.” It may be “simplify honestly.” For a lot of teams, the healthier progression is still: - start with clear foundations, - size for the workload you actually have, - keep environments intentional, - separate what truly needs separation, - and only add heavier architecture when the evidence is there. That is one reason the practical guides around [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size), [Single-Server vs Multi-Server Architecture](/learn/guides/single-server-vs-multi-server-architecture), and [SaaS Infrastructure Cost Breakdown](/learn/guides/saas-infrastructure-cost-breakdown) matter so much. They are not “basic” topics. They are often the real decisions underneath infrastructure clarity. The teams that migrate off overcomplicated setups are usually not moving backward. They are moving from infrastructure that looks mature to infrastructure that is actually useful. And those are not always the same thing. --- ### Why Managed Services Are Not Always the Cheapest Decision URL: https://rafftechnologies.com/blog/why-managed-services-are-not-always-the-cheapest-decision Published: 2026-04-18T00:00:00.000Z Description: Why Managed Services Are Not Always the Cheapest Decision ## The cheapest infrastructure choice is often not the one with the lowest monthly price Managed services are not always the cheapest decision. They are often the easiest decision to justify at the beginning. The setup is faster, the operational burden looks lower, and the product page makes the trade-off feel obvious. For a small team, that can be exactly the right choice. But after a certain point, I think many teams stop comparing **service price** and start discovering **workflow price**. At Raff Technologies, we work close to the kinds of infrastructure decisions where this trade-off becomes visible. A managed product can reduce effort in the right environment. But it can also introduce a different cost profile: higher recurring spend, less control over behavior, more dependence on provider limits, and workflow decisions shaped by the service rather than by the workload itself. That is why I do not think the real question is “managed or self-managed?” The better question is: **what does this decision cost once your actual workflow, data shape, and operational habits are included?** ## The first mistake is comparing list price to server price This is the easiest trap to fall into. A team compares one managed database plan, one managed cache tier, or one managed platform product against the monthly cost of a VM. On paper, the VM looks cheaper. Then the conclusion comes quickly: self-managed is the bargain option. That comparison is incomplete. A managed service includes more than raw compute. It usually includes some mix of lifecycle management, backups, upgrades, built-in availability features, support expectations, or simplified operations. If you ignore those pieces, the comparison becomes unfair in one direction. But the reverse mistake is just as common. Some teams see a managed service as automatically cheaper because it reduces administration. That is also incomplete. A service can remove certain operational tasks while introducing new costs through pricing tiers, storage expansion, bandwidth rules, limited configurability, or an environment shape that no longer matches how the application actually behaves. So the honest comparison is not: **managed service price vs VM price** It is: **managed workflow vs self-managed workflow** That is a much harder comparison, but it is the only one that matters. ## Managed services are usually cheaper at the moment of adoption This is the part that makes the topic tricky. For many early workloads, managed services really are the cheaper decision in practice. Not because the monthly bill is lower, but because they save time at the exact stage when time matters more than optimization. If your team is small, your infrastructure knowledge is limited, and the workload is still changing every week, then paying more for simplicity can be the correct financial decision. A managed service can reduce setup friction, shorten time to production, and remove a class of mistakes your team is not ready to own yet. That is why I do not think the right message is “managed services are overpriced.” That is too shallow. The better message is: managed services are often cheaper **early**, but not always cheaper **over time**. The point where that changes depends on the workload. ## Where the cost starts to turn In my view, the cost balance starts shifting when one of four things happens. ### 1. The workload becomes predictable Managed services make a lot of sense when the environment is changing quickly. Once usage becomes stable, recurring managed premiums are easier to notice. A stable internal database, a predictable application stack, or a long-running service with known behavior is a very different financial case from an uncertain MVP. The more stable the workload becomes, the easier it is to ask whether the team is still paying extra for flexibility it no longer uses. ### 2. The team needs more control than the product shape allows This is where managed products become expensive in a less obvious way. Sometimes the issue is not the invoice. It is the fact that the service no longer fits the workflow: - limits are too rigid - configuration is too narrow - networking assumptions are awkward - scaling steps are coarse - operational visibility is weaker than expected Now the team is paying managed pricing while still doing workaround engineering. That is usually the moment when the “cheaper” story starts breaking. ### 3. The service multiplies across environments A single managed service can feel reasonable. Production plus staging plus preview plus regional duplication can feel very different. This is one of the least discussed cost multipliers in startup infrastructure. Teams often choose a managed product because one environment feels easy to justify. Later, the architecture becomes more responsible, which usually means more copies, more boundaries, and more supporting services. The managed convenience stays the same. The price shape does not. ### 4. The workload is simple, but the pricing is not This is my least favorite version of the problem. A team ends up running a straightforward workload on a service that has become financially complicated. The billing logic becomes harder to explain than the application itself. At that point, the service may still be operationally useful, but it is no longer honestly “simple.” That matters because pricing complexity is also workflow complexity. ## The hidden cost is often not infrastructure — it is fit A managed service becomes expensive fastest when it is a poor fit. That poor fit can show up as: - workarounds the team should not need - duplicated tooling around the service - awkward deployment steps - missing access patterns - or a mismatch between the application’s needs and the provider’s pricing logic This is why I do not trust generic advice like “always use managed databases” or “always self-host once you scale.” The right answer depends on what the service is actually doing for your team. A managed service is worth its premium when it removes real burden. It is not worth its premium when it removes one burden and creates three smaller ones that never make it onto the pricing page. ## Control has a cost too This is the part self-managed advocates often understate. Running your own service on a VM is not free just because the VM price is lower. You now own: - setup - patching - upgrades - recovery - monitoring - and the mistakes that come with each of those That means the right self-managed argument is never “it’s cheaper because the server costs less.” The right argument is: “it is cheaper **for this team and this workload** because the control we gain is worth more than the operational burden we take on.” That is a much more honest standard. ## What I would check before choosing managed vs self-managed If I were evaluating this the Aybars way, I would ask: ### Is the workload still changing fast? If yes, managed often keeps the team moving. ### Is the environment now stable and repetitive? If yes, self-managed becomes more worth testing seriously. ### Does the service fit the workflow cleanly? If not, the premium may no longer be justified. ### Are we paying for convenience we still use, or convenience we used six months ago? This is one of the best questions a growing team can ask. ### Can we operate the self-managed version responsibly? If not, the lower price is a trap, not a saving. That last one matters most. A self-managed stack that is cheaper but fragile is not really cheaper. ## What This Means for You If your team is trying to decide between managed and self-managed infrastructure, do not start with the sticker price. Start with the workload. Ask: - how stable it is - how much control you actually need - how many environments will carry the same cost model - and whether the service is reducing real effort or just delaying a decision For some teams, a managed service will absolutely be the right call. For others, the lower-friction choice at month one becomes the wrong economic choice by month twelve. The important thing is to evaluate the full shape of the decision, not just the line item. That is also why this topic connects naturally to the kinds of guides Raff already publishes around [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size), [Single-Server vs Multi-Server Architecture](/learn/guides/single-server-vs-multi-server-architecture), and [SaaS Infrastructure Cost Breakdown](/learn/guides/saas-infrastructure-cost-breakdown). The cheapest choice is rarely the most obvious one. It is the one that fits the workload, the team, and the stage of the company at the same time. Managed services can be the right decision. They are just not automatically the cheapest one. --- ### Why We Think Pricing Simplicity Is a Product Feature URL: https://rafftechnologies.com/blog/why-pricing-simplicity-is-a-product-feature Published: 2026-04-18T00:00:00.000Z Description: Why We Think Pricing Simplicity Is a Product Feature ## Pricing changes product behavior more than most companies admit We think pricing simplicity is a product feature because pricing is one of the first ways a user experiences your platform. Not the landing page. Not the dashboard. Not the provisioning speed. The bill. Or more specifically: the mental model behind the bill. At Raff Technologies, we have written recently about transparent pricing, unmetered bandwidth, hourly flexibility, and why we moved beyond a pure pay-as-you-go model toward something simpler. Those posts were not separate opinions about billing. They were really the same argument seen from different angles: pricing shapes user behavior, and the wrong pricing model can make a good product feel stressful to use. That matters more in cloud than in most software categories. A confusing interface is annoying. A confusing invoice changes how people build. When pricing is noisy, layered, or hard to predict, teams start designing around cost anxiety instead of product needs. They test less freely. They delay experimentation. They become cautious in the wrong places. Sometimes they over-engineer early just to avoid a future billing surprise. Sometimes they under-use the platform they are already paying for because they no longer trust what “one more workload” might actually cost. That is why I do not see pricing as a finance-only topic. I see it as product design. ## A product feature is anything that changes how confidently people use the platform I think this is where cloud companies sometimes get the framing wrong. They treat pricing as something that sits outside the product, like a commercial wrapper added at the end. Build the infrastructure, launch the control panel, define the SKUs, then let pricing explain the rest. But from the customer side, that division does not really exist. If a team cannot predict what a workload will cost, that uncertainty becomes part of the product experience. If bandwidth overages make a team hesitate before shipping or scaling, that hesitation becomes part of the product experience. If billing rules are harder to understand than the infrastructure itself, that confusion becomes part of the product experience. So for me, the question is not: “Is our pricing page clear enough?” The better question is: “Does our pricing model help people use the platform the way they actually want to use it?” That is a product question. ## Complicated pricing creates the wrong kind of discipline One of the most common defenses of cloud pricing complexity is that it teaches customers discipline. I understand the logic. If every resource has a narrow billing rule, then maybe teams will architect more carefully, clean up faster, and avoid waste. Sometimes that is true. But I think the more common outcome is worse. What complicated pricing often creates is not healthy discipline. It creates defensive behavior. A team avoids a useful staging environment because they are worried it will quietly expand the monthly bill. A developer delays testing a heavier workflow because they are not sure how usage is being counted. A founder becomes more focused on invoice avoidance than deployment speed. A small company starts making infrastructure choices based on billing fear instead of operational fit. That is not discipline. That is hesitation. And hesitation is expensive in a growing company. A lot of early cloud waste does not come from people being careless. It comes from people being forced to make decisions inside pricing systems that were designed for provider optimization first and customer clarity second. That is exactly why our recent post on unmetered bandwidth matters to me. The point was not just that “unmetered” sounds attractive on a product page. The deeper point was that bandwidth overage billing creates the wrong behavior in the teams we want to help: less confidence, more caution, and more architecture shaped by invoice anxiety than by application logic. That is a product problem, not just a pricing one. ## Simplicity is not the same as “cheap” This part matters. When I say pricing simplicity is a product feature, I do **not** mean the product should always be the cheapest option on paper. Cheap is a number. Simple is a user experience. A product can be low-cost and still feel risky if the billing logic is unpredictable. A product can be more expensive and still feel easier to trust if the pricing model is clear, stable, and aligned with real usage. That is why I think pricing simplicity should be judged by questions like these: - Can a customer estimate cost before launching? - Can a team understand what changed when usage changes? - Can a founder explain the bill to the rest of the company? - Can a developer spin something up without wondering if one mistake will trigger a hidden penalty? - Can growth happen without every technical decision turning into a billing puzzle? If the answer to those questions is yes, pricing is doing product work. If the answer is no, pricing is adding friction no matter how competitive the headline rate looks. ## The best pricing models reduce cognitive overhead This is the real product lens. Good infrastructure products do not only reduce technical effort. They reduce **cognitive effort**. That is one reason simple provisioning matters. It is one reason clear VM sizing matters. It is one reason sane defaults matter. And it is one reason pricing matters. A team already has enough to think about: - architecture, - deployment, - performance, - security, - environments, - backups, - observability, - customer expectations. They should not also need a second mental model just to understand what the platform is going to charge them for acting normally. If billing logic becomes a second architecture problem, the product is creating unnecessary work. That is why I think pricing simplicity deserves to be discussed alongside UX, reliability, and documentation. It affects user confidence in exactly the same way those things do. ## This is especially true for startups and small teams Large enterprises can survive bad pricing experiences longer than startups can. They have procurement layers, finance teams, and sometimes enough infrastructure experience to normalize the pain. Smaller teams do not. For a startup, pricing clarity affects real operating behavior much faster: - how many environments they keep alive, - how safely they test, - how confidently they scale, - whether they adopt a workflow now or postpone it, - whether infrastructure feels like leverage or like a source of hesitation. That is why I keep coming back to the same principle in Raff’s writing: the product should help smaller teams move with confidence, not force them to think like billing analysts before they can behave like builders. Raff’s public posts on simple cloud power, transparent pricing, and cloud cost comparisons all point in that direction. They are really saying the same thing: clarity is useful, and useful products reduce uncertainty where uncertainty slows people down. ## Why this matters to how we think about Raff This is one of the reasons pricing decisions at Raff are never just spreadsheet decisions. They are workflow decisions. We think about questions like: - Will this make customers more confident or more cautious? - Does this pricing rule match how real teams use infrastructure? - Are we charging in a way that makes the product easier to adopt, or harder to trust? - Are we creating incentives for healthier usage, or just more confusing bills? That is also why recent Raff writing can talk, without contradiction, about hourly flexibility, transparent pricing, unmetered bandwidth, and a simpler subscription model. Those are not random billing experiments. They are different expressions of the same product philosophy: remove unnecessary billing anxiety and make the platform easier to understand. I think more cloud companies should say this more directly: **pricing is part of the interface.** It may live on a different page. It may be owned by a different team internally. But to the customer, it is still part of the product. ## What this means for you If you are building or choosing infrastructure, I think the right pricing question is not only: “How much does this cost?” It is also: “What kind of behavior does this pricing model push me toward?” Does it make you more confident to test? Does it help you understand growth? Does it let you explain spend clearly? Does it reduce fear around success? Does it make the platform feel easier to trust? If yes, that pricing model is doing real product work. And if it is not, then even a technically strong platform can feel harder to use than it should. That is why we think pricing simplicity is a product feature. Not because pricing is branding. Not because “simple” sounds good in a headline. But because the way a platform charges you changes the way you behave on it. And in cloud, behavior is everything. --- ### Most Teams Add Caching in the Wrong Order URL: https://rafftechnologies.com/blog/most-teams-add-caching-in-the-wrong-order Published: 2026-04-12T00:00:00.000Z Description: Most Teams Add Caching in the Wrong Order If your cloud app feels slow, do not start with Redis. Most teams do. They hear the word “cache,” think about database reads, and jump straight to the most technical-looking option in the stack. In practice, that is often the wrong first move. At Raff Technologies, we think about caching as a delivery and complexity decision before we think about it as a tooling decision. The real question is not “Which cache should we add?” It is “Where is repeated work happening, and what is the simplest layer that can eliminate it?” Caching for cloud apps is the practice of storing reusable responses, files, or computed results closer to where requests happen so your infrastructure does less repeated work. That sounds simple, but the confusion starts when four very different layers get lumped into one idea: browser cache, CDN cache, reverse proxy cache, and Redis. They are not interchangeable. They solve different problems, create different trade-offs, and belong at different stages of growth. What surprises me is how often smaller teams choose the most operationally expensive option first. They add Redis before fixing static asset headers. They talk about cache invalidation before checking whether their browser caching is doing anything useful at all. They introduce application-level complexity when their actual bottleneck is that every user keeps downloading the same files or forcing the origin to regenerate the same HTTP response. That is the wrong order. ## The Problem Is Not a Lack of Caches The problem is that many teams do not separate delivery caching from application caching. Delivery caching is everything that helps reusable content get served faster before your application has to do work again. That includes the browser, the edge, and the reverse proxy. Application caching is what happens when the request has already reached your app and you want to avoid repeating expensive logic, queries, or computation. Redis lives here. That distinction matters because the closer a cache is to the user, the less work your stack has to do overall. It also usually means less infrastructure to manage. In other words, the earlier you can stop repeated work in the request path, the better the outcome tends to be for a small team. This is why I think many teams start in the wrong place. They treat Redis like the default answer because it looks serious and scalable. But “serious” is not the same as correct. A better caching strategy starts with the simplest layer that can solve the problem safely. ## Browser Caching Is the Cheapest Win Most Teams Ignore If your app serves JavaScript bundles, CSS files, fonts, images, icons, or versioned frontend assets, browser caching is usually the first place to look. I like browser caching because it removes repeated work without adding a new service, a new dependency, or a new failure mode. You are not changing your architecture dramatically. You are simply telling the user’s browser not to keep fetching the same thing when nothing has changed. That sounds almost too obvious, which is probably why teams skip it. But obvious wins are often the highest-leverage wins. When browser caching is configured well, repeat visits feel faster, pages become lighter on the origin, and your infrastructure stops paying for waste it created itself. That matters even more for small products where every layer of extra complexity costs real engineering attention. This is also where I think teams confuse “performance work” with “infrastructure expansion.” Sometimes performance is not about adding something. Sometimes it is about removing unnecessary repetition. Browser caching does exactly that. If your frontend assets are stable and versioned properly, there is a strong chance this should be your first caching improvement, not your fourth. ## CDN Caching Matters When Distance and Repetition Start Hurting The next layer I would think about is the CDN. A CDN becomes valuable when you have public content that many users request repeatedly and you no longer want your origin doing the same job over and over. It helps when traffic is geographically spread out, when static assets are getting hit constantly, or when you want an additional layer between public traffic and your infrastructure. What I like about CDN caching is that it solves two practical business problems at the same time. First, it improves delivery for users who are physically farther away from your origin. Second, it reduces repeated traffic pressure on the origin itself. That second point matters more than many teams realize. Better caching is not only about shaving milliseconds. It is also about reducing avoidable load so your application servers do less useless work. Once you look at caching this way, the decision becomes clearer. A CDN is not just a speed feature. It is an origin-efficiency feature. This is especially relevant when your application serves a lot of public assets, image-heavy pages, documentation, landing pages, downloads, or static frontend bundles. In that situation, asking your origin to serve every request directly is usually a poor use of compute. At that point, I would rather see a team improve browser and CDN behavior than rush into application-level caching they may not yet need. ## Reverse Proxy Caching Is the Layer Many Teams Underestimate This is where the conversation gets more interesting. Reverse proxy caching sits in a useful middle position. It is not as globally distributed as a CDN, and it is not as application-specific as Redis. It is often the right answer when repeated HTTP work is still happening at the origin boundary and you want to stop your app from regenerating the same responses again and again. That can apply to semi-static pages, anonymous traffic patterns, public API responses with short freshness windows, or content that changes occasionally but not continuously. I think teams underestimate reverse proxy caching because they usually meet reverse proxies first through TLS termination, compression, routing, or security. Caching feels like a secondary feature. In reality, it can be one of the most practical ones. If your app mostly speaks HTTP and your repeated work is still in the request-response layer, reverse proxy caching often gives you the cleanest next step. It reduces application pressure without immediately forcing you into a dedicated in-memory cache tier with its own operational logic. For a lot of small teams running on a [Linux VM](/products/linux-vm), this is a smarter progression. Start with good asset caching. Add edge delivery where it matters. Then let the reverse proxy handle repeated shared responses before you move deeper into application caching. That is a much healthier order than jumping straight to Redis because it feels more advanced. ## Redis Is Powerful, but It Should Earn Its Complexity To be clear, I am not against Redis. Redis is excellent when the repeated work truly belongs inside the application path. If you are caching expensive query results, session state, computed fragments, queue-related state, rate-limiting counters, or short-lived objects your application needs constantly, Redis can be exactly the right choice. But this is the point: Redis should solve an application problem, not a delivery problem. If your real issue is that users keep downloading the same static assets, Redis is the wrong first answer. If your real issue is that your origin keeps serving identical public files, Redis is the wrong first answer. If your real issue is that repeated anonymous HTTP responses are hitting the app unnecessarily, Redis may still be too deep in the stack. The deeper you go, the more complexity you introduce. Redis brings real operational questions with it: How do you invalidate stale values? What is the TTL strategy? What happens on a miss? What happens when stale data is acceptable versus dangerous? What breaks if Redis is slow or unavailable? What belongs in Redis and what belongs in the database? Those are good questions when the payoff is real. They are not good questions to volunteer early if a simpler layer could have solved the problem with less risk. This is where I think teams should be more disciplined. Redis is powerful, but power is not the same thing as priority. ## The Better Order for Small Teams If I had to reduce our view into one rule, it would be this: Start with the cache layer closest to the user that can solve the problem safely. For many teams, the better order looks like this: 1. Browser caching for static, versioned assets 2. CDN caching for public delivery and origin offload 3. Reverse proxy caching for repeated shared HTTP responses 4. Redis for repeated application or database work Not every workload follows that exact sequence. Some applications genuinely need Redis early because their bottleneck is already deep in the application layer. But most small cloud apps do not need to start there. Most need to get the delivery side right first. I prefer this order because it keeps architecture proportional to the actual problem. It delays avoidable complexity, reduces wasted compute, and gives teams a much clearer model for deciding what belongs at the edge, what belongs at the origin boundary, and what belongs inside the app. That is not just a technical advantage. It is an operational one. Small teams do better when performance improvements make the system simpler to reason about, not harder. ## What This Means for You If you are reviewing performance on your cloud app right now, I would avoid the question “Should we add Redis?” until you answer a more important one: Where is the repeated work happening? If the waste is static asset delivery, fix browser caching first. If the waste is public content being fetched from the origin too often, add a CDN strategy. If the waste is repeated HTTP responses at the origin boundary, improve reverse proxy caching. If the waste is repeated application or database work, then Redis starts to make sense. That is the order I would trust for most small teams. If you are building on Raff, that usually means starting with a simple [Linux VM deployment](/products/linux-vm), keeping an eye on cost and usage through [Raff pricing](/pricing), using [Object Storage](/products/object-storage) when static files and assets should move off the main server, and considering [Load Balancers](/products/load-balancers) when traffic patterns become broader than a single-node setup should handle. The key point is this: caching should remove repeated work with the least new complexity possible. The teams that get this right do not necessarily use more caching tools. They use the right cache layer at the right time. And in my opinion, that is how cloud performance decisions should be made. --- ### Why Virtual Machines Still Matter for Beginners in 2026 URL: https://rafftechnologies.com/blog/what-is-a-virtual-machine-a-simple-guide-for-beginners-2025-edition Published: 2025-05-30T00:00:00.000Z Description: Why Virtual Machines Still Matter for Beginners in 2026 ## Virtual Machines Still Matter More Than People Think A lot of beginners first hear the term “virtual machine” and assume it belongs to a more technical world than their own. It sounds like something for infrastructure teams, cybersecurity labs, or cloud engineers working at large companies. But in reality, virtual machines are still one of the most practical tools a beginner can learn in 2026. Not because everyone suddenly needs to become a systems engineer. Because VMs solve a very simple problem that shows up surprisingly early: you need a clean, flexible computer environment that is not trapped inside your personal machine. ## The real question is not “What is a VM?” Yes, technically, a virtual machine is a software-based computer that runs on top of physical infrastructure through virtualization. That definition is correct, but it is not the most useful way to understand why VMs matter. The better question is: **What problem does a virtual machine solve for a beginner?** That is where things become much clearer. A VM gives you a separate environment where you can install tools, test code, try operating systems, run applications, and make mistakes without turning your main machine into a mess. That is the practical value. And that value is much more relevant now than it used to be, because modern developer and learning workflows are heavier than many beginners expect. ## Your laptop is not always the best place to learn everything This is one of the biggest mindset shifts people go through. At first, it feels logical to do everything on your personal computer: - install every framework there - try every package there - test every script there - keep every experiment there That works for a while. Then the machine starts collecting too much: - conflicting dependencies - old packages - broken configurations - half-finished experiments - tools you no longer need - project setups that interfere with one another That is when the local machine stops feeling like a clean starting point and starts feeling like a pile of history. A virtual machine helps because it gives you separation. Instead of turning your laptop into the home of every experiment, you create a dedicated environment that belongs to a specific purpose. That one change makes learning and building much calmer. ## A VM is basically controlled freedom This is the simplest way I explain it to beginners. A virtual machine gives you freedom with boundaries. You can: - install a different operating system - break something and rebuild it - test software without risking your main machine - run development tools in a dedicated environment - learn Linux even if your laptop runs Windows or macOS - experiment with cloud workflows earlier than you otherwise could That is why VMs are such a strong beginner tool. They let you explore without putting every consequence on the machine you depend on every day. That freedom matters because beginners do not only need “access to tools.” They need safe space to learn what those tools actually do. ## Why VMs are still relevant in 2026 Some people assume VMs matter less now because containers, cloud platforms, and AI tools get more attention. I do not see it that way. In fact, I think VMs are still highly relevant because the environment problem has not disappeared. It has actually become more important. Modern workflows involve more moving parts: - code editors - package managers - databases - Docker or container tools - local servers - testing environments - automation scripts - AI-generated code that still needs somewhere clean to run That is a lot for one personal machine to carry well. A VM gives those workflows a cleaner home. And if that VM lives in the cloud, the benefits get even bigger: - you can access it from anywhere - you are not limited by your laptop’s hardware - you can resize later - you can rebuild when needed - you start learning real infrastructure habits earlier That is why I think VMs are still foundational, not outdated. ## Beginners usually need VMs for practical reasons, not abstract ones Very few people wake up and say, “Today I want virtualization.” They usually arrive at VMs through a more practical problem. ### 1. Learning Linux safely This is one of the strongest starting points. If you want to learn Linux, a VM is one of the best ways to do it. You can work in a real Linux environment without replacing your main operating system. That makes it easier to explore the terminal, package installation, file permissions, SSH, and server basics without putting your everyday machine at risk. ### 2. Testing code without polluting your laptop A VM is a clean space for trying frameworks, packages, and development tools that you do not want permanently installed on your main machine. That matters much more than people think, especially once you start moving across multiple projects. ### 3. Running workloads your machine is not ideal for Some people simply need more RAM, more CPU headroom, or a more dedicated environment than their laptop gives them. A cloud VM helps because the compute does not depend entirely on local hardware. ### 4. Learning cloud and server basics properly If you want to understand deployment, SSH, server setup, networking, backups, or infrastructure more seriously, a VM is one of the best entry points. It teaches the habits that sit underneath a lot of modern cloud work. ### 5. Building portfolio projects or internal tools A VM gives your project a stable home outside your personal machine. That matters when you want something to stay online, be accessible remotely, or feel more like a real environment than a local experiment. ## The hidden benefit is reproducibility This is something beginners usually appreciate later. A good environment is not only one that works once. It is one that you can understand, rebuild, and explain. Virtual machines help with that because they encourage a cleaner mental model: - this machine is for this project - this OS is for this purpose - these tools live here - this setup can be repeated That is a big improvement over “everything lives somewhere on my laptop and hopefully still works.” The more serious your learning becomes, the more valuable reproducibility becomes too. ## Cloud VMs make this more accessible than it used to be Years ago, working with VMs often felt heavier for beginners. Now it is much more approachable. On Raff’s current Linux VM pages, the public positioning is already much clearer and more beginner-friendly than many older VM products used to be: - deployment in under 60 seconds - full root access and SSH - 9 Linux distributions available - snapshots and backups available - NVMe-backed infrastructure - a 14-day money-back guarantee instead of confusing “free tier” wording That matters because beginners do not only need infrastructure. They need infrastructure that feels reachable. If getting started feels too slow, too expensive, or too confusing, most people stop before they actually learn anything useful. This is one reason I think practical cloud VMs are such a strong entry point now. They remove a lot of friction from the first serious step. ## A beginner does not need the biggest cloud platform first I think this is another important point. A lot of people assume that once they want to learn cloud or servers, they should immediately jump into the largest and most complicated platform possible. I do not think that is the best starting point for most beginners. Beginners usually need: - a clean machine - a clear operating system choice - the ability to connect over SSH - enough performance to run their tools - pricing they can still understand - backups or snapshots when they make mistakes That is a much smaller requirement set than a full hyperscaler operating model. That is one reason platforms like Raff make sense in this part of the journey. The goal is not to overwhelm a beginner with every possible cloud service. The goal is to make the first real infrastructure step useful and understandable. ## A VM is often the bridge between learning and building This is why I still think VMs are so important. A virtual machine often becomes the first place where someone stops only reading about infrastructure and starts actually using it. You move from: - watching tutorials - reading docs - installing random tools locally to: - creating an environment - connecting to a server - managing files - configuring services - understanding what runs where - learning how systems behave over time That is a very important transition. It is the bridge between curiosity and actual skill. And for a lot of developers, students, and early builders, that bridge still starts with a VM. ## What This Means for You If you are a beginner, do not think of a virtual machine as an “advanced cloud product.” Think of it as a cleaner workspace. If your laptop is getting messy, if you want to learn Linux, if you want to test things safely, or if you want your project to live outside your personal machine, a VM is still one of the most useful tools you can learn in 2026. At Raff, that is exactly how I think these machines should feel: practical, fast to launch, and useful early. Start with a [Linux VM](/products/linux-vm), use [snapshots and backups](/products/data-protection) when you need a safety net, and add layers like [object storage](/products/object-storage) or [private cloud networks](/products/private-cloud-networks) only when the project starts needing them. That is the better way to grow. Not by making infrastructure feel bigger than it is. By making it useful sooner. --- ### The Best AI Tool in 2026 Still Needs the Right Cloud Environment URL: https://rafftechnologies.com/blog/which-ai-tool-should-developers-use-in-2026 Published: 2025-11-12T00:00:00.000Z Description: The Best AI Tool in 2026 Still Needs the Right Cloud Environment ## The Best AI Tool in 2026 Still Needs the Right Cloud Environment Developers spend a lot of time asking which AI tool is best. ChatGPT, Gemini, open models, coding assistants inside the IDE, agent-style workflows, API-first setups — the market keeps getting better, faster, and more crowded. That is a useful question. But I do not think it is the most important one anymore. The more important question is this: **What kind of environment are you giving that AI tool to work with?** Because the truth is simple: even the best AI assistant does not remove the need for clean infrastructure. It still needs somewhere to generate, test, run, deploy, isolate, store, and ship real work. That is where many teams still underestimate the problem. ## AI tools are getting better, but they do not replace execution environments The first phase of AI for developers was about surprise. People realized these tools could write boilerplate, explain code, generate functions, summarize docs, and accelerate debugging. That was a real shift, and it is still happening. Now we are in a different phase. The tools are no longer the novelty. They are becoming part of the workflow. That changes the question from: - Which model is smartest? - Which tool writes better code? - Which assistant feels faster? to: - Where does this code run? - How do we test it safely? - How do we keep environments isolated? - How do we avoid turning the local machine into a bottleneck? - How do we move from AI-generated output to actual deployment? That is why I think the AI conversation is maturing. The bottleneck is increasingly not only the model. It is the environment around the model. ## A lot of developer workflows still break at the same point This is something I think gets hidden by AI hype. A model can generate code in seconds. That does **not** mean the team can validate, test, deploy, and manage it cleanly in seconds. In fact, AI often increases the need for better infrastructure discipline because it increases output volume. Teams generate more experiments, more scripts, more prototypes, more automation, more side services, more containers, and more deployment attempts. That has consequences. Suddenly the local machine is carrying too much. The dev environment becomes messy. One project interferes with another. Dependencies drift. Reproducibility gets worse. Testing becomes uneven. The gap between “AI wrote this” and “this is production-ready” stays large. That is the point where cloud infrastructure becomes more important, not less. ## The real value is not only AI assistance — it is AI plus clean execution This is the frame I care about most. An AI tool on its own is not the full workflow. It is one layer inside the workflow. The stronger setup looks more like this: - AI helps generate or refine the work - cloud infrastructure gives the work a clean place to run - environments stay isolated - deployment becomes repeatable - storage, networking, and backups stay separate from the developer laptop - the team can move from idea to implementation without polluting the local machine That is why I do not think the “best AI tool” conversation is enough anymore. The more useful comparison is: **AI tool + weak environment** versus **AI tool + clean cloud environment** The second combination wins far more often. ## The wrong mental model is “AI means I need less infrastructure” For some reason, a lot of people still assume AI reduces the importance of infrastructure because the tool itself feels abstract. But that is backwards. AI reduces some effort at the code-generation layer. It does not eliminate the systems layer. If anything, it makes good infrastructure more valuable because teams can move faster only when the surrounding environment can keep up. Think about what modern developers are actually doing with AI now: - generating internal tools - testing API logic - spinning up containers - building automations - writing scripts that touch production services - experimenting with self-hosted tools - creating background workers - deploying staging builds more frequently That is not less infrastructure pressure. That is more. The tool may live in a browser tab or IDE extension, but the consequences of using it well live in the runtime environment. ## This is where local development starts to strain Local machines are still fine for many things. But the more AI gets integrated into daily work, the more developers start using it to create workloads that are better off outside the laptop. That includes: - isolated dev servers - test environments - reproducible Docker-based workflows - background services - scheduled tasks - file-heavy pipelines - automation jobs - self-hosted tools that should not live on personal hardware This is one of the reasons cloud infrastructure matters more in the AI era than some people expected. Not because AI itself needs a VPS to answer prompts. But because developers are using AI to create more things that need a stable place to run. That changes the architecture conversation. ## The best teams are not choosing one tool. They are building a better system Another reason the old “which AI tool wins?” frame is getting weaker is that many good teams are not choosing one winner at all. They are mixing tools. Maybe one assistant is better for brainstorming. Another is better for coding. Another is useful because it is open or self-hostable. Another fits a specific IDE or workflow better. That is fine. The mistake is thinking the model choice alone defines productivity. It does not. The stronger teams are doing something else: they are building a workflow where AI and infrastructure work together. That means: - clean compute - isolated environments - practical storage - sensible networking - repeatable deployment paths - enough flexibility to keep experimenting without chaos This is a much more useful maturity model than obsessing over which assistant won this month’s benchmark argument. ## Why this matters so much to us at Raff This topic is directly relevant to how we think about the platform. We are not trying to compete in the AI model layer. We are trying to build the environment layer that makes modern developer workflows more practical. That is why our stack matters in this conversation: - [Linux VMs](/products/linux-vm) for isolated development and deployment environments - [Windows VMs](/products/windows-vm) where Windows-based workflows matter - [S3-compatible object storage](/products/object-storage) for backups, artifacts, assets, and file-heavy workloads - [private cloud networks](/products/private-cloud-networks) to keep internal traffic cleaner - [data protection](/products/data-protection) when experiments start becoming real workloads - a broader direction toward [Kubernetes](/products/kubernetes) and [Raff Apps](/products/raff-apps) as the platform grows That is the operator perspective I think is missing from generic AI tool posts. The AI assistant is not the whole story. The environment you give it is what determines whether the output becomes useful, reproducible, and scalable. ## The more AI output you generate, the more environment discipline matters This is the part that gets more important every month. If AI helps you produce more code, more prototypes, more scripts, and more automation, then your environment quality becomes a force multiplier or a failure point. A weak setup gives you: - faster mess - more brittle experiments - more local clutter - more deployment inconsistency - more confusion between “prototype” and “real workload” A strong setup gives you: - clean isolation - safer testing - easier collaboration - better reproducibility - a clearer path from experiment to shipped system That difference matters much more than people think. And it is one of the reasons I believe the “tool choice” discussion is gradually becoming secondary to the “workflow quality” discussion. ## So which AI tool should developers use? My honest answer is: use the one that fits your workflow best. But do not stop the decision there. If the tool helps you think better, code faster, document more clearly, or automate more aggressively, that is great. But the real leverage comes when that output can move into a cloud environment that keeps your work organized and repeatable. That is why I think the strongest answer is no longer: “Use ChatGPT.” or “Use Gemini.” or “Use open models.” The stronger answer is: **Use the AI tool that fits your workflow — and pair it with infrastructure that keeps the workflow clean.** That is a much more durable strategy than chasing a single winner. ## What This Means for You If you are evaluating AI tools as a developer or small team, keep using the model comparison as one part of the decision. But do not mistake it for the whole decision. Ask a better second question: - Where will the generated code run? - How will we test it safely? - How will we keep environments isolated? - How will we handle files, artifacts, and backups? - How do we move from AI-assisted output to something stable enough to ship? That is where infrastructure becomes part of the productivity story. At Raff, that is exactly the layer we care about. We are building the cloud environment around the workflow: [cloud servers](/products/linux-vm), [object storage](/products/object-storage), [private networking](/products/private-cloud-networks), and the platform pieces that help teams build faster without turning speed into chaos. Because in 2026, the best AI tool is still not enough on its own. The teams that win are the ones that pair AI with the right environment. --- ### Should You Run Kubernetes on a VPS? A Practical View for Small Teams URL: https://rafftechnologies.com/blog/run-kubernetes-cluster-on-vps-step-by-step Published: 2026-03-12T00:00:00.000Z Description: Should You Run Kubernetes on a VPS? A Practical View for Small Teams ## Kubernetes on a VPS Sounds Simpler Than It Feels Kubernetes on a VPS is one of those ideas that sounds almost perfect the first time you hear it. Lower cost than a managed platform. Full control over the nodes. A real cluster you can shape around your workload. And if you are trying to learn Kubernetes properly, it feels more serious than a local lab and more practical than reading docs in isolation. I understand the appeal. I also understand why so many developers search for step-by-step guides on this topic. But after spending enough time around infrastructure decisions, I think the more useful question is not “Can you run Kubernetes on a VPS?” Of course you can. The more useful question is: **should you?** That is a much better filter for small teams, because Kubernetes is not only a deployment method. It is an operating model. And once you install it on your own VPS infrastructure, the responsibility does not stop at getting the cluster to say `Ready`. ## The real attraction is not Kubernetes itself Most people are not actually attracted to Kubernetes for its own sake. They are attracted to what they hope it will solve: - cleaner deployment workflows - better workload separation - easier scaling - more resilience than a single Docker host - a real path toward modern infrastructure practices - a way to learn orchestration without paying managed-cluster prices too early Those are all valid reasons. That is why this topic keeps coming up. There is a real middle ground between “everything on one VPS with Docker Compose” and “fully managed Kubernetes platform with a long bill and a bigger learning curve.” A self-hosted cluster on virtual machines can absolutely live in that middle ground. But that only works if the team is honest about what Kubernetes adds, not just what it promises. ## Where the tutorials usually stop too early This is the biggest problem with most Kubernetes-on-VPS content. A lot of guides stop at cluster creation. They explain: - control plane - worker nodes - join commands - maybe K3s versus kubeadm - maybe a sample Nginx deployment And then they act as if the hard part is over. It is not. That is the point where the real work starts. A cluster that boots is not automatically a platform you can trust. The moment you want to run anything meaningful, you run into the parts that actually define the experience: - how traffic enters the cluster - how services talk to one another - how storage persists beyond pod lifecycles - how you back up state - how you monitor failures - how you recover when a node disappears - how you handle secrets, certificates, and upgrades - how much operational time the team is willing to spend That is why I do not think “step-by-step” is the strongest frame for this topic anymore. The stronger frame is operational honesty. ## K3s changes the equation, but it does not remove responsibility If you are a small team and still want Kubernetes on VPS, K3s is usually the place I would start thinking first. That is not because kubeadm is bad. It is because K3s is much closer to the shape many VPS-based workloads actually need: lighter, faster to stand up, and better suited to smaller environments where you want real Kubernetes behavior without carrying every bit of upstream complexity from day one. That said, people sometimes hear “lightweight” and translate it into “easy.” That is not the same thing. K3s makes cluster setup more approachable. It does **not** make networking, storage, ingress, upgrade planning, observability, or disaster recovery disappear. It simply gives you a more realistic starting point if your goal is to run Kubernetes without turning a small VPS cluster into a full-time side job. If your main goal is deeper upstream learning, maximum configuration control, or a path closer to standard Kubernetes internals, kubeadm is still valid. But for most teams who are not trying to simulate enterprise platform engineering on day one, K3s is the more practical choice. ## The first serious problem is usually networking A lot of people think the challenge in Kubernetes is “installing Kubernetes.” It usually is not. The first serious challenge is traffic design. You still have to decide: - how public traffic gets in - how internal services communicate - how DNS maps to workloads - how you expose applications safely - which things should never be public in the first place That matters even more on VPS infrastructure, because small teams often start with simpler assumptions and then discover that “simple” public exposure can become messy very fast. This is one reason I still think private network design matters before orchestration excitement. If your cluster nodes are on separate public paths with no clean internal network strategy, you are adding friction to a system that already has enough moving parts. That is why I usually think of Kubernetes on a VPS as a **networking decision** at least as much as a compute decision. At Raff, this is exactly why [private cloud networks](/products/private-cloud-networks) matter so much in the larger platform story. East-west traffic should feel deliberate. Sensitive communication between services should not be an afterthought. If the internal traffic model is weak, Kubernetes does not fix that. It simply gives you a more complex place to experience the weakness. ## Storage is where “stateless dreams” meet reality The next place reality shows up is storage. A lot of small teams start with the mental model that their applications are mostly stateless. Then real workloads appear: - databases - uploads - build artifacts - CMS media - internal tools with local persistence - queues - application data that cannot disappear with a pod restart That is where Kubernetes gets much less theoretical. Persistent storage in Kubernetes is its own layer of design. It is not a footnote. It is one of the biggest reasons small clusters feel more fragile than expected when people rush past the storage conversation. If you are self-hosting on VPS infrastructure, this gets even more important. Your cluster is only as calm as its stateful workloads are recoverable. That is why I think storage planning should come much earlier in the conversation. Before a team gets excited about replicas and ingress rules, it should be able to answer simpler questions: - where does data live? - how does it persist? - how does it get backed up? - what happens if a node dies? - what gets restored first? This is also where platform building blocks around Kubernetes matter more than Kubernetes itself. [Block storage volumes](/products/volumes) and [data protection](/products/data-protection) are not glamorous talking points, but they are exactly the things that separate a demo cluster from a cluster that can survive a bad day. ## A lot of teams should not start with Kubernetes at all This is the part some infrastructure people do not like saying out loud. A surprising number of small teams should not begin with Kubernetes. Not because Kubernetes is bad. Not because it is overhyped. Not because orchestration is not useful. But because the timing is wrong. If you are running: - one application - one internal tool - one API and one database - one staging environment - one project where the main problem is still shipping product then a single well-structured VM is often the better first system. A clean VM setup with good process management, backups, private networking where needed, and disciplined deployment habits is still a very strong operating model. In many cases, it will teach you more useful discipline than rushing into orchestration early. This is one reason Raff continues to treat [Linux VMs](/products/linux-vm) as a foundation, not a transitional product we expect people to outgrow immediately. A lot of teams do not need Kubernetes first. They need infrastructure that is fast to deploy, easy to understand, and flexible enough to evolve when the workload earns more complexity. That is a healthier starting point than adopting Kubernetes just because it feels like the “real” thing. ## So when does Kubernetes on a VPS make sense? I think it makes sense when at least a few of these become true: - you are running multiple services that need cleaner orchestration - you want real pod scheduling and service abstraction - you need a learning environment closer to actual cluster operations - you are willing to own the operating model, not just the installation - your team has enough infrastructure curiosity to debug cluster behavior calmly - you understand that storage, ingress, and recovery are part of the project It also makes sense for teams that are consciously choosing a lower-cost orchestration environment before moving to something more managed later. That is a real use case. A VPS-based cluster can absolutely be a meaningful step in that journey. But it only works well when the team is using Kubernetes to solve a real workload or real learning need — not just to borrow the status of “running Kubernetes.” ## Why we think about this carefully at Raff This topic matters to us for a reason. We have [Kubernetes](/products/kubernetes) on the public roadmap because the demand is real. Teams do want container orchestration. They do want a cleaner path from VMs to more structured workload management. And we think that need deserves a serious platform answer. At the same time, we do not think every team should be pushed there too early. That is an important distinction. A lot of platforms behave as if “more orchestration” is always the next obvious step. We do not see it that way. We think infrastructure should grow in the order that keeps the operating model understandable. That usually starts with: - clear virtual machines - good networking boundaries - practical storage - backups and snapshots - enough flexibility to shape the workload properly Only then does Kubernetes become the right next question. That is why I see our current stack and roadmap as connected. [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [block storage volumes](/products/volumes), [data protection](/products/data-protection), and the public Kubernetes direction are not random products. They are part of the same platform sequence. ## What I would tell a small team today If you are a small team thinking about Kubernetes on a VPS, my practical advice is this: ### Start with a clearer question than “How do I install it?” Ask: - What problem am I solving that a single VM cannot solve cleanly? - Do I need orchestration, or do I need better deployment discipline? - Am I willing to own the operational overhead? - Is the team trying to learn, or trying to simplify? Those answers will tell you much more than a cluster-install script ever will. ### If you are mostly learning Use K3s. Keep the cluster small. Do not pretend it is an enterprise platform. Learn ingress, storage, backups, and monitoring properly. ### If you are mostly shipping product Be stricter. A single VM may still be the stronger move. You can go very far with disciplined VM-based infrastructure before Kubernetes becomes necessary. ### If you are between those two states That is where VPS-based Kubernetes can make the most sense. Not as a badge. As a bridge. ## What This Means for You If you are evaluating Kubernetes on VPS infrastructure right now, do not make the decision based only on whether you can install a cluster. Make it based on whether the operating model matches your team. Kubernetes on a VPS is a real option. For the right workload, it can be a cost-effective, flexible, and educational path. But it becomes a good decision only when you are ready for the responsibilities that come with it: ingress, storage, monitoring, upgrades, backups, and recovery. At Raff, that is exactly how we think about the path forward. Start with infrastructure that is easy to understand. Use [Linux VMs](/products/linux-vm) when that is enough. Add [private cloud networks](/products/private-cloud-networks), [block storage volumes](/products/volumes), and [data protection](/products/data-protection) when the workload needs them. Then move toward [Kubernetes](/products/kubernetes) when orchestration becomes the right next layer, not just the most fashionable one. That is the cleaner way to grow. And if you are honest about what your workload really needs, it is usually the cheaper way too. --- ### Why We Shipped Object Storage Before Managed Databases URL: https://rafftechnologies.com/blog/why-we-shipped-object-storage-before-managed-databases Published: 2026-04-05T00:00:00.000Z Description: Why We Shipped Object Storage Before Managed Databases ## Why We Shipped Object Storage Before Managed Databases If you only look at feature checklists, managed databases probably seem like the more obvious thing to ship first. They are easy to market. Everyone understands the pitch. “We run PostgreSQL, MySQL, or Redis for you” is a very clean sentence. For a lot of cloud companies, that sounds like the natural milestone that proves the platform is becoming more serious. We did not see it that way. We shipped object storage first because we think infrastructure should be built in the order that makes the platform stronger, not just in the order that makes the homepage look more complete. And for us, object storage solved a more foundational problem earlier. ## The wrong way to build a cloud platform A lot of infrastructure roadmaps are shaped by optics. What looks good in a comparison table. What sounds more advanced in a launch post. What makes people say, “Okay, now this is a real cloud.” I understand the temptation. I really do. But we have tried to build Raff around a different principle: the next thing we ship should make the whole platform more useful, not just more crowded. If a feature introduces a lot of operational weight without improving the foundation underneath, it can make the platform look broader while actually making it weaker. That is the context behind this decision. We did not ask, “Which launch sounds bigger?” We asked, “Which layer makes more of the platform better right now?” For us, the answer was object storage. ## Object storage is more foundational than many people think Object storage sounds simple until you list the number of things that depend on it. Backups. Media files. Build artifacts. Static assets. User uploads. Exports. Logs. Generated files. Application blobs that should not live on the same disk as the VM that serves the app. That list cuts across a huge number of workloads. A team running one VM may already need it. A team running a web app almost certainly benefits from it. A team doing automation, CI, media handling, backup retention, or file-heavy application work starts needing it even faster. That is why we did not think of object storage as a side product. We thought of it as a platform layer. Once it exists, a lot of other things get cleaner. ## Managed databases are powerful, but they are not neutral This is the part people miss. Managed databases are not just “database hosting with nicer branding.” They are one of the most trust-sensitive infrastructure products you can ship. If you get a VM slightly wrong, a customer can often work around it. If you get object storage slightly rough around the edges, many users can still adopt it gradually. If you get a managed database wrong, the blast radius is much bigger. Because now you are taking responsibility for: - backups - recovery design - failover behavior - versioning - storage performance under real load - connection handling - maintenance windows - scaling expectations - the customer’s confidence that their data layer is safe That is not a feature I wanted to rush for the sake of sequence. We were not interested in launching a shallow managed database product just so we could say we had one. ## Object storage made more of Raff make sense immediately When we launched [object storage](/products/object-storage), it was not only about adding another SKU. It made the rest of the platform more coherent. A VM is useful on its own, of course. But modern applications should not force every kind of data onto the VM disk forever. Once object storage is in the platform, a more sensible application shape becomes possible: - your VM runs the application - your object store holds large files, assets, backups, and static data - your networking model gets cleaner - your recovery model gets cleaner - your architecture starts looking less like “everything on one server” and more like a real cloud system That is a more meaningful step than people sometimes realize. It is one reason I see object storage as infrastructure, not decoration. ## We wanted to launch a storage layer that people could use broadly There is another practical reason behind the decision. Object storage has a broader early-use footprint than managed databases for the kinds of teams Raff serves. A lot of users do not want us to run their primary database on day one. Not yet. They still want control. They are still testing. They are still deciding whether the workload belongs in a VM, a container, or a more opinionated managed layer later. But many of those same users absolutely do want: - a place to store backups - a place to keep media files - a place to serve static assets - a place to keep artifacts and exports - a simpler way to separate storage concerns from VM concerns That is a much wider adoption surface. And if you are building a young platform, that matters. It means the thing you ship first has a better chance of becoming part of many workloads instead of being reserved only for a narrower category of production users. ## S3 compatibility mattered a lot in this decision Another reason object storage came first is interoperability. We did not want to invent an awkward storage product that forced users into a Raff-specific habit just to do something basic. We wanted a storage layer that fit the way builders already work. That is why S3 compatibility matters so much. If the API is familiar, the integration story is easier. Existing tools make sense. Migration is easier. Scripts and workflows do not need to be reinvented. The product starts life as something useful, not something the user has to translate first. That is a strong platform move because it lowers friction immediately. And that is very different from shipping a feature that sounds impressive but still requires the user to adapt heavily to the platform. ## Shipping databases later was not hesitation. It was discipline. I want to be clear about that. Choosing not to ship managed databases first was not a sign that we underestimated them. It was the opposite. We respected the complexity enough not to rush it. A managed database service should not just exist. It should behave in a way that makes people trust it with something important. That means we needed the surrounding platform and operational assumptions to be ready for it. We needed the product direction to make sense. We needed to be honest about what should be foundational first. Object storage passed that test earlier. Managed databases are still an important part of the platform direction. They are already visible publicly on Raff’s site, and they are clearly part of where the platform is going. But I would rather launch them later and correctly than earlier and thinly. That is an easy decision for me. :contentReference[oaicite:2]{index=2} ## The order of launches says something about how we think This decision also says something broader about Raff. We are not trying to build the platform in the order that looks most dramatic in a pitch deck. We are trying to build it in the order that creates a stronger operating model. That means we care about the layers underneath: - virtual machines that are fast to launch and easy to reason about - networking that helps workloads stay cleanly separated - storage layers that let applications be structured properly - protection and recovery tools that make the platform safer to trust - higher-level services only when they are ready to carry real responsibility That is why [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), and [object storage](/products/object-storage) fit together so naturally already. They are not random product checkboxes. They are pieces of the same infrastructure logic. ## Managed databases are still important — just not first There is no anti-database message here. Managed databases are a very important product category. For many workloads, they are the right abstraction. They remove operational burden, standardize backups, simplify failover, and make scaling more approachable for teams that do not want to own every database operation themselves. That is exactly why they matter. And it is exactly why they deserved patience. If we had shipped managed databases first, before object storage, I think we would have been building the platform upside down. We would have been jumping to one of the most responsibility-heavy layers before establishing a storage primitive that many more workloads can use immediately and repeatedly. To me, that would have been the more shortsighted move. ## This is also about the kinds of teams we serve Raff is not being built only for giant platform teams. A lot of our users are developers, growing startups, lean engineering teams, and builders who need the cloud to be practical before it is theatrical. Those teams do not always need the biggest-looking launch first. They need the next useful layer first. A team with a VM and an app can benefit from object storage very quickly. A team with backups, uploads, artifacts, or static assets can use it almost immediately. A team trying to clean up how application data is shaped can use it without redesigning everything. That is a better first-use story. And if you are building a cloud platform that wants to be genuinely useful, not just loudly expanding, that matters a lot. ## What This Means for You If you are building on Raff, the practical takeaway is simple: we did not ship object storage before managed databases by accident. We shipped it first because we think good platform sequencing matters. A strong cloud platform is not only a list of products. It is a set of layers that make more sense together over time. Right now, that means you can already build around the pieces that are live and broadly useful: [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [data protection](/products/data-protection), and [object storage](/products/object-storage). And as higher-level layers like managed databases arrive, they will sit on top of a platform that already makes more architectural sense. That is how we want Raff to grow. Not by shipping the loudest thing first. By shipping the right layer first. --- ### Why We Moved Beyond Pure Pay-As-You-Go Billing URL: https://rafftechnologies.com/blog/why-developers-are-switching-to-usage-based-cloud-platforms Published: 2025-11-13T00:00:00.000Z Description: Why We Moved Beyond Pure Pay-As-You-Go Billing When we first thought about pricing Raff, pure pay-as-you-go looked like the obvious answer. It sounded modern. It sounded developer-friendly. And on paper, it matched the way many builders want to think: spin things up, use what you need, pay only for what ran. At a conceptual level, I still understand why that model is attractive. But building a cloud company teaches you something quickly: a pricing model does not have to sound good only in theory. It has to work in real life — for customers, for support, for operations, and for the platform itself. That is exactly why we moved beyond pure pay-as-you-go billing. ## The original idea made sense at first In the early stage, pay-as-you-go felt aligned with the kind of users we care about. Developers want freedom. Startups want flexibility. Small teams do not want infrastructure commitments before they know what the workload will become. That logic is not wrong. In fact, I think it is one reason usage-based cloud products became attractive in the first place. They remove the feeling of being trapped. They make experimentation feel possible. They lower the psychological barrier to launching something new. For a young infrastructure company, that is a very tempting place to start. And it was tempting for us too. ## But a pricing model has to survive contact with reality This is the part that matters most. What looks elegant in a pitch or on a landing page does not always hold up once real usage patterns show up. We learned that the hard way. Pure pay-as-you-go sounds fair because it implies perfect alignment between usage and cost. But in practice, it also creates a different set of problems: - cost perception becomes harder to anchor - billing expectations become less stable - users think in short bursts, even when their workloads are not actually short-term - platform planning becomes harder - pricing conversations become more reactive than intentional And most importantly, it does not always match how customers actually behave. A surprising number of workloads are not “launch for 30 minutes and destroy.” They are persistent. They are ongoing. They are the kind of projects that need a machine, keep the machine, resize the machine, and build on top of it. Once we saw that pattern more clearly, it became obvious that pure pay-as-you-go was not the best long-term foundation for Raff. ## The real issue was not flexibility. It was clarity. This is where I think many infrastructure companies make the wrong distinction. They assume the only alternative to pay-as-you-go is rigidity. That is not how I see it. The real question is: **Does the pricing model help the customer understand what they are buying and what it will cost as the workload becomes real?** That is where pure usage billing can become weaker than it first appears. Yes, it feels flexible. But flexibility without enough structure can create a different kind of friction. Teams start asking: - What will this actually cost if we keep it running? - Is this still the right configuration for next month? - Are we optimizing for usage or just reacting to charges? - How do I explain this model internally if the workload becomes more permanent? That uncertainty is not always visible in the first week. But it becomes much more visible once the project is no longer a temporary experiment. ## We realized our customers needed something simpler One of the things I care about most at Raff is reducing unnecessary decision fatigue. Infrastructure is already full of choices: VM class, CPU, RAM, storage, backups, networking, regions, architecture, growth path. If the pricing model itself also becomes something the user has to constantly interpret, the platform starts consuming too much attention. That is why we moved toward a simpler subscription model. Today, Raff publicly frames pricing around clear terms: - monthly - 1-year - 2-year Longer commitments come with bigger savings, and customers receive a detailed invoice at the end of each billing cycle. The platform also supports automatic and manual payment modes, with credits and account balance applied first before charging the payment method. That is a much cleaner model for the kinds of teams we serve. It is easier to understand. It is easier to explain internally. And it is easier to build on when the workload becomes something serious rather than temporary. ## We did not reject flexibility — we changed where it lives This is important. Moving beyond pure pay-as-you-go does **not** mean we stopped caring about flexibility. It means we stopped putting all of that flexibility pressure on the billing model alone. Instead, we think flexibility should show up in more useful places: - clear VM options - monthly, yearly, and 2-year terms - easy upgrades and resize paths - backups and snapshots when workloads become important - practical infrastructure layers like [Linux VMs](/products/linux-vm), [object storage](/products/object-storage), and [private cloud networks](/products/private-cloud-networks) That is a healthier version of flexibility. Because what most users really need is not billing chaos in the name of freedom. What they need is a platform that lets them start cleanly, understand their costs, and still adapt as the workload grows. ## Why this shift made more sense for Raff specifically I also want to be honest about something: a pricing model is not only a customer-experience decision. It is also an operating decision. If you are building real infrastructure, the platform needs a model that supports reliability, product development, support, and clear financial expectations without turning every active workload into a micro-billing event. That matters even more when your goal is not just to rent compute, but to build a platform people can trust. Raff today is already broader than just “a VM with a price tag.” The current public platform includes: - [Linux VMs](/products/linux-vm) - [Windows VMs](/products/windows-vm) - [object storage](/products/object-storage) - [data protection](/products/data-protection) - [private networking](/products/private-cloud-networks) And the broader direction includes more platform layers over time. That kind of platform benefits from pricing that is simpler, more stable, and easier to reason about than pure raw usage billing. ## Customer behavior taught us more than theory did This is probably the biggest lesson. In theory, developers say they want maximum freedom. In practice, many of them want something slightly different: they want **freedom without billing anxiety**. That is not the same thing. They want to know: - what they are paying for - how long it will make sense - what happens if usage grows - whether the platform still feels affordable next month, not just today That is why transparent pricing matters so much to me now. Not as a slogan. As a product standard. The pricing page should make sense. The billing cycle should make sense. The upgrade path should make sense. The invoice should make sense. That is a better customer experience than a model that sounds modern but becomes harder to interpret once the workload stops being temporary. ## Why I still think the original instinct was useful Even though we moved away from pure pay-as-you-go, I do not think the original instinct was wrong. It taught us something valuable. It forced us to ask: “How do we keep infrastructure from feeling heavy, rigid, or commitment-driven too early?” That is still the right question. We just learned that the answer was not “charge everything in the most usage-granular way possible.” The better answer was: build a pricing model that stays clear, supports different commitment levels, and still feels fair to the kinds of teams Raff is built for. That is a more mature answer. And honestly, a more useful one. ## Where the current Raff model is stronger I think Raff’s current public pricing model is stronger for a few reasons. ### 1. It matches how many real workloads behave A lot of customer workloads are persistent enough that monthly or longer-term pricing is easier to plan around than raw pay-as-you-go. ### 2. It is easier to explain internally Founders, developers, and small teams do not want to become infrastructure accountants. Clear terms are easier to communicate. ### 3. It creates better long-term trust When pricing is simple, the platform feels more trustworthy. That matters a lot more than people think. ### 4. It still leaves room for flexibility Monthly plans still exist. Longer terms simply reward predictability with better value. That is a much more balanced model than pretending every workload should be priced like a short-lived experiment. ## What This Means for You If you are evaluating cloud infrastructure, I would encourage you to look beyond whether a provider says “pay-as-you-go” or “subscription.” That label alone does not tell you enough. Ask better questions: - Will this pricing still make sense once my workload becomes real? - Can I understand my billing model without overthinking it? - Does the platform feel flexible in the right places? - Am I buying freedom, or just buying uncertainty with a modern label? That is the more useful filter. At Raff, we started with one instinct, learned from how the platform and customers actually behaved, and changed direction. Today, the public model is much clearer: choose a term, know the structure, and build on infrastructure that is designed to stay understandable as you grow. If you want to evaluate that model directly, start with the [pricing page](/pricing), then compare it with the practical infrastructure layers around it: [Linux VMs](/products/linux-vm), [data protection](/products/data-protection), and [private cloud networks](/products/private-cloud-networks). That is where the current Raff story makes the most sense. Not pure pay-as-you-go. Not rigid long-term lock-in. A clearer middle ground that actually works. --- ### Why Virtual Dev Environments Are Moving to the Cloud URL: https://rafftechnologies.com/blog/virtual-dev-environments-and-platform-engineering-in-2025-the-end-of-works-on-my-machine Published: 2025-11-24T00:00:00.000Z Description: Why Virtual Dev Environments Are Moving to the Cloud If you have ever lost half a day to a broken local setup, you already understand why virtual dev environments are becoming more important. Not because developers suddenly forgot how to use their laptops. Because modern software projects got heavier, more distributed, and more fragile than the old local-first workflow was designed to handle. That shift matters a lot to me, because I think many small teams still underestimate how much speed they lose to environment drift. We talk about developer productivity as if it is mostly about better tools, faster AI assistance, or stronger deployment pipelines. In reality, a surprising amount of friction still starts earlier: one laptop behaves differently, one runtime version is off, one missing dependency turns into a debugging session, and the team loses momentum before real work even begins. That is exactly why cloud development environments are becoming more relevant. And it is one of the reasons Raff’s infrastructure direction matters beyond just “hosting a server.” ## The laptop stopped being the best home for everything For a long time, the default assumption was simple: your laptop is where development lives. Your editor, terminal, containers, database, package managers, background services, credentials, browser sessions, and half-finished experiments all pile into one machine, and somehow that machine is supposed to stay clean, stable, and reproducible across every project you touch. That was already imperfect years ago. Today, it breaks down much faster. Projects are more dependency-heavy. Teams are more distributed. Environments need to be easier to recreate. Security expectations are higher. Collaboration is more asynchronous. And many builders are moving across multiple contexts at once: client work, startup work, testing, staging, demos, internal tools, automation, and production debugging. At some point, the problem is no longer “my laptop is underpowered.” The problem becomes: **why is my personal machine still acting like the source of truth for the whole environment?** ## “Works on my machine” is still a very real tax People joke about this phrase because it is familiar. But the hidden cost is more serious than the joke. When every developer environment is slightly different, teams lose time to problems that should not exist: - different language versions - hidden local dependencies - mismatched Docker behavior - conflicting ports - weird package leftovers - onboarding docs that get longer every quarter - local fixes nobody remembers well enough to document properly That is not just a setup annoyance. It is an execution tax. And for small teams, that tax hurts more because there is less slack in the system. A larger company may absorb a broken half-day here and there without much visible damage. A small startup, freelancer, or bootstrapped team feels it immediately. That is one of the reasons I think cloud-based dev environments are not just a “nice future trend.” They are a practical fix for a very old bottleneck. ## Virtual dev environments are really about reproducibility A virtual dev environment is not magic. It is just a much healthier operating model. Instead of treating one developer’s local machine as the environment, you define the environment intentionally and launch it in infrastructure that is easier to reproduce. That environment can live on a VM, in a container workflow, or in a hybrid setup where the repo and tooling define how the machine should behave. That changes the question from: “Can I get this working on my machine?” to: “How quickly can we recreate this working environment anywhere?” That is a much better question. Because reproducibility helps with almost everything that small teams struggle with: - onboarding - handoffs - debugging - temporary workspaces - client-specific environments - testing risky changes - recovering from local machine chaos - keeping project state separate from personal state Once you think about it this way, cloud dev environments stop looking like an advanced enterprise pattern and start looking like basic operational hygiene. ## Platform engineering matters, but smaller teams need the lightweight version “Platform engineering” is one of those terms that gets bloated quickly. At enterprise scale, it can mean internal developer platforms, golden paths, service catalogs, policy controls, and teams dedicated to making infrastructure feel like a product. That is real. But smaller teams do not need the full ceremony to get the benefit. For a lean team, platform engineering often starts in a much simpler place: - one reproducible environment - one clean VM pattern - one defined repo setup - one shared way to launch and connect - one predictable base for development and testing That is still platform thinking. It is just platform thinking at the right size. And that distinction matters, because too many infrastructure conversations are framed as if you either need full enterprise internal-platform maturity or nothing at all. In practice, most useful improvements start much smaller. ## Why this fits Raff’s audience so well This is exactly the kind of problem Raff’s audience runs into. Not giant platform teams with dozens of specialized engineers. The people we care about most are usually much closer to the problem: - developers switching between projects - hackathon teams - startups trying to ship without environment friction - students and bootcamp learners - freelancers working across multiple stacks - QA and test engineers needing clean labs - technical founders who cannot afford to lose days to setup drift These are the users who get punished the most by bad environment habits. They do not have extra time. They do not always have expensive local hardware. They do not have room for avoidable delays before demos, deployments, or deadlines. That is one reason I care so much about environment reproducibility. The smaller the team, the more expensive setup chaos becomes. ## Why we built Raff around clean infrastructure building blocks At Raff, we did not approach this from the angle of “how do we sell developers more cloud?” We approached it from a simpler question: **How do we reduce the amount of friction between needing an environment and actually having one that works?** That is a different product mindset. It is one reason our [Linux VMs](/products/linux-vm) matter so much to this conversation. They deploy in under 60 seconds, support full root access, and are built to be usable starting points rather than complicated infrastructure puzzles. That sounds basic, but it matters because a development environment loses a lot of value if the setup path is already slow or constrained. It is also why [private cloud networks](/products/private-cloud-networks) matter. Once development environments become shared, repeatable, or tied to real services, networking starts to matter much earlier than many people expect. Isolation, security groups, and clean internal communication are not only production concerns. They become relevant whenever a workflow stops being “just one laptop.” And it is why [object storage](/products/object-storage) matters too. Once workflows become more real, data stops belonging only on the same machine that runs the code. Artifacts, backups, test data, static assets, and environment-related storage patterns need a cleaner home. That is the bigger point I want people to see. Virtual dev environments are not a side trend. They are one more example of why infrastructure is becoming more layered, more intentional, and more workflow-aware. ## The real win is not convenience. It is momentum. A lot of people describe virtual dev environments as “more convenient.” That is true, but it undersells the real value. The real value is momentum. Convenience sounds optional. Momentum is not. If your team can launch a clean environment faster, hand it to someone else faster, test changes without local contamination, and get new contributors productive sooner, that is not just a nicer developer experience. That is a more effective delivery process. And for small teams, speed of execution is one of the few advantages you can actually protect. That is why I think “works on my machine” is not a funny little relic. It is a sign that the team is still relying on a workflow model that no longer fits the shape of modern software work. ## Where this trend is going next I think the direction is becoming clearer, not fuzzier. Development environments are moving toward being: - defined as part of the project - easier to launch in the cloud - less dependent on personal hardware - more integrated with containers and repo context - more secure by default - closer to the rest of the infrastructure lifecycle This is also where the broader Raff platform direction becomes relevant. Raff Apps and Kubernetes are both signals that the platform is moving beyond raw server creation toward more productized application and orchestration layers. That matters because development environments, application environments, and deployment environments are gradually becoming less separate than they used to be. The old model was: every developer crafts a machine. The newer model is: every project can define one. That is a healthier direction. ## What This Means for You If your team is still depending almost entirely on personal laptops for serious project setup, I would suggest asking a better question. Not: “Can our current machines handle this?” Ask: “Should our workflow still depend this much on personal machines?” That is the more useful question. If onboarding feels heavier than it should, if projects are difficult to recreate, if environment drift keeps eating time, or if collaboration keeps bumping into machine-specific weirdness, that is usually a sign that part of your workflow wants to move into the cloud. It does not have to be everything. But it probably should not be nothing either. If you want to explore that shift through Raff, start with the practical layers: [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [object storage](/products/object-storage), and the public [pricing page](/pricing). That will tell you a lot more about how the platform fits modern dev workflows than any generic “future of platform engineering” article ever could. That is how I think about this trend now. Not as a fancy enterprise idea. As the cleanest way for more builders to stop debugging their machines and start building on environments they can actually trust. --- ### Why We Made n8n Easy to Launch on Raff URL: https://rafftechnologies.com/blog/launch-n8n-in-minutes-on-raff-the-easiest-way-to-automate-your-workflows Published: 2025-12-01T00:00:00.000Z Description: Why We Made n8n Easy to Launch on Raff Automation tools are supposed to save time. Too often, they start by wasting it. That is the problem we wanted to solve with n8n on Raff. If you are a developer, operator, startup team, or even a solo builder, self-hosted automation is attractive for a simple reason: you want control. You want your workflows, your logic, your integrations, and your data to live in an environment you understand. But in practice, many people hit the same wall before they even build their first workflow: setup friction. Local Docker issues. Port conflicts. machine-specific weirdness. Environments that work once and break later. Laptops that go to sleep while workflows should still be running. That is exactly why we decided to make n8n easy to launch on Raff. ## The real problem was never n8n itself n8n is already a strong product. It is flexible, open-source, code-friendly when needed, and much more controllable than many hosted automation tools. It is one of the clearest examples of a tool that becomes more powerful the more technical your workflow gets. The problem is not the product. The problem is that too many people meet n8n through setup pain instead of through useful automation. That changes the first impression completely. Instead of thinking: “I can automate this process in an hour.” They end up thinking: “I guess I need to debug Docker, ports, volumes, reverse proxy, and persistence first.” That is not a workflow-automation problem. That is an infrastructure-experience problem. ## Why we thought this mattered at Raff At Raff, we try to pay attention to where builders lose momentum. That matters to me a lot, because in smaller teams momentum is one of the most important resources you have. If the first step feels heavier than it should, projects get delayed. Experiments get postponed. People settle for smaller workflows because the environment around the tool feels annoying. That is one of the reasons we built a dedicated [n8n VM offering](/products/n8n-vm) instead of expecting users to piece everything together themselves. This was a product decision, not just a packaging decision. We wanted the first experience of self-hosted automation to feel like: “my workflow is ready to start” not: “now I need a side quest in Linux setup.” ## Why n8n belongs on cloud infrastructure, not a laptop You *can* run n8n locally. For many people, that is where they start. And for lightweight testing, that is fine. But local-first automation breaks down quickly in real use. ### Workflows should not depend on your laptop being awake This is the most obvious issue. If your automations matter, they need to run continuously. Your laptop is not designed to be an always-on workflow system. It sleeps, reboots, disconnects, updates at the wrong time, and competes with everything else you are doing on the machine. An automation tool becomes much more useful when it lives in an environment designed to stay online. ### Clean environments matter more than people think A workflow platform becomes part of your operational stack. That means you want it in a stable, isolated environment — not mixed in with local development leftovers, temporary packages, random ports, and machine-specific quirks. This is one of those issues that seems small until you try to share the setup with a teammate or recreate it later. A cloud VM gives you a clean base. ### Self-hosted should still feel simple A lot of people hear “self-hosted” and assume complexity is part of the deal. I do not think that should be the standard. Control is good. Ownership is good. Customization is good. But none of those should require unnecessary setup pain if the platform around the tool is designed well. That is what we are trying to improve with n8n on Raff. ## What we actually built We did not build “automation hosting” as a vague concept. We built a practical way to get a real n8n instance running quickly on infrastructure that already makes sense for always-on automation. The current Raff n8n product page is built around a few points that matter directly: - your own n8n instance - no execution limits - full data ownership and control - support for custom nodes - cloud deployment without the usual setup hassle - protection options like snapshots and backups - infrastructure built on AMD EPYC, NVMe storage, and high-availability design Those details matter because they change what the user is actually buying. You are not just getting “a server with n8n on it.” You are getting a cleaner environment for automation work to live in. ## Why this is better than a generic VPS + manual setup story Could someone manually install n8n on a Linux VM? Of course. In fact, that option should absolutely exist for technical users who want full manual control. But the more interesting question is: **should that be the default experience for most users?** I do not think so. Because most people interested in n8n are not trying to become part-time infrastructure operators for fun. They are trying to automate work. That is why the default experience matters. The default should not force everyone through the longest path just to prove they are technical enough to deserve self-hosting. It should remove avoidable friction while keeping control where it matters. That is the balance we want. ## Where n8n fits in Raff’s broader platform story This is also important because I do not want people to think of Raff as “just a place to run n8n.” n8n is a great example of the kind of workload that fits our platform direction. Raff is being built around practical cloud layers: - [Linux VMs](/products/linux-vm) - [object storage](/products/object-storage) - [data protection](/products/data-protection) - [private cloud networks](/products/private-cloud-networks) - one-click and simplified application workflows through [Raff Apps](/products/raff-apps) That matters because automation does not live in a vacuum. Real workflows often touch: - APIs - databases - webhooks - internal services - backups - storage - networking boundaries - deployment environments So the real value is not only that n8n runs. It is that it runs on infrastructure that can still make sense as your workflows become more real and more important. ## What kinds of teams this actually helps I think this is especially useful for teams in the middle. Not giant enterprises with a platform team for every layer. Not purely no-code users who never want to think about infrastructure at all. I mean teams like: - developers automating GitHub, CI, alerts, and internal tools - startups connecting signup flows, CRM actions, and operations tasks - content teams pulling analytics and publishing workflows into one place - operators building approval systems or lightweight internal automations - technical founders who want self-hosted control without setup drag Those users do not need complexity for its own sake. They need a cleaner path from idea to working workflow. That is exactly where this product makes sense. ## The hidden value is momentum If I had to summarize the real benefit in one word, it would be: **momentum** A lot of infrastructure decisions are judged only by specs or pricing. Those matter, of course. But what gets underestimated is how much progress a team loses when the platform slows down the first useful action. With automation, that cost is even more visible. The value of n8n is not in “having n8n installed.” The value is in getting to actual workflows. If the infrastructure removes enough friction that a user gets from: “I should automate this” to “it’s already running” much faster, that is a real product advantage. And that is the part I care about most. ## What This Means for You If you are evaluating n8n right now, I would suggest asking a slightly different question. Not: “Can I install this?” Ask: “Where will this be easiest to keep running, easiest to trust, and easiest to build on later?” That is the more useful question. If you want local experimentation, local is fine. But if the workflows matter, if they need to run continuously, if you want cleaner setup, or if you are already thinking beyond a one-machine experiment, a cloud VM is usually the better home. That is why we built [n8n on Raff](/products/n8n-vm) the way we did. Not to make automation look more complicated. To make self-hosted automation feel more practical from the first click. --- ### Why Small Teams Should Stop Buying Cloud Like Enterprises URL: https://rafftechnologies.com/blog/raff-vs-big-cloud-providers-why-small-teams-need-a-developer-first-platform Published: 2025-08-12T00:00:00.000Z Description: Why Small Teams Should Stop Buying Cloud Like Enterprises Big cloud platforms are impressive. They are also often the wrong buying model for small teams. That is something I have become more convinced of over time, not less. If you are running a huge enterprise with multiple departments, dedicated infrastructure specialists, compliance layers, and a roadmap that depends on a broad catalog of managed services, hyperscalers make sense. They were built for that world. But most builders are not operating in that world. A startup with three engineers, a technical founder launching an MVP, a freelancer delivering client systems, a small SaaS team, or a growing business building internal tools does not need to buy cloud like a multinational company. And yet many still do — because the market trained them to think bigger automatically means better. I do not believe that. At Raff, one of the decisions we made early was not to build a miniature version of hyperscaler complexity. We built around the idea that most small teams need something more practical: a fast path to real infrastructure, pricing they can still explain later, and platform layers that make sense as the workload grows. ## The enterprise buying model leaks into everything One of the biggest problems in cloud right now is that enterprise assumptions leak into products that are also being sold to small teams. You can see it in the way some platforms are structured: - giant service catalogs - multiple pricing dimensions for a single workload - bandwidth rules that create invoice anxiety - setup flows that assume prior cloud fluency - architectural choices pushed too early, before the project even exists in a stable form From the inside, all of that may look like flexibility. From the buyer side, it often feels like friction. That is an important distinction. A product can be technically broad and still operationally wrong for the stage a team is in. In fact, that happens a lot. The platform is capable of everything, but the user only needs a small set of clean decisions to get moving. And when that gap is large enough, the “power” of the platform becomes a drag on the user. ## What small teams usually need first When people talk about cloud infrastructure, the conversation often gets pulled toward the largest possible use case. That is backwards. The right starting point is not: “What can this provider support at maximum scale?” It is: “What does my team need to launch, learn, test, and grow without unnecessary drag?” For most small teams, the early answer is simpler than cloud marketing makes it seem. They need: - a reliable virtual machine - clear pricing - enough performance headroom to run the stack - backups and recovery options that are easy to understand - networking that does not become messy the moment a second service appears - storage that fits the workload instead of forcing everything onto one disk - a platform that can become more capable later without becoming confusing now That is exactly the kind of problem we think about at Raff. Not “How do we look bigger?” But “How do we make practical infrastructure easier to start and easier to grow with?” ## Why we did not want Raff to feel like a small copy of big cloud There is a trap smaller infrastructure companies can fall into. They assume credibility comes from imitating the biggest names as closely as possible. Same language. Same product sprawl. Same complexity signals. Same feeling that the user should “graduate into” a complicated operating model as early as possible. We chose not to go that direction. Because if you are building for developers, startups, and growing teams, the goal should not be to recreate hyperscaler friction at smaller scale. The goal should be to remove the parts that make teams hesitate for the wrong reasons. That is why Raff’s foundation matters so much to me. We start with things that are immediately useful: - [Linux VMs](/products/linux-vm) - [Windows VMs](/products/windows-vm) - [object storage](/products/object-storage) - [private cloud networks](/products/private-cloud-networks) - snapshots and backups - pricing that stays understandable - infrastructure that feels like a tool, not a certification exam That is not a “less serious” cloud philosophy. I would argue it is a more honest one. ## VMs still matter — but they are not the whole story A lot of people first discover Raff through virtual machines, and that makes sense. VMs are still one of the most flexible ways to launch real workloads. You choose the operating system, control the stack, and shape the environment around the application instead of around a rigid hosting model. That is why VMs remain central. But if all people understand about Raff is “they rent VMs,” they are missing the real direction of the platform. The more useful view is this: VMs are the starting layer. The platform value comes from what sits around them. A VM becomes much more useful when it is surrounded by: - predictable billing - storage options beyond the root disk - data protection that is clear to operate - network isolation that does not feel bolted on - deployment workflows that can get simpler over time That is the difference between “server rental” and “cloud platform.” ## Storage is one of the clearest examples Traditional hosting tends to flatten storage into one simple idea: you have hosting space. Modern workloads do not behave that way. Application media, static assets, backups, build artifacts, logs, exports, and object-based application data do not all belong on the same server disk forever. If the platform makes you think that way, it is already encouraging the wrong architecture. That is one reason [object storage](/products/object-storage) matters so much in Raff’s shape. It changes how teams think about their applications. Instead of asking only: “Where is the server?” You start asking: “Which data belongs on the VM, and which belongs in a storage layer designed for scale and separation?” That is a healthier cloud model, and it becomes more important as the project becomes more real. ## Networking is where “small team cloud” often gets underestimated Another area where big-cloud thinking distorts the conversation is networking. Small teams are often told one of two incomplete stories: - either networking is too advanced to matter early - or they should immediately design as if they are operating a giant multi-region platform Neither is helpful. The truth is more practical. A lot of teams do not need advanced networking on day one. But once a stack becomes more than one public VM, networking matters quickly. Internal traffic matters. Environment separation matters. Isolation matters. Security boundaries matter. That is why [private cloud networks](/products/private-cloud-networks) are such an important part of Raff’s platform story. They let the platform grow beyond “a server with an IP” into something more structured and more operable. That matters for teams much earlier than many providers admit. ## The platform direction matters too Another reason I push back on the “just a VPS provider” label is that it ignores where Raff is going. The visible public direction already tells the story: - core VM infrastructure today - live object storage today - live private networking today - broader application and orchestration layers in the platform direction Two of those future-facing layers matter especially: - [Kubernetes](/products/kubernetes) - [Raff Apps](/products/raff-apps) I do not mention them because I think every small team needs them immediately. Most do not. I mention them because they show something important about how we think: the platform is being built to start simple and become more capable, not to trap users in a forever-basic hosting model. That is the difference I want people to see more clearly. ## Why the “small team discount cloud” framing is too narrow There is another misunderstanding I want to push against. Sometimes smaller platforms get framed as if they only exist to be a cheaper alternative. Price matters. A lot. But that is still too narrow. The better question is not: “Is this cloud cheaper?” It is: “Is this cloud shaped correctly for the team using it?” Because the wrong platform can be expensive even when the monthly line item looks reasonable. It becomes expensive in slower setup. In architectural confusion. In hidden billing tension. In overbuying complexity. In waiting to ship because the platform keeps asking the team to think like a bigger company than it is. That is why I think the best infrastructure for small teams is not the one with the biggest brand, the widest menu, or even the lowest advertised price. It is the one that helps the team move with the least unnecessary drag. ## What I think big cloud still gets right This is not an anti-hyperscaler argument. Big cloud providers are strong for real reasons. They earned that position. They are right when you need: - enormous global reach - very deep managed-service catalogs - specialized compliance patterns - extremely large-scale architecture options - procurement and enterprise alignment that smaller providers cannot match The mistake is not that those platforms exist. The mistake is assuming those strengths automatically make them the best first or second choice for teams that do not actually need that operating model yet. That is where I think the market still confuses size with fit. ## The more useful buying question If I could change one thing about how small teams evaluate cloud, it would be this: stop asking which provider looks the most complete in the abstract. Start asking which provider gives your team the shortest path from intent to working infrastructure — without creating long-term friction later. That is the better question. It forces you to evaluate: - whether the pricing model will still make sense once usage grows - whether the platform supports cleaner architecture as the stack expands - whether the product helps you launch now without making you rebuild later - whether the team can understand and operate it without becoming part-time infrastructure analysts That is exactly the lens I would use on Raff. ## What This Means for You If you are a small team, do not buy cloud the way an enterprise buys cloud. You do not need to prove sophistication by choosing the most complex platform in the room. You do not need to overbuy product surface just because it looks impressive on a comparison page. And you definitely do not need to accept billing models that make experimentation feel risky. What you need is a platform that helps you start cleanly and keeps making sense as the workload becomes more real. That is the standard I think infrastructure should be held to. If you want to evaluate Raff through that lens, start with the practical layers: [Linux VMs](/products/linux-vm), [object storage](/products/object-storage), [private cloud networks](/products/private-cloud-networks), and the public [pricing page](/pricing). Then ask whether that platform shape feels closer to the way your team actually works. That is a much more useful comparison than “big cloud versus small cloud.” For most small teams, the real question is simpler: Which platform helps us move now without making the next stage harder than it needs to be? --- ### Why More Modern Dev Workflows Start in the Cloud, Not on a Laptop URL: https://rafftechnologies.com/blog/why-cloud-v-ms-beat-local-machines-for-modern-dev-workflows Published: 2025-07-12T00:00:00.000Z Description: Why More Modern Dev Workflows Start in the Cloud, Not on a Laptop The local machine is still useful. It is just no longer the center of modern development work. That shift has been happening quietly for a while, and I think many teams feel it before they fully name it. Projects get heavier. Toolchains get messier. Environments drift. Teams work across locations, devices, and time zones. At some point, the laptop stops feeling like the best home for serious development and starts feeling like the narrowest part of the workflow. That is one of the reasons I think cloud VMs matter more than ever now. Not because local development is dead, but because more of the real work around modern software benefits from environments that are easier to reproduce, easier to resize, and easier to separate from personal hardware. ## The laptop was never meant to carry everything For a long time, developers got used to the idea that their main machine should do almost everything. Editor. Terminal. Containers. Databases. Background services. Build tools. Browsers. SSH keys. Test environments. Maybe even staging-like workloads. That model worked well enough when projects were smaller and stacks were simpler. But modern development is rarely that tidy. A single project might now involve: - application code - multiple services - Docker containers - a local database - a queue - background jobs - environment variables and secrets - different language runtimes - shared team conventions - production-like debugging needs Once all of that lands on one laptop, the machine stops being just a workspace. It becomes an operational dependency. That is where things start to break down. ## “It works on my machine” is still a real problem People joke about it because it is familiar. But the deeper problem is not the joke. It is the hidden cost. When each developer machine becomes its own unofficial environment, teams lose time to differences that should not matter: - slightly different OS versions - package drift - conflicting ports - toolchain mismatches - broken local dependencies - setup docs that grow longer every month That is not just an inconvenience. It is a drag on delivery. A cloud VM changes that because it gives the team a cleaner base to work from. You define the environment more deliberately, launch the same pattern again when needed, and reduce the number of invisible local differences shaping the result. That does not solve every engineering problem. But it removes one of the most common categories of avoidable friction. ## Cloud VMs make environments more reproducible This is probably the most important benefit, and it is still underrated. A good development environment is not only one that runs. It is one that can be recreated quickly. That matters for: - onboarding new developers - creating temporary environments for contractors - reproducing a bug on a clean system - isolating project-specific dependencies - testing without polluting a personal machine - preserving a known-good setup instead of rebuilding it from memory Once you start thinking this way, the value of cloud VMs becomes much clearer. You stop asking: “Can this run on my laptop?” And start asking: “How quickly can we recreate this environment if we need it again tomorrow?” That is a much healthier question for a modern team. ## Compute should adapt to the project, not the other way around Another reason cloud VMs are becoming more natural in development workflows is simple: projects change faster than laptops do. A machine you bought for general work last year may be fine for editing code and running a few services. But if the project suddenly needs more RAM, more CPU, a cleaner Linux base, or a better place to run containers and databases together, the laptop becomes the bottleneck. Cloud VMs change that relationship. Instead of shaping the project around fixed local hardware, you shape the environment around what the project needs right now. That flexibility matters more than people think. A team may not need a huge machine every day. But when they do need more headroom, the ability to launch it quickly matters. And when they no longer need it, they should not still be carrying that cost in physical hardware or personal machine complexity. That is one reason I think cloud infrastructure is becoming more attractive even for development work that is not “large scale” in the enterprise sense. ## Remote work made this shift more obvious Distributed work did not create the case for cloud VMs. It just made the weaknesses of local-only development much harder to ignore. When work happens across multiple locations and devices, local-machine dependency starts causing more friction: - environment mismatch between teammates - slower onboarding - difficulty resuming work across devices - more painful handoffs - less clean collaboration around setup and debugging A cloud VM does not magically solve collaboration. But it does make the environment easier to centralize, reproduce, and control. That is important. Because modern teams do not just need code collaboration. They need environment collaboration too. Once those environments become easier to share conceptually — even if each person still uses their own machine — the workflow gets cleaner. ## Safer experimentation is a bigger advantage than people expect There is another reason cloud VMs fit development work well: they are easier to treat as disposable. That matters whenever a developer wants to: - test something risky - try a new Linux distro or package setup - run a heavy toolchain - debug a strange environment issue - build a staging-like replica - spin up a project-specific machine that does not need to live forever On a personal laptop, risky experimentation carries emotional cost. You are not just changing an environment. You are changing **your machine**. That changes behavior. People test less boldly. They postpone experiments. They keep messy workarounds in place because the alternative feels annoying or risky. A cloud VM lowers that psychological cost because the environment can be treated more like infrastructure and less like identity. That is a powerful workflow improvement. ## The local machine becomes cleaner too One of the less obvious benefits of moving more dev work to cloud VMs is that it improves the local machine by removing what does not belong there. Instead of turning a laptop into a museum of half-used runtimes, abandoned containers, old databases, temporary scripts, and mismatched project dependencies, you can keep local work lighter and more focused. That leads to a healthier split: - your personal machine stays cleaner - project environments become more intentional - switching contexts becomes easier - onboarding becomes less personal and more repeatable That is good for productivity, but it is also good for reliability. A machine that carries less accidental infrastructure tends to create fewer avoidable surprises. ## Why this matters for small teams especially Large engineering organizations usually have enough operational structure that they can absorb some environment mess. Small teams do not. A startup with three engineers, a freelance developer working across clients, a technical founder building the product and the infrastructure, or a student team preparing a demo does not have extra process to waste. In those environments, environment friction hurts more. A broken setup is not just a broken setup. It is lost momentum. It is context switching. It is an extra half day. It is uncertainty right when someone was ready to build. That is why I think cloud VMs are especially powerful for smaller teams. Not because they need enterprise infrastructure. Because they need fewer invisible blockers. ## What this means for Raff At Raff, this way of thinking influences how we look at the platform. We do not think cloud VMs are only for “production later.” We think they are useful much earlier than that. A developer VM should be fast to launch, easy to understand, and flexible enough to support the real tools people use. That is why the basics matter so much: - current Linux distributions - fast deployment - full root access - snapshot and backup support - enough performance for real development work - pricing that does not feel punishing for experimentation The point is not just to rent a server. The point is to give builders an environment that feels more reproducible, more disposable, and more practical than trying to force every serious workload through one personal machine. That is also why I think [Linux VMs](/products/linux-vm) should be understood as part of a broader workflow, not just as infrastructure for production websites. They are also a clean place to build, test, isolate, and collaborate. ## The real shift is not technical — it is behavioral When I step back, I think the biggest reason cloud VMs are beating local-only development in more cases is not just that the infrastructure got better. It is that teams are thinking differently. They are becoming less attached to the idea that development must happen where the keyboard is. They are becoming more comfortable with the idea that the environment should be portable, reproducible, and shaped around the project rather than tied completely to one device. That is a healthier mental model. It leads to better setups. Cleaner handoffs. Less machine-specific weirdness. More flexibility in how teams work. And over time, I think that becomes one of the biggest quiet advantages in modern software delivery. ## What This Means for You If your team is still forcing every project to live entirely on local machines, I would suggest asking a more useful question. Not: “Can our laptops handle this?” Ask: “Should this workflow still depend this much on personal hardware?” That is the more important question. If the project keeps getting heavier, if onboarding is awkward, if local setups drift, if testing risky changes feels annoying, or if collaboration keeps bumping into environment issues, that is usually a sign that part of the workflow wants to move into the cloud. It does not have to be everything. But it should probably be something. If you want to evaluate that shift through Raff, start with the practical pieces: [Linux VMs](/products/linux-vm), the public [pricing page](/pricing), and the ways snapshots, backups, and clean VM provisioning can reduce development friction before production even becomes the main conversation. That is how I think about cloud VMs now. Not as a replacement for local machines in every case. As the better home for more of the work than most teams realize. --- ### Raff vs. Traditional Hosting: Why the Difference Is Bigger Than It Looks URL: https://rafftechnologies.com/blog/raff-vs-traditional-hosting-what-s-different-and-why-it-matters Published: 2025-07-01T00:00:00.000Z Description: Raff vs. Traditional Hosting: Why the Difference Is Bigger Than It Looks A lot of people still hear the word “hosting” and imagine the same thing everywhere. A server. Some specs. Maybe a control panel. Maybe a monthly bill. But that mental model is already outdated. At Raff, we are not trying to be a prettier version of traditional hosting. And we are not trying to be understood as “just another VPS provider” either. What we are building is a cloud platform that starts with practical infrastructure and grows with the teams using it. That difference matters more than it sounds. Because once you are actually building something real — a product, an internal tool, a test environment, a customer-facing app, an automation stack — the gap between “hosting” and usable cloud infrastructure becomes very obvious very quickly. ## Traditional hosting was built for a different era Traditional hosting products were built for simpler use cases. That does not mean they are useless. They still make sense for brochure sites, lightweight web pages, small CMS installs, and projects where the main requirement is “put this online cheaply.” But the model behind traditional hosting is usually optimized for: - fixed, long-term plans - shared environments - limited customization - panel-driven workflows - low operational flexibility That model worked well when most users just needed a place to serve a website. It is a much worse fit when you need infrastructure that behaves like part of your workflow. Developers, technical founders, SaaS teams, automation-heavy businesses, and modern product teams need more than a place to upload files. They need infrastructure they can launch quickly, shape around their stack, protect properly, and grow without hitting artificial walls. That is where traditional hosting starts to feel small. ## Raff was never meant to be “hosting with nicer branding” This is the point I think we need to communicate more clearly. Raff may be easy to discover through virtual machines, but that is only one layer of what we are building. Yes, VMs matter. They are still one of the cleanest, most flexible ways to launch and control infrastructure. Our [Linux VMs](/products/linux-vm) and [Windows VMs](/products/windows-vm) are an important part of the platform because they give builders a practical place to start. But the real idea behind Raff is bigger than renting a server. The idea is to give teams a cloud foundation that feels simple enough to start with and powerful enough to grow into. That means the right way to understand Raff is not: “a VPS provider with decent specs.” It is: “a cloud platform built around practical infrastructure layers.” That distinction changes everything. ## The difference starts with how you think about the workload Traditional hosting asks: “How do we fit your site into our model?” A cloud platform should ask: “How do we give your workload the building blocks it needs?” That is the mindset behind Raff. Sometimes that starts with a VM. Sometimes it expands into [object storage](/products/object-storage) for media, backups, static assets, or application data. Sometimes it means [private cloud networks](/products/private-cloud-networks) so workloads can communicate securely inside an isolated environment. Sometimes it means stronger data protection, snapshots, restore workflows, and cleaner deployment patterns. And that is exactly why calling Raff “just VPS hosting” misses the real product direction. ## VMs are the starting point, not the whole story Virtual machines are still one of the most useful infrastructure building blocks because they are flexible. You can choose the operating system. You can control the stack. You can deploy the software you actually want. You can adapt the environment to the way your team works. That is why VMs remain foundational to Raff. But the important part is what sits around them. A VM becomes much more valuable when it is part of a wider infrastructure model: - snapshots and backups - predictable billing - API-driven workflows - private networking - storage layers beyond the root disk - application deployment options that reduce setup overhead That is how a VM becomes part of a platform instead of just a rented box. ## Object storage changes what Raff means for real workloads One of the clearest signs that Raff is not just a hosting product is [S3-compatible object storage](/products/object-storage). Traditional hosting does not usually push you to think in storage layers. Everything tends to blur into “the hosting account.” Modern workloads do not work like that. Media files, build artifacts, backups, logs, database exports, static assets, and user uploads should not all be treated like they belong on the same server disk forever. That is exactly where object storage becomes important. Raff’s object storage is S3-compatible, built for scale, and positioned as a separate storage layer for exactly those use cases. That matters because it changes how teams can structure applications on the platform. You stop thinking only in terms of: “Where is my server?” And you start thinking in terms of: “How should my application be shaped?” That is cloud thinking, not traditional hosting thinking. ## Advanced networking is part of the platform story too Another major difference is networking. Traditional hosting often assumes the workload is simple enough that basic connectivity is enough. One server, one public endpoint, one narrow environment. That is not how more serious teams operate for long. Once a stack becomes real, networking starts to matter: which services can talk to each other, how isolation works, where internal traffic lives, how security boundaries are managed, how cleanly environments can be separated. That is why [private cloud networks](/products/private-cloud-networks) matter so much in Raff’s product direction. They make it possible to think beyond “one VM on the public internet” and start shaping real infrastructure: - isolated internal environments - multiple subnets - policy-driven communication - lower-latency internal traffic - better architecture hygiene as the system grows That is a very different category of value than shared hosting or basic VPS packaging. ## The platform is moving toward higher-level layers too Another reason I do not want Raff framed as “just a VPS host” is that the platform direction is already visible. There are two especially important layers here: - [Kubernetes](/products/kubernetes) - [Raff Apps](/products/raff-apps) Kubernetes matters because it signals where orchestration, container-based scaling, and more structured application operations fit into Raff’s future. Not every team needs Kubernetes on day one. In fact, many do not. But it matters that the platform is being built with that next stage in mind. Raff Apps matters for a different reason. It represents a simpler application layer on top of infrastructure — a step toward making deployment easier without hiding the infrastructure so completely that teams lose control. Today, the public positioning is around one-click deployable applications. Over time, that direction opens the door to a more abstracted application experience as well. That is why I think the right way to describe Raff is not: “hosting” and not even only: “VPS.” It is a cloud platform that starts from useful infrastructure and expands upward into more capable layers. ## Why this matters for builders right now This is not just a branding issue. It affects how people choose infrastructure. If you think Raff is only a VPS provider, you compare it too narrowly. You compare CPU, RAM, disk, maybe a few support details, and stop there. But that misses the real question: what kind of platform will this become for my team once the first deployment is already working? That is the question more builders should ask. Because many teams do not fail by picking the wrong first server. They create friction later by picking a platform that makes the next stage awkward. The right infrastructure decision is not only about what helps you launch. It is also about what still makes sense after growth begins. That is where the broader Raff platform story matters. ## Simplicity still matters — but simplicity is not the same as limitation One thing I care about a lot is that broader platform vision should not automatically mean more complexity. That is where many infrastructure products go wrong. They add more services, more pages, more terminology, more surface area — and the result is a platform that feels more “complete” internally but less usable from the customer side. That is not what we want. Raff should feel simple at the point where teams need simplicity most: the beginning. That means: - launching fast - understanding the offering quickly - knowing what the next step is - not needing a giant architecture diagram before shipping something useful But simplicity should not mean the platform stops there. The right product feels approachable on day one and still meaningful on day one hundred. That is the standard I care about. ## What I think people should understand about Raff now If I had to summarize the shift in one sentence, it would be this: **Raff is not trying to modernize traditional hosting. It is trying to make practical cloud infrastructure easier to start and clearer to grow with.** That is why the stack matters. VMs matter. Object storage matters. Backups and snapshots matter. Private networking matters. Upcoming orchestration and application layers matter. Each one is a sign that Raff is not being built around a narrow hosting model. It is being built around the way real teams move from: one machine, to one stack, to one product, to one actual infrastructure footprint. That is a very different direction. ## What This Means for You If you are evaluating infrastructure right now, I would suggest changing the filter you use. Do not just ask: “Is this cheaper than traditional hosting?” or “Is this just another VPS product?” Ask: “What kind of platform is this becoming?” “Will it still make sense after my first deployment?” “Can I start simple without being trapped in a small model later?” That is the better question. If you want to evaluate Raff through that lens, start with the foundations: [Linux VMs](/products/linux-vm), [object storage](/products/object-storage), [private cloud networks](/products/private-cloud-networks), and the public [pricing page](/pricing). Then look at the platform direction beyond the first machine. That is where the real difference is. Raff is not trying to be old hosting with newer words. It is trying to be the kind of cloud platform that gives builders a clean place to start — and a real place to grow. --- ### What July 2025 Taught Us About Where Cloud Infrastructure Is Heading URL: https://rafftechnologies.com/blog/what-s-new-in-cloud-and-infrastructure-july-2025-update Published: 2025-07-21T00:00:00.000Z Description: What July 2025 Taught Us About Where Cloud Infrastructure Is Heading July 2025 looked, on the surface, like just another month of big cloud headlines. More investment. More AI infrastructure talk. More regional policy noise. More pressure on providers to explain why they deserve to be trusted with workloads that are becoming more expensive, more sensitive, and more business-critical. But when I look back at that period now, I think it revealed something more important. It showed that cloud infrastructure is no longer judged only by raw scale. It is increasingly judged by a different combination: performance, control, pricing clarity, and how easy it is for teams to actually move. That matters a lot to us at Raff, because we are not trying to win by copying hyperscalers. We are trying to build infrastructure that makes more sense for the teams that need to move fast without getting buried in complexity. ## The cloud conversation changed in a meaningful way For years, the cloud market was dominated by one broad assumption: bigger platform equals better answer. That logic made sense for a long time. The largest providers offered the deepest service catalogs, the widest region footprints, and the most mature enterprise relationships. If you needed everything, they were the natural starting point. But by mid-2025, the market was showing signs of a different kind of maturity. Teams were asking sharper questions. Not just: “Who has the most services?” But: “Who gives us the right amount of infrastructure without unnecessary drag?” “Who helps us stay flexible as requirements change?” “Who keeps pricing understandable once the project becomes real?” “Who lets us keep more control without forcing us into a giant platform mindset?” That is not a small shift. That is the beginning of a healthier buying behavior. ## AI demand changed what people expect from infrastructure One of the clearest changes in 2025 was that AI stopped feeling like a side conversation and started changing infrastructure expectations directly. Even teams that were not building foundation models were affected by it. Why? Because AI changes the surrounding market in at least three ways: - it increases demand for high-performance compute - it makes storage and networking choices more visible - it raises expectations around scalability and response time In other words, AI does not only affect “AI companies.” It affects everyone buying infrastructure in a market where compute quality, deployment speed, and resource pricing matter more than before. That is part of why I do not think small teams can afford to treat infrastructure as an afterthought anymore. You do not need a giant platform. But you do need a platform whose economics and performance profile still make sense once your workload becomes more serious. ## Cloud buyers started caring more about control again Another signal that stood out in that period was the growing focus on control. Sometimes that appeared as sovereignty language. Sometimes it showed up as compliance pressure. Sometimes it was simply teams becoming less comfortable with being deeply dependent on one giant provider for everything. I think this is one of the most important long-term shifts. Because when buyers start caring more about control, they also start caring more about platform shape. They ask questions like: - Can I understand this pricing model clearly? - Can I move my workloads without rewriting everything? - Do I know where my infrastructure is running? - Can I choose simpler building blocks instead of being pushed into a giant stack? This is exactly where focused cloud platforms become more interesting. Not because they are “bigger.” Because they are often easier to reason about. At Raff, that way of thinking influences a lot of our decisions. We care about giving teams usable building blocks like [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [object storage](/products/object-storage), and [clear pricing](/pricing) instead of asking them to decode a massive product tree before launching something practical. ## Multi-cloud stopped sounding theoretical Another thing July 2025 reinforced for me was that multi-cloud thinking became more practical and less philosophical. For a while, multi-cloud was often discussed like a strategy deck concept. Something enterprises talked about because it sounded sophisticated. But what many teams actually wanted was simpler: they wanted optionality. They wanted to know they were not trapped. They wanted to choose the right platform for the workload. They wanted APIs, workflows, and deployment paths that did not force them into one model forever. That does not mean every startup suddenly needs a true multi-cloud architecture. Most do not. But it does mean buyers increasingly value infrastructure that fits into a broader strategy instead of limiting it. That is a very different mindset from the old “pick one giant platform and accept everything that comes with it” approach. ## The real lesson was not about Europe, Oracle, or OpenAI alone One thing I try to be careful about with market commentary is overreacting to individual headlines. A single investment announcement is not the strategy. A single partnership is not the future. A single policy push is not the whole market. The more useful question is: What do these headlines reveal when you step back? For me, the July 2025 answer was this: the market was rewarding infrastructure that feels more intentional. Intentional about performance. Intentional about cost. Intentional about control. Intentional about where the platform is going. That is the part I think founders and operators should pay attention to. Because a lot of cloud buying mistakes happen when teams optimize for prestige instead of fit. The biggest brand is not always the best operational decision. The broadest service catalog is not always the best starting point. And the cheapest headline number is definitely not always the best long-term value. ## What this changed in how I think about Raff When I look at those signals through Raff’s lens, I do not interpret them as “the market will automatically come to smaller platforms.” That would be lazy thinking. The real takeaway is more demanding. If focused cloud platforms want to matter, they need to earn that position by being clearer, faster, and more practical than the alternatives for the people they serve. That is how I think about Raff. We are not trying to imitate hyperscalers at smaller scale. We are trying to build something different: a cloud platform where teams can start with the fundamentals, stay in control, and keep moving without unnecessary friction. That is why we care so much about things that are easy to underestimate: - launch speed - understandable VM classes - storage and backup clarity - private networking that feels usable - infrastructure you can actually explain to your team - pricing that does not become a puzzle once the workload grows To me, that is what “cloud value” really means. Not just how much raw compute you can rent. But how clearly the platform supports the way you actually build. ## Smaller teams should read market shifts differently If you are a small team, a founder, an indie builder, or an early engineering group, market headlines can be misleading. They make it sound like the only meaningful cloud decisions happen at giant scale. But most real infrastructure decisions are much more grounded than that. You are usually deciding things like: - what should we launch first? - how much should we spend before usage justifies more? - do we need more services, or just cleaner infrastructure? - is our current platform helping us move, or just asking us to learn its logic? That is why I think smaller teams should read cloud market updates through a different lens. Do not ask: “What are the giants investing in?” Ask: “What does this trend tell me about what good infrastructure should feel like for my team?” That is a more useful question. ## Simplicity is becoming a stronger competitive advantage I believe this more now than I did a year ago: simplicity is not the opposite of serious infrastructure. It is one of the strongest signs of serious product thinking. When the market gets noisier, simpler products often become more valuable. When infrastructure gets more expensive, pricing clarity becomes more valuable. When teams get stretched thin, understandable workflows become more valuable. That does not mean “fewer features at all costs.” It means every piece of the platform should justify itself. That standard matters to me because there is a lot of fake simplicity in cloud right now. Products that look easy at the top and become messy underneath. Pricing that looks friendly until the surrounding costs show up. Infrastructure that looks flexible until you try to grow inside it. Real simplicity is harder than that. Real simplicity holds up after the first launch. ## What This Means for You If you are watching cloud trends, do not treat them like entertainment. Use them to improve your buying filter. The real lesson from that period was not that the cloud got louder. It was that buyers started asking better questions about value, control, and fit. That is a good thing. If you are evaluating infrastructure now, I would start here: - Do I understand how this platform will feel after the first deployment? - Will pricing still make sense if the workload grows? - Does the platform give me clean building blocks or just a crowded menu? - Am I choosing something because it is right for my team, or because it is the default name everyone recognizes? If you want to evaluate Raff through that lens, start with the fundamentals: [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [object storage](/products/object-storage), and the public [pricing page](/pricing). That will tell you much more about the platform than any generic cloud trend summary ever could. That is how I look at these market shifts now. Not as proof that smaller cloud platforms automatically win. But as proof that clarity, control, and practical value matter more than ever. --- ### How to Launch a Virtual Machine in Seconds (Without the Complexity of Traditional VPS Hosting) URL: https://rafftechnologies.com/blog/how-to-launch-a-virtual-machine-in-seconds-without-the-complexity-of-traditional-vps-hosting Published: 2025-07-13T00:00:00.000Z Description: How to Launch a Virtual Machine in Seconds (Without the Complexity of Traditional VPS Hosting) Most people do not delay launching a VM because they lack ambition. They delay because too many infrastructure products make the first step feel heavier than it should. That has always bothered me. If you are a developer, founder, freelancer, or small team, your first server should feel like momentum. It should feel like progress. It should not feel like you just enrolled in a part-time course on legacy hosting terminology, pricing traps, and unnecessary setup friction. That frustration is one of the reasons we built Raff the way we did. ## The real problem was never the virtual machine A virtual machine is not a hard concept. You choose a configuration. You pick an operating system. You launch it. You connect. You start building. That is the basic promise. But in practice, many traditional VPS experiences wrap that simple workflow in too much friction. Confusing dashboards. Pricing that feels low until you start adding the basics. Platform language written for people who already know the system. Product decisions that make sense internally, but not from the customer’s side. For experienced infrastructure teams, some of that complexity is tolerable. For everyone else, it creates drag. And drag matters more than many cloud companies admit. If your first infrastructure decision costs you an extra afternoon, interrupts a project sprint, or makes a founder postpone testing an idea until “later,” that is not a small UX issue. That is lost momentum. ## What small teams actually need from a first VM When I think about the teams we want to help at Raff, I do not start with the question, “How many features can we stack onto a VM page?” I start with a simpler question: What does someone actually need to get moving without second-guessing the platform? Usually, it comes down to a few things: - fast provisioning - clear resource choices - predictable pricing - full control once the machine is live - confidence that the platform can still grow with them later That is a very different mindset from building a product page around maximum complexity. Most small teams do not need the broadest possible infrastructure catalog on day one. They need a clean starting point. That is why I think the first VM experience matters more than many providers realize. It is the moment where a product either feels like an enabler or another obstacle. ## Why we wanted Raff to feel simpler We built Raff for builders. That means we care about the time between “I need a machine” and “I’m working.” Not in a marketing way. In a very practical way. If someone wants to launch a Linux server, test a product idea, host an internal tool, run a development environment, or give a team member a clean cloud workspace, they should be able to do that without feeling punished for not being a full-time infrastructure specialist. That is also why simplicity cannot just mean “fewer buttons.” Real simplicity means the product still gives you the things that matter: - root access - current operating systems - useful storage - network and security basics - pricing you can understand before you commit - enough flexibility to keep building after the first launch In other words, the goal is not to make cloud infrastructure look smaller than it is. The goal is to remove the parts that make people hesitate for the wrong reasons. ## Fast does not just mean technical speed When people talk about speed in cloud infrastructure, they often mean raw performance. That matters, of course. But there is another kind of speed that I think matters just as much, especially for smaller teams: decision speed. Can you understand the offer quickly? Can you choose without overthinking? Can you launch without opening six tabs first? Can you tell what your next step is once the machine is live? That kind of speed is underrated. A platform can be technically powerful and still slow the user down. And for a lot of early-stage teams, that kind of slowdown is more expensive than people think. It delays experiments. It delays deployments. It delays learning. It makes infrastructure feel like homework instead of leverage. That is not the feeling we want Raff to create. ## Simple should not mean limited This is the trap some infrastructure companies fall into. They assume that if you make the first step easier, the product will look less serious. I think the opposite is true. A serious infrastructure product should be able to do both: - feel approachable at the beginning - stay useful as the workload grows That is how I think about Raff. Yes, we want the first launch to feel straightforward. Yes, we want the platform to feel cleaner than traditional VPS experiences. But that does not mean we want people to outgrow it immediately. It means the platform should meet teams where they are and give them a path forward. That is why the broader structure matters. A VM is not just a VM decision forever. Teams eventually care about backups, networking, storage, access patterns, and how everything fits together once the first machine becomes two, then five, then something more operationally real. The first experience still matters. But the long-term shape matters too. ## What I think traditional VPS products still get wrong I think many traditional VPS products still assume that friction communicates seriousness. That if the dashboard feels dense enough, the platform will look more professional. That if pricing is fragmented enough, the offer will look more customizable. That if the setup takes longer, the buyer will assume they are dealing with something more “enterprise.” I do not believe that. I think clarity is more professional than clutter. I think understandable pricing is more credible than a cheap-looking number followed by five caveats. And I think a fast first deployment is not a shortcut — it is respect for the customer’s time. The teams we care about are not asking for less control. They are asking for less unnecessary friction between intent and execution. That is a very different problem to solve. ## The business side of this matters too There is also a business reason I care about this so much. Small teams do not just buy infrastructure with money. They buy it with attention. If your team spends too much time navigating the platform instead of using it, the infrastructure has already become more expensive than it looked on the pricing page. That is why simplicity is not just a design preference. It is an economic advantage. A VM that launches quickly, feels understandable, and gives you control without making every step heavier than necessary creates a different kind of value. It saves setup time. It reduces hesitation. It helps teams move from idea to execution faster. And for startups, builders, and lean operators, that speed of execution matters a lot. ## What this means for you If you are evaluating cloud infrastructure right now, I would suggest asking a different question. Not: “Which provider has the longest feature list?” Ask: “Which provider will let my team start cleanly and still make sense when we grow?” That is a more useful filter. If what you need today is a clear place to launch a server, get control quickly, and avoid unnecessary friction, start there. Do not overbuy complexity just because it looks impressive on a comparison table. And if that is the lens you want to use on Raff, begin with the basics: [Linux VMs](/products/linux-vm), [Windows VMs](/products/windows-vm), and the public [pricing page](/pricing). Then explore the rest of the platform once the first deployment is already doing useful work. That is how I think infrastructure should feel. Not intimidating. Not bloated. Not artificially complicated. Just ready when you are. --- ### What Benchmark Rankings Do and Don’t Tell You About Cloud Value URL: https://rafftechnologies.com/blog/what-benchmark-rankings-do-and-dont-tell-you Published: 2026-04-02T00:00:00.000Z Description: What Benchmark Rankings Do and Don’t Tell You About Cloud Value A benchmark result can make you proud. It can also make you careless. That is the part I think founders, operators, and buyers all need to be more honest about. Recently, Raff appeared near the top of a public value-focused VPS ranking. As a founder, I was genuinely happy to see that. Not because I think one benchmark “proves” everything about a cloud company, but because third-party testing matters. It is one thing for us to say we offer strong performance for the price. It is another thing for an independent benchmark platform to test plans side by side and show that we belong in the conversation. Still, I think this is where many providers — and many buyers — make the same mistake. They treat a benchmark ranking like a complete answer. It is not. A benchmark can tell you something real. Sometimes something very useful. But it cannot tell you everything that makes infrastructure valuable once it becomes part of a real team’s workflow. ## A Good Benchmark Measures One Layer of the Truth What I like about benchmark rankings is simple: they force reality into the room. Marketing pages can say almost anything. Every provider talks about performance. Every provider talks about reliability. Every provider says they are simple, scalable, affordable, or developer-friendly. A third-party benchmark changes the conversation because it gives you an external point of reference. That matters. It matters even more for a younger company like Raff. Established providers already have brand recognition. Newer platforms need a way to show, in public, that they can compete on the fundamentals. A solid ranking does that. It tells people, “This provider deserves a closer look.” That is valuable. But even the best benchmark is still measuring a defined testing environment, a defined time window, and a defined scoring model. In other words: it tells you something meaningful, but not everything meaningful. ## What Benchmark Rankings Usually Tell You Well The first thing benchmark rankings usually tell you well is whether a plan is competitive on raw public performance for the price. That is a very important signal. If a provider is expensive and underperforming, that should raise questions immediately. If a provider is cheap but still shows up strongly in web performance, network performance, disk I/O, or CPU categories, that is worth paying attention to. Benchmark rankings are especially useful for filtering out noise at the top of the funnel. If you are comparing ten providers, you probably do not want to manually trial every single one from scratch. A serious public benchmark can help you reduce that list to three or four worth investigating. That is a big service to the buyer. It also helps highlight where a provider’s strengths actually are. A plan may look great on web performance and network speed, while being only average on stability. Another may be incredibly consistent but not especially strong on price-weighted value. That kind of nuance is useful because not every workload cares about the same bottleneck. In that sense, rankings are not just about who is “best.” They help you understand what kind of provider you may be looking at. ## What Benchmarks Do Not Tell You About Cloud Value This is where I think the real buying conversation starts. Cloud value is not just “how much performance do I get for this monthly number?” Cloud value is also: - how predictable the bill remains after success - how easy it is to recover from mistakes - how cleanly the platform grows with your team - how much friction shows up when you move beyond a single VM - how much confidence you have when something breaks at the wrong time A benchmark does not capture most of that. ### 1. It Does Not Show the Full Cost Shape A benchmark can compare plan price against measured performance. What it usually does not show well is the full economic shape of the platform around that plan. That matters more than many people realize. A provider may look cheap in a benchmark and become expensive in practice because of transfer limits, backup costs, IP charges, volume pricing, or the way upgrades compound as your system grows. Another provider may look slightly more expensive at first glance, but become easier to budget because the pricing model is cleaner and the platform does not punish normal growth. This is one of the reasons I care so much about predictability. For small teams, “cloud value” is not only about finding the lowest possible number. It is about finding a number you can still explain three months later when traffic grows, environments multiply, and your architecture becomes more real. ### 2. It Does Not Show the Product Direction A benchmark tells you how a tested plan performs. It does not tell you where the platform is going. That matters because most teams do not stay frozen at the same infrastructure maturity level forever. You may start with a single VM. Then you need private networking. Then object storage. Then a cleaner application deployment workflow. Then maybe databases, orchestration, or a more programmable infrastructure model. If the provider only makes sense at the exact stage you are in today, that is not full cloud value. That is temporary convenience. This is also how I think about Raff internally. Yes, today many people may first notice Raff as a VPS provider. That is fair. Compute is where we started publicly. But the point is not to stop there. We already think in terms of infrastructure layers, not isolated server sales. That is why [Linux VMs](/products/linux-vm), [private cloud networks](/products/private-cloud-networks), [data protection](/products/data-protection), and [object storage](/products/object-storage) matter so much in the shape of the platform. It is also why the next layers matter. A strong benchmark result is encouraging, but it is only one signal that the foundation is worth building on. ### 3. It Does Not Show Operational Experience One of the biggest gaps in benchmark-driven buying is this: A benchmark cannot tell you how a platform feels to operate. It cannot tell you if the dashboard is clear or confusing. It cannot tell you whether backup and restore workflows feel obvious under pressure. It cannot tell you whether support replies with a copied script or with a useful answer. It cannot tell you how many little pieces of friction accumulate between “I launched a server” and “my team can rely on this.” For a solo developer, some of that friction is manageable. For a small team, it compounds. Every ambiguous billing rule, every awkward restore flow, every infrastructure decision that requires a support ticket instead of a product feature — these things create real cost. Not always in dollars first. Often in hesitation, delay, and mental overhead. That is part of cloud value too. ### 4. It Does Not Know Your Actual Workload This part is important enough to say plainly: No benchmark knows your application. A price-weighted value ranking can be directionally useful, but it is still a general test suite. Your actual workload may care more about one category than another. Maybe you are running a lightweight SaaS backend where web performance and network responsiveness matter a lot. Maybe you are running CI jobs and care more about consistent CPU behavior. Maybe you are serving large assets and care more about storage throughput and bandwidth model. Maybe you are hosting a stateful application where backup policy and restore simplicity matter more than any synthetic score. If you treat a benchmark as final truth rather than strong screening data, you will eventually optimize for the wrong thing. ## How I Think Small Teams Should Use Benchmark Rankings My advice is simple. Use benchmark rankings as a filter, not as a verdict. A good flow looks like this: 1. Use benchmark results to shortlist serious candidates. 2. Check whether the pricing model still makes sense after growth. 3. Look at backups, snapshots, networking, and storage — not just the VM. 4. Ask whether the platform matches the stage your team is entering, not just the stage you are leaving. 5. Run your own real-world test on the finalists. That last point matters a lot. The smartest infrastructure buyers I know do not stop at public rankings. They use them to save time, then they test the short list using their own application shape, their own deployment flow, and their own priorities. That is how you move from “interesting benchmark result” to “good long-term platform decision.” ## What This Ranking Meant to Me as a Founder From my perspective, a good public benchmark result is exciting for one main reason: it tells us the foundation is strong enough to earn attention. That is all. It does not mean “mission accomplished.” It does not mean “we won.” It does not mean benchmarks should replace product thinking. What it does mean is that the work underneath the platform is showing up in a way the market can independently observe. That matters. Because the real ambition behind Raff has never been to become “just another VPS provider with a decent score.” The ambition is to build a cloud platform that starts simple, stays understandable, and grows with the teams that use it. That is a much bigger challenge than posting a good benchmark image on social media. It means the fundamentals have to be there. It means the pricing has to remain understandable. It means the product layers beyond compute have to become real and useful. And it means we have to keep earning trust long after the benchmark page refreshes. That is how I think about it internally. A benchmark is not the destination. It is evidence that the road we are on is worth continuing. ## What This Means for You If you are evaluating cloud providers, do not ignore benchmark rankings. They are useful. They are healthy. They are one of the best ways to cut through vague marketing. But do not stop there. Ask harder questions: - What happens to my cost if this workload succeeds? - How easy is it to back up, restore, and isolate my infrastructure? - Does this provider make sense only for my first VM, or for my next stage too? - Am I buying a server, or choosing a platform direction? That is the difference between chasing a good-looking score and making a good infrastructure decision. If you want to evaluate Raff through that lens, start with the basics: our [Linux VM plans](/products/linux-vm), [private networking](/products/private-cloud-networks), [object storage](/products/object-storage), and [pricing](/pricing). Then compare those pieces against the providers on your shortlist — not just on benchmark charts, but on the parts of cloud value your team will actually feel every week. That is the standard I would use as a buyer. It is also the standard we are building toward as a company. --- ### Logs, Metrics, or Traces? What Small Teams Need First URL: https://rafftechnologies.com/blog/logs-metrics-traces-small-teams Published: 2026-03-31T00:00:00.000Z Description: Logs, Metrics, or Traces? What Small Teams Need First ## Most teams buy complexity before they buy clarity The observability conversation usually starts in the wrong place. A team launches an API, adds a worker, maybe plugs in Redis, and the first question becomes: “Should we set up logs, metrics, or traces?” The more honest question is simpler: when production feels wrong at 2:13 a.m., which signal will actually help you recover first? My view is not fashionable, but it is practical: most small teams should start with **metrics first**, add **structured logs second**, and only invest seriously in **traces** when the request path has become distributed enough to justify the extra instrumentation, storage, and mental overhead. That is not an argument against tracing. Tracing is powerful. In some architectures, it becomes essential. But the industry has a bad habit of turning “all three matter” into “you need all three immediately.” Those are not the same statement. At Raff, when we think about default operability for teams running on VMs, we bias toward telemetry that does three things well: it tells you something is wrong early, it narrows the blast radius quickly, and it stays understandable to a lean team without a dedicated observability engineer. That bias changes the order. ## What each signal is actually good at Before talking about order, it helps to strip the jargon out of the terms. **Metrics** tell you that something is changing over time. CPU climbs. Memory gets tight. Error rate jumps. Queue depth grows. P95 latency drifts upward. Metrics are compact, cheap to aggregate, and ideal for dashboards and alerts. **Logs** tell you what happened at a specific moment. A user failed authentication. A database connection timed out. A deploy changed an environment variable. A payment provider returned an unexpected response. Logs are rich, descriptive, and often messy. They explain events in detail, but they can drown you if you treat them like a primary alerting system. **Traces** tell you where time was spent across a request path. A trace follows a single transaction as it moves through your application and dependencies. It becomes especially useful when one request touches multiple services, queues, databases, and third-party APIs. That distinction matters because these signals solve different problems. Metrics answer: **Is the system healthy?** Logs answer: **What happened?** Traces answer: **Where in the path did it break or slow down?** If you try to use one signal for every question, you end up with a noisy stack and very little clarity. ## Why metrics should usually come first If I had to choose one signal for a small team starting from zero, I would choose metrics without hesitation. The reason is simple: metrics are the fastest route from “something feels off” to “this area needs attention.” They are lightweight enough to collect continuously, structured enough to alert on automatically, and broad enough to describe system health before you know the exact failure mode. That makes them your best first line of defense. A small team usually needs answers to a short list of questions before anything more advanced: - Is the server under resource pressure? - Is the application error rate rising? - Is request latency trending up? - Is the queue backing up? - Is the database responding more slowly than normal? - Did a deploy correlate with a sudden change? Metrics answer those questions cleanly. They also create the habit that matters most in operations: defining what “normal” looks like before something breaks. This is where a lot of teams go wrong. They install logging, skim a wall of text, and call that observability. It is not. It is exhaust. Without metrics, you are waiting to notice a problem reactively. With metrics, you can detect it proactively. That difference matters more than people think, especially when your infrastructure is still simple. If your application is running on one or two [Linux VMs](/products/linux-vm), one database, and a worker process, good metrics already cover a surprising amount of ground. CPU saturation, memory pressure, disk I/O, error rate, response time, queue depth, and restart frequency will tell you where to look long before a tracing system becomes necessary. ## Why logs come second — but not as raw noise Logs are the second layer because once metrics tell you **where** to look, logs usually tell you **why**. But there is a catch: logs only become useful at scale when they are structured and intentional. A lot of teams say they “have logs” when what they actually have is a terminal full of inconsistent strings written by different developers in different moods over six months. That is not observability. That is archaeology. If you want logs to work for you, you need to make them queryable. That means logging in a structured format, usually JSON, and attaching a consistent set of fields such as: - timestamp - level - service - environment - version - request ID - correlation ID - job ID where relevant Once you do that, logs stop being random narrative and start becoming evidence. This is also why I put logs after metrics, not before. Logs are rich, but they are expensive in every sense: storage, cardinality, indexing, retention, and human attention. They scale badly when your first question is “Is the system healthy?” They scale well when your first question is “What exactly happened inside the component metrics just pointed me toward?” That is the right relationship. Metrics tell you the API error rate doubled after the deploy. Logs tell you the payment adapter is throwing a null reference only in the `eu-west` environment. Metrics tell you queue latency spiked. Logs tell you one worker version is failing to deserialize a job payload. Metrics tell you the database is slow. Logs show the ORM suddenly issuing an N+1 query pattern. If metrics are your radar, logs are your incident notebook. ## When traces become worth the effort Now the controversial part. Tracing is powerful, but for many small teams it is not the first missing piece. It is the third one. If your system is still mostly one application, one worker tier, and one database, traces can absolutely help — but they are often not the thing standing between you and operational clarity. In that stage, poor metrics and poor logs are usually the bigger problem. Tracing becomes worth the effort when the system stops being legible as a single unit. That usually happens when requests begin crossing multiple boundaries: - service-to-service network calls - async queues and background jobs - third-party APIs with variable latency - separate ownership across domains - retries, fallbacks, and partial failure paths - multiple databases or datastores in one request lifecycle That is when traces stop being nice to have and start becoming operationally important. The reason is not just that traces are “cooler” or more modern. It is that distributed systems create failure paths that logs and metrics alone explain poorly. Once one user action fans out across multiple services, you need request-level visibility to understand where time went and which dependency introduced failure or latency. This is why tracing shines in microservices, queue-heavy applications, and integration-heavy systems. It is also why I do not recommend forcing it too early onto every small app. You end up instrumenting for a topology you do not actually have yet. There is another practical point here: tracing gets much better when it is correlated with logs. Once trace IDs, service names, environment tags, and version fields are shared consistently, traces and logs stop competing and start reinforcing each other. Until then, teams often blame tracing when the real problem is inconsistent telemetry design. ## The order I recommend for small teams on Raff If you are running a lean application on Raff today, this is the sequence I would recommend. ### 1. Start with infrastructure and application metrics Get basic host and app health visible first. Track CPU, RAM, disk, network, error rate, response latency, restarts, queue depth, and database latency if you can. Build a small dashboard. Add a few alerts that you will actually respect. Not fifty. A few. The goal is not “full observability.” The goal is knowing when the system moves outside normal behavior. ### 2. Add structured logs with correlation IDs Once metrics tell you where pain is appearing, structured logs let you investigate without guessing. Make logs machine-readable. Add request IDs. Make sure deploy version and environment are included. Keep log levels disciplined. Do not dump every debug detail into production forever and call that maturity. ### 3. Add traces when request paths earn them When the system starts crossing enough boundaries that cause-and-effect becomes blurry, add tracing deliberately. Not because a vendor told you the stack is incomplete without it. Because you now have a real problem tracing is good at solving. ### 4. Correlate the signals instead of treating them as separate products This is the maturity step that matters. Metrics should lead you to the incident. Logs should explain the event. Traces should expose the path. If they do not connect cleanly, you do not really have observability yet. You just have three storage systems. ## The mistake behind most observability waste Most waste in observability does not come from buying the wrong tool. It comes from solving the wrong stage problem. A team with one service, one queue, and one database buys a tracing-first stack because it sounds advanced. Meanwhile, they still have no reliable latency alert, no deploy markers in dashboards, no structured error logs, and no agreement on what “healthy” means. That team does not need more telemetry types. It needs clearer fundamentals. This is the same pattern we see in infrastructure more broadly. Teams often jump to the advanced version of the solution before the simpler version has actually failed. They start with Kubernetes when a VM would do. They split into microservices when a modular monolith would do. They instrument traces everywhere when metrics and logs would answer most incidents faster. I am not against any of those tools. I am against using them to skip the discipline of asking what problem exists right now. ## What This Means for You If your team is deciding what to monitor first, keep the sequence simple. Start with **metrics** because they tell you when the system leaves the healthy path. Add **structured logs** because they explain what happened inside that unhealthy window. Add **traces** when your architecture becomes distributed enough that request flow is no longer obvious from metrics and logs alone. That order is not anti-modern. It is pro-clarity. If you are building on Raff, begin with a lean VM setup you can understand, instrument, and improve over time. Our [Linux VM plans](/products/linux-vm) and public [pricing page](/pricing) make that staged approach straightforward. Then pair this post with [Single-Server vs Multi-Server Architecture](/learn/guides/single-server-vs-multi-server-architecture) and [Dev vs Staging vs Production](/learn/guides/dev-staging-production-cloud-environments), because observability quality is tightly tied to how you structure environments and failure domains. My rule of thumb is simple: do not instrument for the architecture you imagine you might have next year. Instrument for the one that can wake you up tonight. --- ### Cloud VMs for Hackathons: How to Launch Fast and Stay Focused URL: https://rafftechnologies.com/blog/cloud-vms-for-hackathons-how-to-launch-fast-and-stay-focused Published: 2025-07-05T00:00:00.000Z Description: Cloud VMs for Hackathons: How to Launch Fast and Stay Focused Hackathons are won in the first few hours more often than people admit. Not because the final pitch is decided that early, but because momentum is. If your team spends the beginning of a 24- to 72-hour sprint installing dependencies, fixing laptop-specific issues, and explaining local setup to every teammate, you start the event with less energy than the teams already building. That is why cloud VMs are such a practical hackathon tool. A cloud VM is a remote virtual machine that gives your team a clean, ready-to-code environment without depending on one person’s laptop, one operating system, or one fragile local setup. At Raff, we think that matters because hackathons reward focus, speed, and iteration far more than they reward infrastructure cleverness. ## The real enemy at a hackathon is setup drag Most hackathon teams think they are racing the clock against other teams. In practice, they are usually racing against wasted setup time. You see the same problems over and over: * one teammate is on Windows, another is on macOS, another is on Linux * Docker behaves differently on each machine * the backend needs more RAM than someone’s laptop can comfortably spare * a package that worked last week suddenly breaks on a fresh install * the team loses an hour just getting everyone into the same environment None of that wins points. None of it improves the product. It just burns the short window you were supposed to use for shipping. A cloud VM fixes that by giving you a neutral workspace. Instead of making the project adapt to everyone’s local machine, you make the environment consistent first and let the team build on top of that. ## Why hackathons pair so well with cloud VMs A hackathon project usually has three needs at the same time: speed, flexibility, and disposability. You need to move quickly because the deadline is measured in hours, not quarters. You need flexibility because the idea may change halfway through the event. And you need disposability because this environment may only matter for one weekend. That is exactly where virtual machines shine. A VM gives you a full operating system, root access, predictable resources, and a clean place to run the stack you actually want. If you need Docker, Node.js, Python, PostgreSQL, Redis, Nginx, or all of them together, you can build that environment once and let the team work against it. If the idea changes, you can resize, rebuild, or throw the machine away without dragging your personal device through the process. This is one reason we like the VM model so much for short sprints. It is flexible enough for serious work, but simple enough that you do not need an ops team to get moving. ## Why we think simple infrastructure wins hackathons This is where our product philosophy matters. At Raff, we have deliberately kept the platform centered on practical infrastructure building blocks instead of burying users under a giant service catalog on day one. For hackathon teams, that is usually the right trade-off. You do not need a long architecture workshop before you launch. You need a server, an operating system you already understand, enough resources to build and demo, and a pricing model you can explain without opening a second spreadsheet. That decision becomes even more important when the team is tired. The best hackathon infrastructure is not the most impressive on paper. It is the setup that disappears into the background fast enough for the team to keep building. ## What a strong hackathon VM setup looks like A good hackathon VM setup is not complicated. It usually looks like this: ### One shared development base Start with one machine that acts as the team’s consistent environment. This can be where the backend runs, where dependencies are installed, where the API is tested, or where the group stores the working stack everyone needs to reference. ### Clear separation between code and machine Use Git for the code and the VM for the environment. That sounds obvious, but it matters. The point is not to make the VM the only place your work exists. The point is to make it the cleanest place to run the work. ### Enough headroom to avoid laptop pain Hackathons often create awkward workloads: AI experiments, Docker containers, browser automation, background services, live demos, local databases, or image processing tasks. These are exactly the workloads that can make a personal laptop feel overloaded at the worst possible moment. ### Disposable by design The machine should feel temporary. That mindset helps you move faster. You are not designing a forever-environment. You are building a fast, useful workspace for a short, high-pressure sprint. ## Where hackathon teams usually lose time The time loss is rarely dramatic. It is cumulative. Ten minutes fixing package conflicts. Twenty minutes figuring out which Node version everyone has. Fifteen minutes explaining Docker setup to the one teammate who has never used it. Another fifteen minutes because one person’s laptop starts thermal throttling during a demo build. That is how half a day disappears. A cloud VM does not eliminate every problem, but it removes a category of problems that should never decide the outcome of a hackathon in the first place. If everyone can target the same environment from the start, you reduce the number of moving parts that have nothing to do with the idea you are trying to ship. ## When to use one VM and when to use two Not every team needs multiple machines. For many hackathons, one well-chosen VM is enough. It gives you a place to run the app, test the environment, and host a preview or demo without spreading the team too thin. Two VMs can make sense when: * one machine is for development or build tasks * the second is for demo or staging * you want to avoid breaking the pitch environment while still shipping changes * the team is splitting frontend and backend work and wants a cleaner boundary If you are unsure, start with one. Simpler setups usually win under time pressure. You can always grow from there if the project proves it needs more structure. If your team wants a better mental model for this, our guide on [dev, staging, and production environments](/learn/guides/dev-staging-production-cloud-environments) is useful because it explains when separate environments help and when they are unnecessary overhead. ## Choosing the right environment without overthinking it The fastest hackathon setup is usually the one closest to what your team already knows. If the team is comfortable on Ubuntu, use Ubuntu. If the app is containerized, bring Docker into the environment quickly. If you want a cleaner understanding of provisioning options, our guide on [VM provisioning models](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click) is the right background read, but for a hackathon the answer is usually simple: pick the fastest path to a known-good machine. This is not the moment to optimize for theoretical perfection. It is the moment to choose a setup your team can trust under deadline pressure. That principle also applies to the architecture itself. If the project can run on one VM, do that. If you need a reverse proxy and one app process, keep it there. If you need separate services, use them because the project needs them, not because the diagram looks more impressive. ## Why cloud VMs beat “everyone just use your laptop” There is nothing wrong with local development. But hackathons create exactly the kind of messy, high-speed collaboration where local-only workflows become fragile. A VM gives you: * consistency across teammates * a place to run demos outside personal hardware * cleaner collaboration for backend services * fewer surprises from OS differences * a safer way to test realistic deployment behavior That last part matters more than people think. Hackathon teams often build something that works locally but behaves differently the moment it leaves the laptop. A cloud VM closes that gap early, which makes the final demo more reliable. If you want to understand the trade-offs more deeply, our guide on [Docker vs. virtual machines](/learn/guides/docker-vs-virtual-machines-when-to-use) is useful. In short, containers are great for packaging applications, but VMs are still the practical base layer when you need a full environment you can trust during a sprint. ## Cost matters, but predictability matters more Hackathon teams are usually cost-sensitive. Students, indie developers, small teams, and early-stage founders do not want a weekend project to turn into a platform surprise. That is why predictability matters so much. It is not enough for infrastructure to be affordable in theory. It needs to be understandable in practice. One reason we emphasize simple infrastructure at Raff is that short-term projects should not force long-term financial anxiety. If a team needs a VM for a sprint, they should be able to launch it, use it, and shut it down without spending the entire event wondering what the final bill will look like. That is the practical cloud-economics lesson behind hackathons: simple infrastructure helps teams stay creative because it removes operational doubt from the middle of the project. ## A realistic hackathon workflow on Raff A practical flow looks like this: 1- Choose one Linux VM as the shared project base. 2- Install the core runtime or container tooling the team needs. 3- Put the project in Git and use the VM as the common execution environment. 4- Test early from outside the machine, not just from localhost. 5- Protect the environment from last-minute chaos by deciding what changes are safe before the demo window. 6- Shut it down, snapshot it, or keep it if the project deserves another week of work. That is not glamorous infrastructure. It is useful infrastructure. And useful infrastructure is what wins these events. ## What This Means for You If your next hackathon matters, treat environment setup like part of the competition. You do not need a huge cloud architecture. You need a fast, consistent place to build, test, and demo without sacrificing the first hours of momentum to dependency issues and laptop limitations. For most teams, that means one simple cloud VM, a familiar Linux environment, and just enough structure to keep the build stable while the idea evolves. That is exactly the kind of workflow Raff is built to support. Start with [Raff pricing](/pricing), review the [Linux VM options](/products/linux-vm), and keep your next hackathon environment focused on one thing: helping your team ship more before the deadline hits. --- ### AI Workloads on Cloud Infrastructure: What Changes When the App Gets Heavier? URL: https://rafftechnologies.com/blog/ai-workloads-cloud-infrastructure-heavier-apps Published: 2026-03-17T00:00:00.000Z Description: AI Workloads on Cloud Infrastructure: What Changes When the App Gets Heavier? AI workloads do not stress infrastructure in the same way as a typical web app. As models get larger and requests become more complex, the bottleneck shifts from simple CPU and RAM scaling to a broader system problem involving compute, storage, networking, and scaling behavior. A traditional SaaS application becomes heavier in predictable ways: more users, more database queries, more background jobs. AI applications behave differently. A single request can consume significantly more memory, take longer to process, and introduce unpredictable latency. If you treat an AI app like a normal app with higher CPU usage, you will run into problems—usually in production. --- ## What Actually Gets “Heavier”? When teams say their AI workload is getting heavier, they usually mean one (or more) of the following: - The model size increases - Requests take longer to complete - Memory usage grows significantly - Traffic becomes bursty and unpredictable - Latency requirements become stricter This changes the core infrastructure questions: - How fast can the model load? - Can storage keep up with the workload? - Will cold starts hurt user experience? - Can the system scale without wasting money? - Do we need specialized compute? At this point, infrastructure stops being a background concern and becomes a product decision. --- ## Compute Stops Being Generic For most applications, scaling compute is straightforward: add more CPU and RAM. AI changes that. Some workloads still run well on CPUs: - Lightweight inference - Data preprocessing - API orchestration - Background jobs But as workloads grow heavier, compute becomes a strategic decision: - **CPU-first** → cheaper, simpler, good for early-stage AI features - **GPU-backed** → required for larger models or low-latency inference - **Hybrid setups** → separate application logic from model-serving infrastructure The key is separation. You don’t want expensive compute doing work that cheaper machines can handle. --- ## Storage Becomes a Performance Layer In traditional apps, storage is mostly about capacity. In AI workloads, storage directly affects performance. Large models, embeddings, and artifacts must be loaded quickly. Slow storage leads to: - Longer startup times - Higher latency - Poor scaling behavior Fast local storage (like NVMe SSDs) becomes important for: - Model loading - Temporary data - Caching As workloads grow, storage design becomes part of your performance architecture—not just a backend detail. --- ## Network and Latency Start to Matter More AI systems are rarely a single service. They often include: - Frontend/API layer - Inference service - Data or vector storage - Logging and monitoring systems This increases internal traffic. Two things start to matter: 1. **Latency between services** 2. **Reliability of internal communication** Private networking becomes valuable because it: - Keeps internal traffic secure - Reduces exposure to public internet latency - Improves consistency between services At small scale, you can ignore this. At larger scale, you cannot. --- ## Scaling Gets Slower and More Expensive Scaling a normal app is simple: > Add more instances → put them behind a load balancer AI workloads break this assumption. New instances may take time to become useful because they need to: - Load models - Initialize runtimes - Warm caches This creates new challenges: - Cold starts become visible to users - Autoscaling reacts slower - Idle capacity becomes expensive Scaling decisions now involve trade-offs: - Cost vs readiness - Latency vs utilization - Simplicity vs control Autoscaling is no longer just “add more servers”—it becomes workload-aware. --- ## Reliability Looks Different for AI Systems Heavier applications are not just more expensive—they are often more fragile. Common failure points include: - Model servers failing to start - Memory limits being exceeded - Latency spikes under load - Dependencies slowing down the entire request This shifts how you think about reliability: - Redundancy is essential - Health checks become critical - Failover must be tested - Backups must include more than just data Infrastructure alone does not guarantee reliability—system design does. --- ## A Practical Path for Growing AI Workloads Most teams don’t need to jump into complex infrastructure immediately. A realistic progression looks like this: | Stage | What Changes | Infrastructure Focus | |------|-------------|--------------------| | Early feature | Small models, low traffic | Simple CPU-based VMs | | Growth phase | More memory and longer requests | Stronger compute, better monitoring | | Production | Latency and uptime matter | Load balancing, private networking | | Heavy workloads | Large models and slow startup | Storage optimization, caching | | Mature system | Multiple services | Scaling strategy, failover design | The goal is not to over-engineer early—but to evolve architecture as pressure increases. --- ## What This Means in Practice The biggest shift with AI workloads is not just higher resource usage. It is **interdependence**. - Storage affects latency - Network affects reliability - Compute affects cost - Scaling affects user experience Everything becomes connected. That is why heavier AI applications require better infrastructure thinking—not just bigger machines. --- ## Conclusion When an AI application gets heavier, the problem is no longer just scaling a server. You are managing a system where compute, storage, networking, and scaling behavior all interact. The right approach is not to overbuild from day one, but to understand where the pressure is coming from: - Is it compute? - Is it storage? - Is it latency? - Is it scaling behavior? Once you identify the bottleneck, you can make smarter infrastructure decisions. That is how you build AI systems that are not just powerful—but reliable, efficient, and scalable. --- ### Why Raff Is a Solid VPS Choice for Growing Teams URL: https://rafftechnologies.com/blog/why-raff-is-a-solid-vps-choice Published: 2026-02-24T00:00:00.000Z Description: Why Raff Is a Solid VPS Choice for Growing Teams Choosing a VPS provider is not just about CPU, RAM, or the lowest monthly price. For most growing teams, the real questions are simpler: - How fast can we launch? - How easy is it to manage? - How quickly can we get help when something breaks? - Can this platform grow with us beyond a single virtual machine? That is where provider choice starts to matter. Some teams need a massive ecosystem. Others just need infrastructure that is fast to provision, easy to understand, and flexible enough to support real workloads without adding unnecessary complexity. For teams in that second group, **Raff** is a strong option. --- ## What Companies Actually Need From a VPS Provider When companies compare VPS providers, they usually care about a handful of practical things: - predictable pricing - fast provisioning - reliable performance - simple networking - automation options - responsive support - a clear migration path These are operational needs, not marketing features. A good VPS provider should reduce friction for engineering teams, not create more of it. That is especially true for startups, agencies, product teams, and lean engineering organizations that need to move quickly. --- ## Why Teams Switch VPS Providers in the First Place Companies rarely move infrastructure just because of raw specs. They move because day-to-day operations start getting painful. Common reasons include: - slow or clumsy provisioning workflows - support that is hard to reach when issues are urgent - confusing billing or bandwidth rules - weak automation options - migration that feels harder than it should be In other words, teams do not just buy servers. They buy **speed, clarity, and confidence**. --- ## Where Raff Stands Out Raff is a solid VPS choice because it focuses on the things modern teams actually use every day. ### 1. Fast deployment without unnecessary friction If your team needs infrastructure quickly, speed matters. Raff is built around fast VM provisioning and a simpler workflow for getting from account creation to a running server. That matters for: - urgent test environments - staging infrastructure - customer demos - new product environments - short feedback loops for engineering teams When infrastructure is fast to launch, teams spend less time waiting and more time shipping. --- ### 2. Strong support when infrastructure becomes urgent Support quality matters more than many teams realize. A VPS provider can look similar on a pricing page, but the real difference shows up when you need help under time pressure. Responsive support becomes critical when you are dealing with: - network issues - deployment problems - migration questions - production incidents - configuration uncertainty For growing teams, strong support reduces operational stress and shortens downtime. That is not a small advantage. It is part of the product. --- ### 3. Migration help lowers switching risk Migration is one of the biggest reasons companies stay with infrastructure they are no longer happy with. Even when pricing or experience is not ideal, teams often delay switching because they do not want to deal with: - moving workloads - recreating environments - reconfiguring networking - validating application behavior after migration That is why migration assistance matters. A provider that helps teams move workloads reduces one of the biggest barriers to adoption. --- ### 4. More than just a basic VPS dashboard A modern infrastructure platform should do more than let you click “Create VM.” Teams increasingly need: - automation through APIs - infrastructure as code - private networking - storage options - a path toward more advanced workloads Raff fits that direction well. It starts with virtual machines, but it also supports a broader infrastructure workflow for teams that want more control and flexibility over time. --- ## Raff Is Built for Teams That Want to Grow Without Replatforming Too Early One of Raff’s strongest positioning advantages is that it is not limited to “just another VPS.” Teams can start with simple virtual machines and still have room to expand their architecture over time. That matters for companies that expect to grow from: - one VM to multiple environments - manual deployment to API-driven automation - simple services to more structured infrastructure - direct server hosting to storage, networking, and orchestration needs If that sounds like your roadmap, a platform that already points in that direction is valuable. For example, if you are thinking about edge protection or proxying traffic in front of your infrastructure, you may also want to read [When Cloudflare Isn’t Enough: Why Developers Still Need a VPS](/blog/cloudflare-vs-vps-why-developers-still-need-a-server) and [How to Host Your App on a VPS with Cloudflare](/blog/host-app-on-vps-with-cloudflare). If your team is moving toward container orchestration, see [Should I Run Kubernetes on a VPS?](/blog/should-i-run-kubernetes-on-a-vps) and [How to Run a Kubernetes Cluster on a VPS (Step-by-Step)](/blog/run-kubernetes-cluster-on-vps-step-by-step). And if you are thinking about modern storage architecture, read [Why Use S3 with a VM? Object Storage Explained](/blog/why-use-s3-object-storage-with-vm). --- ## Who Raff Is a Good Fit For Raff makes the most sense for teams that want simplicity without giving up flexibility. That includes: - startups launching early production workloads - SaaS teams running APIs and backend services - agencies managing staging or client environments - developers running Docker-based applications - teams that want API-driven infrastructure workflows - companies that may later expand into Kubernetes, object storage, or more advanced networking This is especially valuable for teams that do not want a heavy platform experience on day one. --- ## Common Workloads That Fit Well on Raff A strong VPS platform should support real-world workloads, not just theoretical use cases. Examples include: - backend APIs - Docker containers - internal tools - staging environments - CI/CD runners - proof-of-concept environments - customer demo environments - Kubernetes test clusters - application workloads that need private networking That is the practical lens companies should use when evaluating a VPS provider. Not “Which platform has the longest feature list?” Instead: **Which platform helps us run our workloads with less friction?** --- ## Why “More Than VPS” Matters For many teams, the first purchase is a VM. But that is rarely where infrastructure stops. Over time, teams often need: - object storage for files and backups - private networks between workloads - automation through APIs and Terraform - a more structured way to run containers - a path toward Kubernetes That is why it is useful to choose a provider that can support both your current needs and your next layer of complexity. Raff’s direction makes sense for companies that want to start simple and grow deliberately. --- ## FAQ ### Is Raff only for basic VPS hosting? No. Raff starts with virtual machines, but it also fits teams that need automation, networking, and a broader infrastructure path as they grow. ### Can Raff help with migration? If your team is moving from another environment, migration help can reduce the operational burden of switching infrastructure and speed up onboarding. ### Is Raff a good fit for startups? Yes, especially for startups that want fast deployment, simpler infrastructure workflows, and a platform that can expand with their needs. ### Does Raff support teams that want automation? Yes. Teams that want infrastructure automation, repeatable workflows, and developer-friendly operations should care about API and infrastructure-as-code support from the beginning. --- ## Final Thoughts The best VPS provider is not always the one with the most features or the biggest name. It is the one that helps your team move faster with fewer operational headaches. For companies that care about: - fast infrastructure setup - responsive support - migration help - automation options - room to grow beyond a single VM Raff is a solid choice. If your team wants a VPS provider that feels practical, developer-friendly, and built for real workloads, Raff is worth serious consideration. --- ### How to Deploy a Production Docker Server on a VPS (2026 Guide) URL: https://rafftechnologies.com/blog/aws-ec2-vs-raff-vps-cost-comparison-2026 Published: 2026-03-04T00:00:00.000Z Description: How to Deploy a Production Docker Server on a VPS (2026 Guide) # AWS EC2 vs Raff VPS: Cost Comparison for Developers (2026) Choosing the right infrastructure is one of the first decisions developers make when launching a project. Two common options are **hyperscale cloud platforms like AWS EC2** and **modern VPS providers like Raff Technologies**. While both offer virtual servers, they are designed for different use cases. In this article, we compare **AWS EC2 and Raff VPS** in terms of pricing, simplicity, and developer experience. --- ## What is AWS EC2? Amazon EC2 (Elastic Compute Cloud) is one of the most widely used cloud computing services in the world. It allows developers to run virtual machines in Amazon’s global cloud infrastructure. AWS provides hundreds of instance types and integrates with many services such as: - managed databases - load balancers - serverless functions - monitoring tools Because of this ecosystem, AWS is extremely powerful — but it can also become complex and expensive for smaller workloads. --- ## What is Raff VPS? Raff Technologies provides **developer-friendly cloud VPS servers** designed to be simple, fast, and affordable. Instead of complicated billing models, Raff offers **clear monthly pricing** with high-performance infrastructure. Typical Raff VPS features include: - AMD EPYC CPUs - NVMe SSD storage - predictable pricing - instant VM deployment - built-in DDoS protection For many developers, this makes infrastructure easier to manage. --- ## Pricing Comparison Let’s compare a typical backend server configuration. | Provider | vCPU | RAM | Storage | Monthly Price | |--------|------|------|------|------| | AWS EC2 | 4 | 16 GB | EBS | ~$120+ | | Raff VPS | 4 | 8 GB | NVMe | $19.99 | AWS pricing may increase further depending on: - bandwidth usage - storage volumes - monitoring services - load balancers With VPS platforms like Raff, the pricing is typically **fixed and predictable**. --- ## Infrastructure Complexity AWS EC2 is part of a very large ecosystem. Launching a production workload often involves: - EC2 instances - VPC networking - EBS storage - load balancers - security groups - monitoring tools For large companies this flexibility is powerful. But for individual developers or startups, this complexity can slow things down. With a VPS platform like Raff, developers can simply: 1. Launch a server 2. SSH into the machine 3. Deploy their application This simplicity is one of the main reasons many developers choose VPS infrastructure. --- ## When AWS EC2 Makes Sense AWS is still a great choice when you need: - massive scalability - multi-region deployments - complex enterprise architecture - advanced managed services Large companies often rely on AWS because of its global infrastructure. --- ## When Raff VPS Makes More Sense A VPS solution like Raff is often ideal for: - SaaS startups - developer projects - backend APIs - Docker servers - self-hosted applications For many of these workloads, a single VPS can run production services reliably at a much lower cost. --- ## Final Thoughts AWS EC2 remains one of the most powerful cloud platforms available. However, many developers do not need the full complexity of hyperscale cloud infrastructure. Modern VPS platforms like **Raff Technologies** provide a simpler alternative — offering strong performance, predictable pricing, and fast deployment. For developers building new projects in 2026, the decision often comes down to this: **Use AWS when you need hyperscale infrastructure. Use a VPS like Raff when you want simplicity, performance, and predictable costs.** --- ### Hetzner vs Raff Technologies: A Real Cloud Platform Comparison for Developers (2026) URL: https://rafftechnologies.com/blog/hetzner-vs-raff-cloud-comparison Published: 2026-03-09T00:00:00.000Z Description: Hetzner vs Raff Technologies: A Real Cloud Platform Comparison for Developers (2026) Hetzner has long been known as one of the best price-to-performance infrastructure providers in the hosting industry. Many developers choose Hetzner when looking for affordable virtual machines and reliable infrastructure. However, depending on workflow and project requirements, developers sometimes look for alternatives that offer different advantages such as simpler deployment, higher RAM tiers at entry level, or developer-focused tooling. In this article we compare **Hetzner Cloud and Raff Technologies** across pricing, infrastructure features, and developer experience to help you decide which platform fits your needs. --- ## Entry-Level Pricing Comparison When comparing cloud providers, it’s important to compare **similar RAM tiers**, since memory often determines what workloads a server can handle. | Provider | CPU | RAM | Storage | Bandwidth | Price | |---|---|---|---|---|---| | Hetzner CPX11 | 2 vCPU | 2 GB | 40 GB NVMe | 1 TB | €4.99 (~$5.40) | | Hetzner CPX21 | 3 vCPU | 4 GB | 80 GB NVMe | 2 TB | €9.49 (~$10.30) | | Raff Starter VM | 2 vCPU | 4 GB DDR5 | 50 GB NVMe | Unmetered | $4.99 | ### Key Observations If we compare **similar RAM tiers (4 GB)**: - Hetzner: €9.49 (~$10.30) - Raff: $4.99 At this tier, Raff offers: - more memory at the entry price point - NVMe storage - DDR5 RAM - unmetered bandwidth Hetzner focuses on **very low starting prices**, which can be attractive for extremely lightweight workloads. --- # Higher Tier Pricing Comparison As applications grow, developers often move to larger instances with more memory and compute power. Below is a comparison of **mid-tier and higher-tier virtual machines**. --- ## 8 GB RAM Tier | Provider | CPU | RAM | Storage | Bandwidth | Price | |---|---|---|---|---|---| | Hetzner CPX31 | 4 vCPU | 8 GB | 160 GB NVMe | 3 TB | €16.90 (~$18.30) | | Raff VM | 4 vCPU | 8 GB DDR5 | 120 GB NVMe | Unmetered | $9.99 | --- ## 16 GB RAM Tier | Provider | CPU | RAM | Storage | Bandwidth | Price | |---|---|---|---|---|---| | Hetzner CPX41 | 8 vCPU | 16 GB | 240 GB NVMe | 4 TB | €32.90 (~$35.60) | | Raff VM | 8 vCPU | 16 GB DDR5 | 240 GB NVMe | Unmetered | $19.99 | --- ## 32 GB RAM Tier | Provider | CPU | RAM | Storage | Bandwidth | Price | |---|---|---|---|---|---| | Hetzner CPX51 | 16 vCPU | 32 GB | 360 GB NVMe | 5 TB | €65.90 (~$71.30) | | Raff VM | 16 vCPU | 32 GB DDR5 | 360 GB NVMe | Unmetered | $39.99 | --- ### Pricing Pattern As instance sizes increase, the **price-to-performance advantage becomes more noticeable**. Raff tends to provide: - more RAM per dollar - unmetered bandwidth - NVMe storage - modern DDR5 memory This can make a difference for workloads that require **higher memory or sustained traffic**. --- ## Platform Features Comparison Both Hetzner and Raff provide modern cloud infrastructure features used by developers building applications and services. | Feature | Raff | Hetzner | |---|---|---| | Virtual Machines | ✓ | ✓ | | NVMe Storage | ✓ | ✓ | | Block Storage / Volumes | ✓ | ✓ | | Object Storage (S3 Compatible) | ✓ | ✓ | | API Access | ✓ | ✓ | | API Keys | ✓ | ✓ | | Private Networking | ✓ | ✓ | | Firewalls | ✓ | ✓ | | Load Balancers | ✓ | ✓ | | Snapshots & Backups | ✓ | ✓ | | Kubernetes | ✓ | Self-managed | Both platforms support **API-driven infrastructure**, allowing developers to automate server provisioning and integrate infrastructure into CI/CD pipelines. --- ## Storage & Data Services Modern applications rely heavily on flexible storage options. ## Raff Storage Raff provides: - NVMe block storage volumes - snapshot support - scalable volume resizing - S3-compatible object storage - API-based automation These tools allow developers to run applications, databases, and microservices without manually managing storage infrastructure. --- ## Hetzner Storage Hetzner provides: - scalable block storage volumes - snapshot and backup capabilities - S3-compatible object storage - redundant data center infrastructure Hetzner storage systems are designed to support **large scale production environments**. --- ## Kubernetes & Container Workloads Many modern applications are built around containers and Kubernetes. Hetzner servers can run Kubernetes clusters using tools such as: - kubeadm - k3s - managed orchestration frameworks Raff also supports container-based workloads and Kubernetes environments for deploying scalable applications and microservices. --- ## Developer Experience The biggest difference between these platforms is **platform philosophy**. --- ## Hetzner Hetzner is primarily a **datacenter operator and infrastructure provider**. It is known for: - excellent hardware price-performance - dedicated servers - large infrastructure deployments - strong hosting reputation Many companies run **large production workloads and enterprise infrastructure** on Hetzner. --- ## Raff Technologies Raff focuses on **developer-centric cloud infrastructure** designed for quickly launching and running projects. Common Raff workloads include: - development environments - backend APIs - bots and automation tools - microservices - prototypes and side projects The platform is designed to help developers **spin up compute resources quickly without unnecessary infrastructure complexity**. --- ## Real Developer Use Cases Cloud machines are commonly used for a wide variety of developer workloads. --- ## Development Environments Many developers run **remote development environments** in the cloud. Examples include: - Node.js or Python development servers - Docker environments - CI/CD runners - temporary staging servers Both platforms can support these workflows effectively. --- ## Automation & Bots Developers often deploy servers for: - trading bots - Discord or Telegram bots - automation scripts - scheduled cron jobs These workloads usually require **reliable compute with minimal overhead**. --- ## Backend APIs Cloud servers are frequently used to host: - REST APIs - GraphQL services - webhook processors - authentication services These applications require **consistent compute resources and stable networking**. --- ## Learning Infrastructure Students and developers often deploy servers to learn: - Linux server administration - Docker - Kubernetes - infrastructure automation Entry-level servers provide an accessible environment for experimenting with these technologies. --- ## When to Choose Hetzner Hetzner may be the right choice if you need: - extremely low-cost entry servers - dedicated bare metal infrastructure - large scale deployments - enterprise infrastructure - global data center presence --- ## When Raff May Be the Better Choice Raff may be a better fit if you want: - higher RAM tiers at entry pricing - unmetered bandwidth - developer-focused cloud workflows - simple and fast infrastructure deployment - modern NVMe-based cloud machines --- ## Final Thoughts Both Hetzner and Raff are powerful cloud infrastructure platforms, but they focus on slightly different priorities. Hetzner focuses on **large-scale infrastructure and hardware efficiency**, while Raff focuses on **developer productivity and high-value compute resources for everyday workloads**. Choosing the right platform ultimately depends on how you build and run your applications. If you're exploring modern cloud platforms for development environments, backend services, automation workloads, or side projects, Raff may be worth considering alongside traditional providers. --- Learn more about Raff Technologies https://rafftechnologies.com --- ### Running Kubernetes on a High-Performance VPS: Is It Worth It in 2026? URL: https://rafftechnologies.com/blog/kubernetes-on-vps-is-it-worth-it-2026 Published: 2026-02-24T00:00:00.000Z Description: Running Kubernetes on a High-Performance VPS: Is It Worth It in 2026? Kubernetes is no longer reserved for enterprise giants. In 2026, startups, DevOps teams, indie hackers, and SaaS builders are running production workloads on Kubernetes every day. But one question keeps coming up: **Do you really need expensive managed cloud platforms to run Kubernetes — or can a high-performance VPS handle it just as well?** Let’s break it down. --- ## The Rise of Self-Managed Kubernetes Managed Kubernetes services (EKS, GKE, AKS) are powerful — but they come with: - Complex pricing models - Egress bandwidth costs - Hidden infrastructure charges - Vendor lock-in - Over-provisioned resources For many teams, especially startups and lean DevOps groups, these costs grow fast. That’s why more cloud-native teams are asking: > Can we run Kubernetes on a powerful VPS instead? In many cases, the answer is **yes**. --- ## When Running Kubernetes on a VPS Makes Sense Running Kubernetes on a high-performance VPS is worth it when: ### ✅ You want predictable pricing No surprise network fees. No multi-layered billing structures. ### ✅ Your workloads are containerized but not hyperscale Many applications don’t need multi-region distributed clusters. ### ✅ You value control and flexibility Full root access. Custom networking. Infrastructure the way you want it. ### ✅ You want better cost-performance ratio High-performance CPUs + NVMe storage can outperform entry-level managed nodes. --- ## What You Need for a Production-Ready Setup If you’re running Kubernetes on a VPS, you must choose the right foundation. ### 1️⃣ CPU Power Matters Kubernetes schedules containers across nodes. Weak CPUs cause: - Slow pod scheduling - Poor scaling - High latency under load Modern AMD EPYC processors provide strong multi-core performance for container-heavy workloads. --- ### 2️⃣ NVMe Storage Is Critical Containerized applications generate logs, volumes, cache, and databases. NVMe SSD provides: - Faster I/O - Lower latency - Better performance under load Compared to traditional SSD, NVMe can dramatically improve application responsiveness. --- ### 3️⃣ Sufficient RAM Kubernetes components (kubelet, etcd, controller manager) consume memory. A realistic minimum for production: - 8GB RAM for small clusters - 16GB+ for moderate workloads Under-provisioning memory is the most common mistake. --- ### 4️⃣ Network Stability & DDoS Protection Cloud-native apps often expose APIs publicly. Your VPS provider should offer: - DDoS protection - Stable bandwidth - Low-latency connectivity Without that, Kubernetes won’t save you. --- ## Cost Comparison: Managed Kubernetes vs VPS Let’s look at a simple example. ### Managed Cloud Setup: - Control plane fees - Worker node pricing - Network transfer fees - Load balancer fees Monthly cost can easily exceed $70–$120 for a modest setup. --- ### High-Performance VPS Setup: - 4 vCPU - 8 GB RAM - NVMe storage - Flat monthly pricing Often under $20–$30 per month. For early-stage startups and lean DevOps teams, that difference is massive. --- ## What Are the Trade-Offs? Running Kubernetes on a VPS does require: - Manual setup - Security configuration - Monitoring setup - Backup planning Managed services abstract these away. But for many technical teams, the extra control is worth it. --- ## Is It Worth It in 2026? If you: - Run a SaaS - Deploy microservices - Use CI/CD pipelines - Want predictable infrastructure cost - Don’t need multi-region enterprise scale Then yes — running Kubernetes on a high-performance VPS is absolutely worth it. It offers: - Better cost efficiency - Full infrastructure control - Strong performance - No vendor lock-in Cloud-native doesn’t have to mean enterprise pricing. --- ## Final Thoughts Kubernetes is about flexibility and scalability. A high-performance VPS gives you: - Dedicated resources - Transparent pricing - High-speed storage - Powerful CPUs For many teams in 2026, that’s more than enough. If you’re building modern cloud-native applications, consider whether you truly need managed cloud — or if a powerful VPS can deliver better value. --- Fast. Simple. Reliable. --- ### Docker vs Kubernetes: When to Use Which (2026 Guide) URL: https://rafftechnologies.com/blog/docker-vs-kubernetes-when-to-use-which-2026 Published: 2026-02-15T00:00:00.000Z Description: Docker vs Kubernetes: When to Use Which (2026 Guide) If you're building modern software in 2026, you've probably heard these two names everywhere: - **Docker** - **Kubernetes** They are at the heart of cloud-native development — but they solve different problems. And one of the most common questions developers ask is: **Should I use Docker or Kubernetes?** The answer is simple: Docker helps you *package* applications. Kubernetes helps you *run and manage* them at scale. Let’s break it down clearly. --- ## What Is Docker? Docker is a platform for building and running applications inside **containers**. A container packages everything your app needs: - code - runtime - dependencies - libraries So it runs the same everywhere: - your laptop - staging - production - any cloud VM Docker solves the classic problem: > “It works on my machine, but not on yours.” --- ### Docker Is Best For: ✅ Local development ✅ Packaging applications ✅ Running single services ✅ Simple deployments ✅ Consistent environments If you're a developer shipping an app quickly, Docker is usually step one. --- ## What Is Kubernetes? Kubernetes (K8s) is a container orchestration platform. Once you have many containers running across many machines, you need a system to manage them. Kubernetes automates: - deployments - scaling - load balancing - self-healing - service discovery Kubernetes solves the problem: > “How do I run containers reliably in production at scale?” --- ### Kubernetes Is Best For: ✅ Microservices architectures ✅ Production orchestration ✅ Auto-scaling workloads ✅ High availability systems ✅ Multi-service applications Kubernetes is what teams use when complexity grows. --- ## Key Difference: Packaging vs Orchestration Here is the simplest way to understand it: | Tool | Role | |------|------| | Docker | Builds and runs containers | | Kubernetes | Manages containers at scale | Docker is the container engine. Kubernetes is the container manager. They are not competitors — they work together. --- ## Do You Need Kubernetes? Not always. Kubernetes is powerful, but it introduces complexity. You should ask: - How many services do I run? - Do I need autoscaling? - Do I need high availability? - Do I have a platform team? If you're running one app or a small backend… A VM + Docker might be enough. --- ## When to Use Docker Only Docker alone is perfect when: ### You are building an MVP Startups often need speed, not orchestration. ### You run a single application A monolith or small API can run easily in Docker. ### You want simple deployments Docker Compose can handle multi-container setups without Kubernetes overhead. ### You are learning containers Docker is the entry point into cloud-native development. --- ## When Kubernetes Becomes Necessary Kubernetes makes sense when: ### You have many microservices Service-to-service networking becomes complex. ### You need autoscaling Traffic spikes require dynamic scaling. ### You want self-healing infrastructure Kubernetes restarts failed workloads automatically. ### You run production workloads across multiple nodes Kubernetes balances workloads across machines. ### You need standardized deployment across teams Kubernetes becomes a shared operational layer. --- ## Real-World Example ### Small Startup App - One backend API - One database - Few users Best choice: ✅ VM + Docker No need for Kubernetes. --- ### Scaling SaaS Platform - Multiple services - CI/CD pipelines - Thousands of users - High uptime requirements Best choice: ✅ Kubernetes + containers Kubernetes becomes worth it. --- ## Docker vs Kubernetes in 2026: The Modern Stack In 2026, most modern teams follow this progression: 1. Start with Docker 2. Deploy on VMs 3. Scale services 4. Adopt Kubernetes when needed Cloud-native maturity is a journey, not a starting requirement. --- ## Where Raff Fits In At Raff Technologies, we support developers at every stage: - simple VM deployments - Docker-based environments - cloud-native workflows - scalable infrastructure foundations Our mission is: **Fast. Simple. Reliable.** Whether you're running a single Docker container or preparing for Kubernetes workloads, Raff provides the compute power and simplicity modern teams need. --- ## Final Thoughts Docker and Kubernetes are both essential technologies — but for different reasons. Docker helps you ship applications consistently. Kubernetes helps you operate them reliably at scale. Start simple. Use Docker first. Adopt Kubernetes when your system demands orchestration. That’s the cloud-native way in 2026. --- ### Virtual Machine vs Docker: Which One Should Developers Use? URL: https://rafftechnologies.com/blog/virtual-machine-vs-docker Published: 2025-12-21T00:00:00.000Z Description: Virtual Machine vs Docker: Which One Should Developers Use? As modern development workflows evolve, developers are faced with an important architectural question: **Should you use a Virtual Machine or Docker?** Both technologies are widely used, both solve real problems, and both are often misunderstood. This confusion leads many developers to choose tools based on trends rather than technical fit. This guide breaks it down clearly — without hype. By the end of this article, you’ll understand: - What a Virtual Machine is - What Docker (containers) are - The key differences between VMs and Docker - When developers should use one, the other, or both together --- ## What Is a Virtual Machine? A **virtual machine (VM)** is a fully isolated computer created using software. Each VM includes: - Its own operating system - Allocated CPU, RAM, and storage - Complete isolation from other environments Virtual machines run on top of a **hypervisor**, which manages physical hardware and distributes resources. From a developer’s perspective, a VM behaves exactly like a real server. --- ## What Is Docker? **Docker** is a containerization platform. Instead of virtualizing hardware, Docker: - Shares the host operating system - Packages applications with their dependencies - Runs lightweight, isolated containers Containers start fast, use fewer resources, and are ideal for application-level isolation. Docker is not a virtual machine — it solves a different problem. --- ## Virtual Machine vs Docker: Core Differences | Feature | Virtual Machine | Docker | |------|---------------|--------| | Isolation | Full OS-level isolation | Process-level isolation | | Startup time | Minutes | Seconds | | Resource usage | Higher | Lower | | OS flexibility | Any OS per VM | Same OS kernel | | Security boundary | Stronger | Lighter | | Best use case | Infrastructure, full environments | Application packaging | --- ## Performance Comparison ### Virtual Machines - Dedicated resources - Predictable performance - Better for heavy workloads ### Docker - Extremely fast startup - Lower overhead - Shares host resources For CPU- or memory-intensive tasks, VMs often perform more reliably. For lightweight services, Docker wins on speed. --- ## Security & Isolation Virtual machines offer **stronger isolation**: - Separate kernels - Reduced blast radius - Better suited for multi-tenant environments Docker containers are secure when configured properly, but: - They share the host kernel - A misconfiguration can increase risk For sensitive workloads, VMs are often preferred. --- ## Resource Usage & Cost Docker containers: - Use fewer resources - Allow higher density - Reduce infrastructure cost Virtual machines: - Consume more memory and storage - Cost more per environment - Offer stronger guarantees Cost efficiency depends on workload, not just technology. --- ## Development Workflow Differences ### Virtual Machines Best for: - Full-stack development - Consistent team environments - Cloud-based development workspaces - CI/CD infrastructure ### Docker Best for: - Packaging applications - Microservices - Local development parity - Deployment pipelines Docker shines inside development workflows — not necessarily as the environment itself. --- ## When Developers Should Use Virtual Machines Use a VM when: - You need a full OS environment - You want strong isolation - You’re building cloud-based dev environments - You want production-like infrastructure - You support multiple projects or teams Virtual machines are ideal as **developer workspaces**. --- ## When Docker Makes More Sense Use Docker when: - You package applications - You deploy microservices - You need fast startup times - You want consistent app environments Docker is an excellent **application delivery tool**. --- ## Can Virtual Machines and Docker Be Used Together? Yes — and this is the most common modern setup. Typical architecture: - **Virtual Machine** → provides isolation and infrastructure - **Docker** → runs applications inside the VM This combines: - VM-level security - Docker-level speed and portability For most teams, this hybrid approach works best. --- ## Final Thoughts Virtual machines and Docker are not competitors — they are complementary tools. - Virtual machines solve **infrastructure and environment** problems - Docker solves **application packaging and deployment** problems Developers don’t need to choose one forever. They need to choose what fits the job. In modern cloud-native development, the strongest setups often use **both**. --- ### What Is a Virtual Machine? A Beginner-Friendly Guide (With Real Use Cases) URL: https://rafftechnologies.com/blog/what-is-a-virtual-machine Published: 2026-01-04T00:00:00.000Z Description: What Is a Virtual Machine? A Beginner-Friendly Guide (With Real Use Cases) Virtual machines are everywhere — from cloud platforms and software development to startups and students learning to code. Yet for many beginners, the term **virtual machine (VM)** still sounds complex or intimidating. This guide is written in plain language. No jargon. No assumptions. By the end of this article, you’ll understand: - What a virtual machine really is - How virtual machines work - Why people use virtual machines instead of physical computers - Real-world use cases for beginners, developers, and businesses --- ## What Is a Virtual Machine? A **virtual machine (VM)** is a computer created using software instead of physical hardware. It behaves like a real computer: - It has its own operating system (Windows, Linux, etc.) - It has CPU, RAM, and storage - You can install software, write code, and run applications The key difference? 👉 A virtual machine runs **inside another computer or in the cloud**, sharing physical hardware with other virtual machines. Think of it like this: - A physical computer is a house - A virtual machine is an apartment inside a large building Each apartment is isolated, secure, and independent — even though they share the same structure. --- ## How Does a Virtual Machine Work? At the core of every virtual machine is something called a **hypervisor**. The hypervisor: - Sits between the physical hardware and the virtual machines - Divides CPU, memory, and storage - Ensures each VM runs independently and securely There are two common environments: ### 1. Local Virtual Machines Installed on your own computer using tools like VirtualBox or VMware. Good for: - Learning - Testing software - Running multiple operating systems on one PC Limited by your computer’s power. ### 2. Cloud Virtual Machines Hosted in data centers and accessed over the internet. Good for: - Developers - Teams - Startups - Scalable workloads You rent computing power instead of buying hardware. --- ## Why Do People Use Virtual Machines? Virtual machines solve real, everyday problems. Here are the main reasons people choose VMs: ### 1. Cost Efficiency You don’t need to buy expensive hardware. With cloud virtual machines, you: - Pay only for what you use - Scale up or down instantly - Avoid maintenance costs ### 2. Flexibility Need Linux today and Windows tomorrow? With virtual machines, switching environments takes minutes — not hours or days. ### 3. Isolation & Security Each VM is isolated. If one crashes or gets compromised, others remain safe. ### 4. Speed Launching a new virtual machine can take less than a minute. No waiting for hardware deliveries. --- ## Real Use Cases for Virtual Machines Let’s move from theory to reality. ### Virtual Machines for Beginners & Students Students use virtual machines to: - Learn Linux without breaking their laptop - Practice programming - Run tools their local computer can’t handle A VM becomes a **safe playground** for learning. --- ### Virtual Machines for Developers Developers use virtual machines to: - Build and test applications - Run development environments - Compile code faster than on local machines Many developers now work entirely on cloud VMs and access them remotely. --- ### Virtual Machines for Startups & Small Teams Startups rely on virtual machines to: - Launch products quickly - Control infrastructure costs - Scale without hiring large IT teams Instead of investing in servers, they rent exactly what they need. --- ### Virtual Machines for Testing & Automation Quality assurance teams use VMs to: - Test software on different operating systems - Reproduce bugs - Run automated tests in parallel This saves time and improves reliability. --- ## Virtual Machine vs Physical Computer So, should you use a virtual machine or a physical computer? ### Choose a Virtual Machine if: - You need flexibility - You want to scale easily - You don’t want hardware maintenance - You work remotely ### Choose a Physical Computer if: - You need offline access - You run hardware-dependent workloads - You prefer full local control For many modern use cases, virtual machines are the smarter choice. --- ## Are Virtual Machines Hard to Use? For beginners, traditional VM platforms could feel complex. Modern cloud platforms have changed that. Today, launching a VM often means: 1. Choose your operating system 2. Select performance 3. Click launch No deep technical knowledge required. --- ## The Future of Virtual Machines As remote work, cloud computing, and AI workloads grow, virtual machines are becoming the default computing environment. They are: - Faster to deploy - Easier to manage - More cost-effective For individuals and businesses alike. --- ## Final Thoughts A virtual machine is simply a **computer without the hardware burden**. For beginners, it’s a safe learning environment. For developers, it’s a powerful workspace. For startups, it’s a scalable foundation. Once you understand virtual machines, you start seeing them everywhere — because they power much of the modern internet. If you’re curious to experience one firsthand, modern cloud platforms allow you to launch a virtual machine in minutes and start working immediately. --- ### Then vs. Now: From Retro PCs to Cloud VMs URL: https://rafftechnologies.com/blog/p0qgxdnny4txbr94qsjwhh8d Published: 2025-09-11T00:00:00.000Z Description: Then vs. Now: From Retro PCs to Cloud VMs # From Retro PCs to Cloud Virtual Machines — How Computing Evolved Computing has evolved dramatically over the last few decades. Once, everything depended on the power of the machine under your desk — limited storage, slow processors, and no way to scale. Today, with Cloud Virtual Machines (VMs), developers, startups, and businesses can access scalable, high-performance environments instantly. This post takes a quick look at that journey: from then (retro PCs) to now (cloud VMs). ## Then: The Retro Computer Era Back then, everything was local and limited. - You worked only on the hardware in front of you. - Upgrades meant buying new, expensive parts. - If the machine crashed, your work was at risk. - Sharing or scaling resources was nearly impossible. For developers and web hosters, this created real bottlenecks: slow build times, limited capacity, and no flexibility. ## Now: Cloud Virtual Machines Fast forward to today — the world runs on cloud infrastructure. With VMs, you’re no longer tied to local limitations. - **Scalable** → Start small and expand CPU, RAM, or storage in seconds. - **Secure** → Each VM is isolated, protecting your projects and clients. - **Accessible Anywhere** → Work from any location with an internet connection. - **Cost-Efficient** → Pay only for what you use, without investing in physical hardware. At Raff Technologies, we’ve made launching a VM as simple as clicking a button. Whether you’re a student testing Linux, a freelancer hosting client websites, or a startup preparing to scale, cloud VMs give you the freedom to build without limits. ## Conclusion The evolution from retro PCs to modern VMs shows just how far we’ve come. What used to be limited and local is now scalable, secure, and global. At Raff, we’re not just following this journey — we’re helping shape it. --- ### Why Web Hosters Should Use Virtual Machines URL: https://rafftechnologies.com/blog/n2il3yz5rtxai1spegns684i Published: 2025-09-07T00:00:00.000Z Description: Why Web Hosters Should Use Virtual Machines Web hosting has come a long way from simple shared servers. While shared hosting is still popular, many developers, freelancers, and agencies quickly run into its limitations: **slow performance, lack of control, and restricted scalability**. That’s where **Virtual Machines (VMs)** change the game. For web hosters, switching to VMs means **more freedom, better performance, and a smarter way to grow**. Let’s break down why. ## 1. Full Control Over Your Environment Shared hosting providers limit what you can install or configure. With a **VM**, you’re in charge: - Choose your operating system (Ubuntu, Debian, CentOS, Windows Server, etc.). - Pick your web server (Nginx, Apache, LiteSpeed). - Install the exact packages your projects require. Whether it’s **Ubuntu with Nginx** or **CentOS with Apache**, the setup is completely yours. This level of control lets you **fine-tune performance and security** to fit your clients’ needs — something shared hosting can’t offer. ## 2. Consistent Performance for Your Clients On shared hosting, resources are divided between hundreds of users. One busy neighbor site can affect everyone else. With a **VM**, you get **dedicated CPU, RAM, and storage**. That means: - Faster page loads - Stable uptime - Reliable performance even during traffic spikes Your clients’ websites stay smooth no matter what. ## 3. Scale as Your Business Grows Every successful hosting business faces a moment when clients need more. On shared hosting, this often means **migrating to a bigger plan** or even another server — a disruptive and time-consuming process. With **VMs**, scaling is simple: - Upgrade CPU, memory, or storage instantly - No moving data or risking downtime - Adjust resources as your clients scale You grow as your clients grow. ## 4. Stronger Security and Isolation Shared hosting environments expose you to higher risks. If one site on the server is compromised, the others can be too. A **VM keeps projects isolated**: - Each environment is separate and secure - Even if one site is attacked, others remain unaffected - You manage your own firewall rules, SSH keys, and security updates This isolation gives you **enterprise-grade safety** without the complexity. ## 5. Cost-Effective and Transparent Many hosting providers offer “Pro” plans that sound attractive but **bundle features you might never use**. With modern VM platforms like **Raff**, you: - Only pay for what you use - Avoid long-term contracts and surprise charges - Monitor usage in real-time Our pricing is simple: add credits, launch your VM, and scale as required. No hidden fees. No confusing billing. Just **straightforward, predictable costs**. ## Final Thoughts For web hosters, switching to VMs is like upgrading from a **rented apartment** to your **own house**. You get: - More control - More security - Better performance - The ability to expand without limits At **Raff Technologies**, we’re building a platform where hosting professionals — from freelancers to agencies — can **host smarter, faster, and with full transparency**. 👉 [Launch your first VM with Raff today](https://rafftechnologies.com) --- ### Google Bets Big on Cloud & AI: $9 Billion Expansion in Oklahoma URL: https://rafftechnologies.com/blog/cgrhb28spz3lmsimlzc76s7c Published: 2025-08-29T00:00:00.000Z Description: Google Bets Big on Cloud & AI: $9 Billion Expansion in Oklahoma # A Landmark Investment in Cloud Infrastructure Google has announced a massive **$9 billion investment in Oklahoma** to expand its AI and cloud computing infrastructure. This move includes building a new data center campus in **Stillwater**, expanding its existing **Pryor** campus, and launching education and workforce development programs. The investment signals just how critical **cloud services and artificial intelligence** have become to the global tech ecosystem. ## Why Oklahoma? Oklahoma’s central location, strong energy resources, and growing tech workforce make it a strategic hub for large-scale cloud deployments. By anchoring billions in infrastructure here, Google is not just adding servers — it’s fueling an entire regional cloud economy. Local officials estimate **thousands of jobs** will be created in construction, operations, and supporting industries. Beyond employment, investments in connectivity and renewable energy partnerships are expected to strengthen the state’s role in the digital future. ## The Global Cloud Race Heats Up Google’s bold expansion comes at a time when **AWS, Microsoft, and Oracle** are also doubling down on infrastructure spending worldwide. - **Amazon** recently pledged **$10 billion** for a North Carolina AI and data center campus. - **Oracle** is investing **€3 billion across Europe** to strengthen sovereign cloud capacity. This arms race is about more than storage and servers — it’s about **AI dominance**. Training and running large-scale models requires vast compute power, and whoever builds the biggest, fastest, and most efficient infrastructure will shape the future of **generative AI, machine learning, and cloud services**. ## What This Means for Developers and Businesses For businesses, these mega-investments translate into: - **Lower latency & better performance** as more regional data centers come online. - **Enhanced AI services** thanks to optimized GPU and TPU infrastructure. - **Competitive pricing pressure** as hyperscalers fight for market share. - **Local compliance & data residency options**, crucial for regulated industries. For developers, it means **faster experimentation**, more reliable cloud-native environments, and an ecosystem that is expanding opportunities from small startups to global enterprises. ## Raff’s Perspective At **Raff Technologies**, we see this as a clear signal: cloud is no longer optional — it’s the backbone of innovation. Whether you’re a freelancer, a student, or part of a growing team, the availability of **affordable, scalable compute power** has never been greater. Our mission is to make that power **accessible without the complexity and overhead** of traditional hosting. As hyperscalers like Google expand the frontier, Raff continues to provide developers and small teams with the tools to **build, learn, and scale on their own terms**. Google’s Oklahoma expansion is a reminder that the **cloud revolution** is still accelerating. With billions flowing into AI-ready infrastructure, the next five years will reshape how the world builds software, analyzes data, and interacts with technology. Stay tuned — the cloud wars are just getting started, and every developer stands to benefit. --- ### Why Every Developer Should Have Their Own Virtual Machine URL: https://rafftechnologies.com/blog/g1jn5c8gqgp2dx1o2nw1erf7 Published: 2025-08-19T00:00:00.000Z Description: Why Every Developer Should Have Their Own Virtual Machine In a world where developers are constantly pushing the boundaries of what’s possible, having the right tools can make all the difference. One of the most powerful yet underutilized tools is the **Virtual Machine (VM)** — and every developer should have one in their arsenal. Whether you’re building side projects, running complex workloads, or experimenting with new tech, a VM can give you freedom, flexibility, and firepower that your local machine simply can’t match. ## 1. Instant Access to High-Performance Resources Sometimes, your laptop just isn’t enough. Need more CPU power? Extra RAM? A GPU for training AI models? With a VM, you can scale your resources in minutes — no hardware upgrades, no waiting. 💡 **Example:** Running a large dataset training job on your local machine might take days. On a properly configured VM, you can get it done in hours. ## 2. Experiment Without Fear Developers love experimenting — but breaking your local setup is a pain. A VM lets you spin up an isolated environment, test whatever you want, and roll back instantly if things go wrong. - Try new frameworks without uninstalling half your system. - Test multiple OS configurations. - Run risky scripts in a safe sandbox. ## 3. Work from Anywhere, Seamlessly Your projects, tools, and setup shouldn’t be tied to a single device. A VM is accessible from anywhere with an internet connection, keeping your dev environment exactly the same across devices. - Switch from your desktop at home to a laptop on the road with zero disruption. - No more “it’s only configured on my main machine” excuses. ## 4. Collaboration Made Simple If you’re working in a team, VMs are a dream for consistency: - Share identical environments with teammates. - Avoid the “works on my machine” problem entirely. - Perfect for hackathons, startup teams, and open-source contributors. ## 5. Cost-Effective Scaling Why buy a high-end laptop for a one-time project? With a VM, you pay only for what you use. Spin up a powerful instance for a week, then shut it down when you’re done — and pay nothing while it’s off. ## 6. Real-World Use Cases Here’s how developers are already using VMs: - 🛠️ **Automation & Workflow Tools:** Running 24/7 processes like n8n or CI/CD pipelines. - 🌐 **Web App Hosting:** Deploy MVPs or prototypes before scaling. - 🎓 **Learning & Experimentation:** Practice Docker, Kubernetes, or advanced Linux setups without risk. - 🧪 **DevOps Testing:** Create replicas of production environments for safe debugging. A Virtual Machine isn’t just a tool — it’s a gateway to faster, safer, and more flexible development. With **Raff Technologies**, you can launch a powerful VM in minutes! 👉 [Start Building with Raff](https://rafftechnologies.com) --- ### Disruptive Innovations from Challenger Providers: How New Players Are Shaping the Cloud in 2025 URL: https://rafftechnologies.com/blog/fyx27p29uysz43xa8etzbun6 Published: 2025-08-07T00:00:00.000Z Description: Disruptive Innovations from Challenger Providers: How New Players Are Shaping the Cloud in 2025 # The Rise of Challenger Clouds — Why It’s Good for Developers For years, the cloud market was dominated by the “big three” — **Amazon Web Services, Microsoft Azure, and Google Cloud**. But **2025** is proving to be a turning point. Challenger providers are making headlines with bold innovations, disruptive pricing models, and tailored solutions for developers, startups, and AI-driven workloads. At **Raff Technologies**, we believe this disruption is healthy — driving choice, transparency, and innovation in ways that benefit everyone from solo developers to enterprise teams. ## Nvidia’s DGX Cloud Expansion **Nvidia’s DGX Cloud** continues to expand globally, offering AI researchers and enterprises unprecedented access to GPU clusters optimized for machine learning workloads. By providing plug-and-play AI infrastructure, Nvidia is narrowing the gap between raw computing demand and accessible supply, reshaping expectations for performance and scalability. **Why it matters:** As AI workloads grow exponentially, developers need cloud solutions that balance power and accessibility. Smaller players like **Raff** have an opportunity to provide leaner, faster-to-launch alternatives that don’t require billion-dollar budgets. ## Enfabrica’s EMFASYS: Cutting AI Memory Costs This month, **Enfabrica** unveiled **EMFASYS**, a system designed to lower the soaring costs of AI training by replacing expensive HBM (High Bandwidth Memory) with DDR5-based alternatives. Backed by Nvidia, Enfabrica’s approach could redefine the economics of AI development. **Why it matters:** Lowering infrastructure costs means more startups and indie developers can access advanced AI capabilities. **Raff’s transparent pricing** strategy aligns with this trend — empowering developers to innovate without hidden costs. ## CoreWeave and the Rise of AI-Focused Clouds **CoreWeave**, a specialized cloud provider, is gaining traction by offering GPU-heavy environments tailored specifically for AI and ML. Their rapid growth underscores the hunger for platforms that break away from traditional one-size-fits-all hosting. **Why it matters:** Specialized challengers highlight the demand for customizable solutions. At **Raff**, we’re building with the same spirit: giving developers a platform that’s powerful yet easy to launch, with pricing that scales fairly. ## The Bigger Picture: Why Challenger Clouds Matter Challenger providers aren’t just competing — they’re changing the rules. By rethinking cost structures, introducing specialized infrastructure, and prioritizing developer experience, they’re forcing the cloud giants to evolve. For developers and small teams, this shift is a win: - More choice in providers and configurations - Lower costs through innovative infrastructure - Better performance for AI-driven workloads - Greater transparency — a value we at **Raff** put front and center ## Conclusion: Where Raff Fits In At **Raff Technologies**, we see ourselves as part of this new wave of challengers. While we may not have the scale of Nvidia or the backing of giants, our strength lies in agility, transparency, and a relentless focus on developer needs. In a world where innovation moves fast, **Raff is here to ensure that you don’t just keep up — you stay ahead.** --- ### The Rise of AMD in the Cloud: What It Means for Your Virtual Machine URL: https://rafftechnologies.com/blog/wu7daaz4f7j260axgu4ewiz8 Published: 2025-08-04T00:00:00.000Z Description: The Rise of AMD in the Cloud: What It Means for Your Virtual Machine # The Rise of AMD — And What It Means for Your Virtual Machines In the past five years, **AMD** has gone from an underdog in the server CPU market to a **dominant force powering some of the most efficient and high-performance data centers in the world**. This shift has had a profound impact on **cloud computing** — especially for developers and teams who rely on **virtual machines** to run applications, test code, and build modern infrastructure. At **Raff Technologies**, we chose **AMD EPYC processors** as the backbone of our cloud VM platform — and for good reason. Here’s what the rise of AMD means for your virtual machine experience. ## 1️⃣ More Cores, More Power **AMD EPYC chips**, particularly the latest generations, offer significantly **higher core counts** than traditional server CPUs. For VM users, this translates to: - ⚡ Faster **parallel processing** - 🧑‍💻 Better **multitasking** - 🏗️ Higher **VM density per host** (without sacrificing performance) 💡 **Game-changer for developers:** Running **Docker containers, CI/CD pipelines, self-hosted apps**, and **full-stack environments** becomes smoother and faster. ## 2️⃣ Better Performance per Dollar One of AMD’s biggest advantages is **delivering excellent performance at a lower cost**. For developers, this means: - 🚀 Competitive pricing **without compromising on speed** - 💸 Infrastructure efficiency passed **directly to users** If you’ve been burned by **hidden costs** or **sluggish VM performance** on other platforms, you’ll feel the difference on a **Raff-powered AMD machine**. ## 3️⃣ Energy Efficiency = Sustainability + Savings AMD’s server-grade chips are built with **power efficiency in mind**. This is good not just for reducing our **data center energy footprint**, but also for: - 🌱 Lower cooling and operational costs - ♻️ Longer-lasting hardware and sustainable infrastructure When you launch a VM with us, you're not only getting **raw compute power** but also contributing to a **more sustainable cloud ecosystem**. ## 4️⃣ Industry Validation — AMD Is the New Standard It’s not just us. Major providers like **AWS, Azure, and Oracle Cloud** are integrating **AMD EPYC** into their infrastructure. That’s a clear signal: **AMD is no longer a niche option — it’s becoming the industry default for high-efficiency compute.** At **Raff**, we were early adopters because we believe in providing **developers with cutting-edge, affordable infrastructure**. ## 5️⃣ What This Means for You When you spin up a VM on Raff, you're getting: - 🔑 **Full root access** on AMD EPYC-backed machines - ⚡ **Faster provisioning** and quick boot times - 🛡️ **Reliable performance under load** - 💵 **Transparent pricing** based on real efficiency Whether you're: - Deploying production code - Running automation tools like **n8n** - Hosting APIs or databases - Learning and experimenting AMD gives your **virtual machine the muscle it needs** — without the noise or overhead. ## 🚀 Ready to Try It for Yourself? Launch your next VM on **AMD EPYC-powered infrastructure** at [rafftechnologies.com](https://rafftechnologies.com). Experience the rise of **better, faster, and more sustainable cloud computing**. --- ### What Can You Build with n8n? 10 Real Use Cases You Can Deploy Today URL: https://rafftechnologies.com/blog/w4rbnhj7kfhe4ww99w75jnal Published: 2025-07-28T00:00:00.000Z Description: What Can You Build with n8n? 10 Real Use Cases You Can Deploy Today # Why This Matters — Unlock the Power of n8n + Raff Most automation tools do the basics: move data from A to B, send a notification, post a tweet. But **n8n** is different — it gives you **control, flexibility, and real power**. When combined with **Raff’s one-click n8n VMs**, it becomes a **developer playground** for building custom agents, internal workflows, and full-stack automations — with or without code. Let’s explore what’s possible. ## 1️⃣ Gmail → Google Drive → Telegram: A Smart File Router When an email arrives with an attachment: - Save it to a specific Google Drive folder - Send a Telegram message with the file link ✅ Useful for: - Invoice collection - Content submissions - Remote collaboration ## 2️⃣ Webhook → Build Trigger → Slack Notify Connect your Git repo or CI/CD service. When a webhook fires: - Trigger a build - Notify the team on Slack - Log it to Google Sheets or Notion ✅ Perfect for: - DevOps teams - Side projects - Solo developers ## 3️⃣ Social Media Auto-Poster - Create a post in Airtable or Notion - Automatically publish it to X, LinkedIn, Instagram - Get analytics via webhook later ✅ Built for: - Content marketers - Indie founders - Personal branding ## 4️⃣ Stripe → Notion CRM → Email Every time a payment is made on Stripe: - Add the customer to a Notion database - Send them a personalized thank-you email - Notify your internal team on Slack ✅ Great for: - SaaS teams - Freelancers - Agencies ## 5️⃣ n8n as a Personal Assistant - Pull weather data in the morning - Combine with your calendar events - Send you a morning summary via WhatsApp or Email 💡 Build your own daily dashboard agent and tweak it however you want. ## 6️⃣ Auto Backup to S3 or Dropbox - Schedule a job every night - Export your database or app data - Upload it to cloud storage ✅ Useful for: - Data retention - Peace of mind - GDPR & compliance workflows ## 7️⃣ AI Workflows with OpenAI + Webhooks - Use webhooks to receive questions - Process them with GPT-4 - Return the answer to Slack, Telegram, or your custom frontend 🚀 Build intelligent agents, chatbots, or content generators. ## 8️⃣ Monitor Prices or Keywords - Use HTTP request nodes to scrape or ping APIs - Monitor product price changes or SEO rankings - Alert when thresholds are met ✅ Ideal for: - Growth hackers - Competitor monitoring - Product teams ## 9️⃣ Lead Capture + Auto Follow-up - Capture leads via Typeform or custom form - Add to CRM (HubSpot, Notion, Airtable) - Schedule follow-up emails at 24h and 72h ⚡ Helps small teams run big workflows **without touching code**. ## 🔟 Build Your Own SaaS Backend (Yes, Seriously) - Use n8n to handle incoming API requests - Route logic through various services - Store, transform, and trigger actions visually 💡 Many founders prototype their MVP backend logic this way before writing a single file. ## Why Use Raff for This? Because none of the above should take you hours to deploy. With **Raff**, you: - 🚀 Launch n8n in seconds - ⚡ Skip server setup - 📈 Scale workflows painlessly - 🔒 Keep full control (private, customizable, yours) You bring the logic — we bring the speed. ## Final Thought **n8n isn’t just an automation tool — it’s a creative engine** for developers, makers, and ambitious teams. With **Raff**, it’s easier than ever to go from **idea to automation fast**. 👉 [Start building now at rafftechnologies.com](https://www.rafftechnologies.com) --- ### 10 Things You Can Automate with Your Cloud VM URL: https://rafftechnologies.com/blog/icbq0v5en1152yactpst22ie Published: 2025-07-24T00:00:00.000Z Description: 10 Things You Can Automate with Your Cloud VM # 10 High-Impact Tasks You Can Automate With Your Raff Cloud VM Spinning up a VM is just the beginning. Once it’s live, the real magic happens when you use it as your own programmable, always-on machine. Whether you're a **developer**, **tester**, **freelancer**, or **indie builder**, here are 10 high-impact tasks you can automate with your Raff cloud VM. ## 1. Run Scheduled Jobs with Cron Use your VM like a reliable cloud-based task scheduler. Automate: - Daily database backups - Data scraping - Email summaries - Scripted deployments It’s as simple as setting up a `crontab` on your Linux instance. ## 2. Deploy GitHub Actions Runners Want full control over your CI pipeline? Set up a **self-hosted GitHub Actions runner** on your VM to: - Speed up workflows - Avoid GitHub's shared runners' timeouts - Run private scripts securely 💡 *Bonus: You can stop the VM when not in use to save costs.* ## 3. Auto-Build and Push Docker Images Use your VM to: - Pull the latest code from GitHub - Build Docker images - Push them to Docker Hub or your private registry Perfect for **staging environments** or **internal tooling**. ## 4. Self-Host Developer Tools Your Raff VM can automate the setup and uptime of tools like: - **JupyterLab** - **VS Code Server** - **Postgres / MongoDB** - **Jenkins / CI dashboards** - **Tailscale or WireGuard** for remote access Install once, run forever. ## 5. Webhooks and Lightweight API Services Want to automate Slack alerts, database updates, or webhook listening? Use **Flask**, **FastAPI**, or **Node.js** to deploy tiny HTTP endpoints that run 24/7 and automate your side-project workflows. ## 6. Mirror & Backup Git Repos Use **cron + shell scripts** to regularly mirror important Git repos to your private storage. Peace of mind, automated. ## 7. Host Your Portfolio or Resume API Set it once, forget it. You can host: - A static portfolio site - Your resume as a JSON API - A Notion-to-site mirror …and automate the refresh too — without needing Vercel or Netlify. ## 8. Monitor Your Personal or Client Websites Run tools like **Uptime-Kuma** or simple bash + `curl` scripts to: - Monitor your sites - Get downtime alerts via email or Telegram - Log response times Lightweight and powerful. ## 9. Convert Your VM Into a Discord/Telegram Bot Server Spin up bots that: - Respond to commands - Automate group tasks - Monitor mentions or RSS feeds Schedule their tasks, keep logs, and scale them easily. ## 10. Automate Learning or Research Workflows Use your VM to: - Download daily articles, papers, or podcasts - Summarize content with an LLM - Push notes to your **Obsidian**, **Notion**, or email inbox It becomes your **always-on second brain**. ## Final Thoughts **Raff** gives you a clean, powerful VM with no bloat, no overcomplication, and no surprise pricing. That means you're free to automate securely, affordably, and on your terms. 👉 [Launch your first VM today](https://rafftechnologies.com) --- ### Quantum Computing Meets Cloud: Preparing for the Next Tech Revolution URL: https://rafftechnologies.com/blog/x8dxh1o0edk4qmgq5pp2515l Published: 2025-07-14T00:00:00.000Z Description: Quantum Computing Meets Cloud: Preparing for the Next Tech Revolution # Preparing for the Quantum Future: Why Developers Should Start Now Quantum computing is no longer just the subject of academic research or science fiction. It is approaching a real-world tipping point. As **Nvidia CEO Jensen Huang** recently noted, quantum computing has reached an “inflection point” — a moment where research is rapidly translating into practical applications. While widespread quantum adoption may still be years away, one thing is clear: developers, cloud platforms, and infrastructure providers need to start preparing now. At **Raff Technologies**, we believe that the cloud must evolve alongside emerging compute paradigms — including quantum — and stay developer-first every step of the way. ## What Makes Quantum Computing Different? Quantum computers process information in fundamentally different ways from classical computers. Rather than using bits (0s and 1s), they use **qubits**, which can exist in multiple states simultaneously due to superposition and entanglement. This allows them to: - Solve specific classes of problems **exponentially faster** - Simulate **molecular and quantum systems** more accurately - Optimize complex systems far beyond traditional computing limits ## Why Developers Should Start Paying Attention Most developers won’t be writing code for quantum computers tomorrow — but preparing for the shift now can create opportunities. Here’s why: ### 1. Hybrid Models Will Become the Norm Many early applications will combine **quantum and classical computing**, requiring cloud platforms that support both environments flexibly. ### 2. Quantum APIs Are Already Emerging Frameworks like **Qiskit** (IBM), **Cirq** (Google), and **Braket** (AWS) are giving developers a sandbox to begin exploring quantum algorithms using simulators or real quantum processors via the cloud. ### 3. Cloud Infrastructure Will Need to Be Quantum-Ready Quantum jobs will require specialized orchestration. Developers and startups will increasingly look for platforms that support experimentation and simulation in a lightweight, affordable way. ## How the Cloud Plays a Role in the Quantum Future Quantum computers will not be personal devices. They will live in highly controlled environments accessed primarily through the cloud. Here’s what this means for infrastructure: - Developers need access to **quantum simulators** and hybrid architectures - Tooling must integrate easily with traditional languages and platforms - Workloads will need to scale elastically between classical and quantum layers - Pricing models must evolve to match short, intensive workloads ## Raff’s Vision: A Cloud Platform That Evolves With Developers While **Raff** does not (yet) offer quantum computing services, our infrastructure is designed to support rapid technological change: - We provide **on-demand, pre-configured environments** developers can adapt quickly - Our **flat-rate pricing** makes experimentation affordable and transparent - Our architecture is **flexible by design**, capable of integrating emerging APIs and toolkits as demand grows We believe platforms shouldn’t just support today’s workflows — they should prepare builders for what’s next. Quantum computing may still be early, but the developer ecosystem needs to start adapting today. The next wave of innovation will come not just from quantum breakthroughs but from making those breakthroughs accessible. At **Raff**, our mission is to stay out of the way and let developers build — whether it's with containers, machine learning, or eventually, quantum systems. 👉 [Visit rafftechnologies.com](https://rafftechnologies.com) to launch your dev environment in seconds — and prepare for what’s next. --- ## Tutorials ### How to Install Node.js on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-nodejs-ubuntu-24-04 Description: Install Node.js 24 LTS and npm on Ubuntu 24.04 on a Raff VM. Covers NodeSource, nvm, build tools, local HTTP testing, Express, and cleanup. In this tutorial, you will install Node.js 24 LTS and npm on Ubuntu 24.04, verify the runtime, install build tools for native modules, run a localhost-only HTTP test, and create a small Express application. Node.js is a JavaScript runtime used for APIs, web applications, command-line tools, automation, and server-side frameworks. For production workloads, the Node.js project recommends using an LTS release. As of August 14, 2026, Node.js 24 is an LTS line while Node.js 26 is the Current line. Raff Technologies supports 3,000+ customers and 15,000+ VMs. A Raff Linux VM provides Ubuntu, root access, NVMe storage, 3 Gbps unmetered VM traffic, snapshots, backups, firewall controls, and the networking foundation for Node.js workloads. The original Node.js 24 workflow was tested on a Raff Ubuntu 24.04 VM with 1 vCPU and 2 GB RAM. This revision refreshes the NodeSource, Node.js LTS, and nvm guidance against current project documentation dated August 14, 2026. Prerequisites: - A [Raff Ubuntu 24.04 VM](/products/linux-vm) - SSH access with a non-root user that has sudo privileges - At least 2 GB RAM for the tested setup - Internet access from the VM for APT and npm downloads > **Installation choice:** This tutorial uses NodeSource for the primary system-wide Node.js 24 installation. Use nvm instead when one user needs to switch between multiple Node.js versions. Do not install both methods unless you understand which `node` binary your shell and services will use. ## Step 1 — Prepare Ubuntu 24.04 Update the package index and install the tools required to add the NodeSource repository: ```bash sudo apt update sudo apt install -y ca-certificates curl gnupg ``` Confirm the Ubuntu release: ```bash lsb_release -ds ``` Expected output includes: ```text Ubuntu 24.04 LTS ``` Check whether an older Node.js runtime is already installed: ```bash node --version 2>/dev/null || echo "Node.js is not installed" npm --version 2>/dev/null || echo "npm is not installed" ``` If an existing application depends on the installed version, do not replace it until you have reviewed that application’s compatibility and rollback plan. Verification is complete when Ubuntu 24.04 is confirmed and you know whether an existing Node.js installation is present. ## Step 2 — Add the NodeSource repository for Node.js 24 NodeSource publishes Node.js 24 packages for Ubuntu 24.04. Download the setup script to a file instead of piping it directly into a privileged shell: ```bash curl -fsSL https://deb.nodesource.com/setup_24.x -o /tmp/nodesource_setup.sh ``` Inspect the downloaded script before running it: ```bash sed -n '1,160p' /tmp/nodesource_setup.sh ``` Run the repository setup: ```bash sudo -E bash /tmp/nodesource_setup.sh ``` Refresh APT metadata: ```bash sudo apt update ``` Verify that APT now sees a NodeSource candidate: ```bash apt-cache policy nodejs | sed -n '1,16p' ``` Expected output includes a `Candidate:` entry from the NodeSource repository. NodeSource’s current distribution matrix lists Ubuntu 24.04 (`noble`) as supported for Node.js 24. Verification is complete when `apt-cache policy nodejs` shows a NodeSource candidate for the Node.js 24 line. ## Step 3 — Install Node.js 24 LTS and npm Install the Node.js package: ```bash sudo apt install -y nodejs ``` Verify Node.js and npm: ```bash node --version npm --version ``` Expected version pattern: ```text v24.x.x 11.x.x ``` As of August 14, 2026, the current Node.js 24 LTS release is `v24.18.1`. Your patch version may be newer when you run the tutorial. Confirm which binaries are active: ```bash command -v node command -v npm ``` For the NodeSource system-wide installation, the paths should normally resolve under `/usr/bin/`. Verification is complete when `node --version` reports `v24.x.x`, npm runs successfully, and the active binaries are the system-wide installation you intended to use. ## Step 4 — Install build tools for native npm modules Some npm dependencies include native addons that need a compiler toolchain when a compatible prebuilt binary is unavailable. Install Ubuntu’s build tools: ```bash sudo apt install -y build-essential ``` Verify the compiler and build utility: ```bash gcc --version | head -n 1 make --version | head -n 1 ``` Expected output includes a GCC version and GNU Make version. Verification is complete when both `gcc` and `make` are available. ## Step 5 — Verify Node.js with a localhost-only HTTP server Create a test project directory: ```bash mkdir -p ~/hello-node cd ~/hello-node ``` Create a small HTTP server: ```bash cat > server.js <<'EOF' const http = require('node:http'); const host = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end('Hello from Node.js on Raff!\n'); }); server.listen(port, host, () => { console.log(`Server running at http://${host}:${port}/`); }); EOF ``` Start the server: ```bash node server.js ``` In a second SSH session, test it locally: ```bash curl -i http://127.0.0.1:3000 ``` Expected output includes: ```text HTTP/1.1 200 OK Hello from Node.js on Raff! ``` Confirm that the test server is not listening publicly: ```bash ss -lntp | grep ':3000' ``` Expected listening address: ```text 127.0.0.1:3000 ``` Stop the foreground server with `Ctrl+C` after verification. Do not open port `3000` through UFW for this installation test. A production Node.js application should normally stay behind a reverse proxy or another controlled ingress path. Verification is complete when the local HTTP request returns `200 OK` and Node.js listens only on `127.0.0.1:3000`. ## Step 6 — Initialize npm and verify an Express dependency Initialize a package manifest: ```bash cd ~/hello-node npm init -y ``` Install Express locally in the project: ```bash npm install express ``` Verify that npm recorded the dependency: ```bash npm ls express ``` Create a small Express application: ```bash cat > app.js <<'EOF' const express = require('express'); const app = express(); const host = '127.0.0.1'; const port = 3000; app.get('/', (req, res) => { res.type('text/plain').send('Express is running on Node.js 24\n'); }); app.get('/health', (req, res) => { res.status(200).json({ status: 'ok' }); }); app.listen(port, host, () => { console.log(`Express listening on http://${host}:${port}`); }); EOF ``` Run the application: ```bash node app.js ``` In a second SSH session, verify both routes: ```bash curl http://127.0.0.1:3000/ curl http://127.0.0.1:3000/health ``` Expected output: ```text Express is running on Node.js 24 {"status":"ok"} ``` Stop the foreground process with `Ctrl+C`. Verification is complete when `npm ls express` succeeds and both Express routes return the expected response. ## Step 7 — Verify the complete Node.js installation Run the final checks: ```bash node --version npm --version command -v node command -v npm gcc --version | head -n 1 cd ~/hello-node npm ls express node -e "console.log(process.version, process.platform, process.arch)" ``` Expected state: ```text Node.js reports v24.x.x npm reports 11.x.x node and npm are available system-wide GCC is installed Express is present in the project Node.js reports linux and the VM architecture ``` The installation is complete when Node.js 24 LTS, npm, the native-module build toolchain, the local HTTP test, and the Express dependency test all succeed. :::cta Deploy Your Server Launch an Ubuntu 24.04 VM and install the Node.js 24 LTS runtime for your application environment. ::: ## Alternative: Install Node.js 24 with nvm Use nvm when a development user needs multiple Node.js versions or wants Node.js installed entirely inside the user account. The Node.js download page currently presents nvm as a Linux installation option, and the nvm project’s current installer release is `v0.40.6`. Download the installer to a file: ```bash curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh -o /tmp/nvm-install.sh ``` Inspect it: ```bash sed -n '1,160p' /tmp/nvm-install.sh ``` Run it as your normal user: ```bash bash /tmp/nvm-install.sh ``` Load nvm into the current shell: ```bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" ``` Install Node.js 24 and make it the default for this user: ```bash nvm install 24 nvm alias default 24 nvm use 24 ``` Verify: ```bash nvm --version node --version npm --version command -v node ``` With nvm, `command -v node` should point inside the user’s `~/.nvm/` directory instead of `/usr/bin/node`. Do not assume an nvm-managed binary path is stable in a systemd unit after changing Node.js versions. For production services, either use a stable system-wide runtime or deliberately update the service’s `ExecStart` path when the nvm version changes. ## Why the Ubuntu 24.04 default package is not the primary method Ubuntu 24.04’s original distribution package is from the Node.js 18 generation. Node.js 18 reached end-of-life on March 27, 2025, so a fresh production deployment should not deliberately choose that branch simply because it is available from the base distribution repository. Use a currently supported LTS line instead. The Node.js project states that production applications should use Active LTS or Maintenance LTS releases. ## Cleanup and rollback Remove only the tutorial project files: ```bash rm -rf ~/hello-node ``` To remove the NodeSource-installed Node.js package while leaving the repository configuration in place: ```bash sudo apt remove -y nodejs ``` To remove the NodeSource repository configuration as well: ```bash sudo rm -f /etc/apt/sources.list.d/nodesource.list sudo rm -f /etc/apt/keyrings/nodesource-repo.gpg sudo apt update ``` The exact NodeSource key filename can vary between installer revisions. List `/etc/apt/keyrings/` and remove only the NodeSource key that actually exists on your VM. If you used nvm instead, list installed versions first: ```bash nvm ls ``` Then uninstall only the Node.js version you no longer need: ```bash nvm uninstall 24 ``` Do not remove a runtime that an existing application or systemd service still depends on. ## Troubleshooting ### `node --version` does not report v24 Check which binary is active and which package APT selected: ```bash command -v node node --version apt-cache policy nodejs | sed -n '1,20p' ``` If `/usr/bin/node` is not from the NodeSource 24 repository, review the repository setup and reinstall only after confirming no application depends on the current runtime. ### The NodeSource repository is missing Check the APT source files: ```bash grep -R "deb.nodesource.com" /etc/apt/sources.list.d/ /etc/apt/sources.list 2>/dev/null ``` Re-download and inspect the current NodeSource 24 setup script before running it again: ```bash curl -fsSL https://deb.nodesource.com/setup_24.x -o /tmp/nodesource_setup.sh sed -n '1,160p' /tmp/nodesource_setup.sh sudo -E bash /tmp/nodesource_setup.sh sudo apt update ``` ### `nvm: command not found` Load nvm directly: ```bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" nvm --version ``` If the command works after loading `nvm.sh`, open a new login shell and verify that your shell profile contains the nvm initialization lines. ### An npm package fails while compiling a native addon Confirm the build toolchain: ```bash gcc --version make --version python3 --version ``` Install the base tools if needed: ```bash sudo apt install -y build-essential python3 ``` Then retry the package installation from the application directory. Some projects may require additional development libraries documented by that package. ### npm reports permission errors for global packages Do not solve npm permission errors with broad filesystem permissions such as `chmod 777`. Prefer project-local dependencies, nvm for user-scoped global tools, or the package manager recommended by the tool you are installing. For production process management, follow [Deploy Node.js with PM2 on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04) instead of adding PM2 to this installation tutorial. ### The local HTTP test does not respond Check whether another process owns port `3000`: ```bash ss -lntp | grep ':3000' ``` Check the Node.js process output for an error, then retry on a different loopback port if necessary. Do not expose the troubleshooting port publicly just to make the local test pass. ## Conclusion and next steps You installed Node.js 24 LTS and npm on Ubuntu 24.04 using a system-wide NodeSource package, added build tools for native modules, verified the runtime with a localhost-only HTTP server, and confirmed npm dependency management with Express. For a production application, continue with [Deploy Node.js with PM2 on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04), [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), or [Deploy Next.js with PM2 and Nginx](/learn/tutorials/deploy-nextjs-ubuntu-24-04-pm2-nginx). Keep the application runtime private behind the intended ingress path rather than exposing a development port directly to the internet. --- ### How to Self-Host n8n on Ubuntu 24.04 with Docker Compose URL: https://rafftechnologies.com/learn/tutorials/self-host-n8n-docker Description: Self-host n8n on Ubuntu 24.04 with Docker Compose, PostgreSQL, Nginx, HTTPS, localhost-only exposure, backups, security auditing, and updates. In this tutorial, you will self-host n8n on Ubuntu 24.04 with Docker Compose, PostgreSQL, Nginx, HTTPS, localhost-only application exposure, execution pruning, backups, and an end-to-end workflow check. n8n is a self-hostable workflow automation platform for connecting APIs, applications, databases, triggers, and custom logic into reusable workflows. Raff Technologies supports 3,000+ customers and 15,000+ VMs, and a Raff Linux VM provides the persistent compute, NVMe storage, firewall controls, backups, and 3 Gbps unmetered VM traffic needed for an always-on automation server. > **Faster path on Raff:** A real n8n template is available through the [Raff Marketplace](/marketplace/n8n). Use that path when you want a preconfigured n8n deployment. Continue with this tutorial when you specifically want to build and operate the Docker Compose stack yourself. This revision targets the current stable n8n 2.x line and pins `2.32.6`, the stable release shown by the official n8n release channel during this revision. The previous Raff article had its Docker Compose, PostgreSQL, Nginx, backup, and security flow reviewed in July 2026; this updated 2.x stack is published with that limitation stated rather than implying a new end-to-end test was completed. Prerequisites: - A [Raff Ubuntu 24.04 VM](/products/linux-vm) with at least 2 GB RAM; 4 GB is the practical baseline for n8n plus PostgreSQL - SSH access with a non-root sudo user - A domain such as `n8n.example.com` pointed to the VM public IPv4 address - Docker Engine with the Docker Compose plugin installed using [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) - Ports `80/tcp` and `443/tcp` available for Nginx ## Step 1 — Prepare Ubuntu, DNS, and Docker Update Ubuntu and install the utilities used later: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y curl ca-certificates openssl nginx ufw snapd dnsutils ``` Verify Docker and Compose: ```bash docker --version docker compose version ``` Confirm the domain resolves to this Raff VM: ```bash dig +short n8n.example.com A ``` Compare the result with the VM public IPv4 address shown in the Raff dashboard. Verification is complete when Docker and `docker compose` both run and the domain resolves to the correct VM. ## Step 2 — Create the n8n project and backup directories Create a dedicated project directory: ```bash sudo mkdir -p /opt/n8n/backups sudo chown -R "$USER":"$USER" /opt/n8n cd /opt/n8n ``` Check ownership: ```bash ls -ld /opt/n8n /opt/n8n/backups ``` Verification is complete when both directories exist and are writable by your administrative user. ## Step 3 — Create protected n8n secrets and environment settings Generate a database password and an n8n encryption key: ```bash openssl rand -base64 36 openssl rand -hex 32 ``` Store both values in a password manager. Create `/opt/n8n/.env`: ```bash nano /opt/n8n/.env ``` Add the following values and replace each placeholder: ```dotenv N8N_VERSION=2.32.6 N8N_DOMAIN=n8n.example.com GENERIC_TIMEZONE=UTC POSTGRES_DB=n8n POSTGRES_USER=n8n POSTGRES_PASSWORD=REPLACE_WITH_A_LONG_RANDOM_DATABASE_PASSWORD N8N_ENCRYPTION_KEY=REPLACE_WITH_THE_64_CHARACTER_HEX_VALUE ``` Protect the file: ```bash chmod 600 /opt/n8n/.env ``` Verify the mode without printing the secrets: ```bash stat -c '%a %n' /opt/n8n/.env ``` Expected output begins with: ```text 600 /opt/n8n/.env ``` The encryption key is required to decrypt stored credentials after a restore. Keep an off-server copy with your backup material. Verification is complete when `.env` exists with mode `600` and the secrets are also stored outside the VM. ## Step 4 — Create the Docker Compose stack Create `/opt/n8n/compose.yaml`: ```bash nano /opt/n8n/compose.yaml ``` Add: ```yaml name: n8n services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 10 n8n: image: docker.n8n.io/n8nio/n8n:${N8N_VERSION} restart: unless-stopped depends_on: postgres: condition: service_healthy ports: - "127.0.0.1:5678:5678" environment: DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_PORT: 5432 DB_POSTGRESDB_DATABASE: ${POSTGRES_DB} DB_POSTGRESDB_USER: ${POSTGRES_USER} DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD} N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY} N8N_HOST: ${N8N_DOMAIN} N8N_PORT: 5678 N8N_PROTOCOL: https N8N_EDITOR_BASE_URL: https://${N8N_DOMAIN}/ WEBHOOK_URL: https://${N8N_DOMAIN}/ N8N_PROXY_HOPS: 1 N8N_SECURE_COOKIE: "true" N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true" GENERIC_TIMEZONE: ${GENERIC_TIMEZONE} TZ: ${GENERIC_TIMEZONE} EXECUTIONS_DATA_PRUNE: "true" EXECUTIONS_DATA_MAX_AGE: 168 volumes: - n8n_data:/home/node/.n8n volumes: postgres_data: name: n8n_postgres_data n8n_data: name: n8n_data ``` This stack keeps n8n on `127.0.0.1:5678`; port `5678` is not exposed directly to the public internet. Nginx will be the public HTTPS entry point. Validate the Compose configuration: ```bash cd /opt/n8n docker compose config >/tmp/n8n-compose-rendered.yaml head -n 20 /tmp/n8n-compose-rendered.yaml ``` Do not share the rendered file publicly because it contains resolved environment values. Verification is complete when `docker compose config` exits successfully and both services appear in the rendered configuration. ## Step 5 — Start PostgreSQL and n8n Start the stack: ```bash cd /opt/n8n docker compose up -d ``` Check container state and logs: ```bash docker compose ps docker compose logs --tail=100 postgres docker compose logs --tail=100 n8n ``` Test the n8n health endpoint locally: ```bash curl -i http://127.0.0.1:5678/healthz ``` Confirm port `5678` is loopback-only: ```bash ss -lntp | grep ':5678' ``` Expected listening address includes: ```text 127.0.0.1:5678 ``` Verification is complete when PostgreSQL is healthy, n8n is running, `/healthz` responds, and port `5678` is bound only to loopback. ## Step 6 — Configure Nginx as the reverse proxy Create the Nginx server block: ```bash sudo nano /etc/nginx/sites-available/n8n.example.com ``` Add: ```nginx server { listen 80; listen [::]:80; server_name n8n.example.com; client_max_body_size 50M; location / { proxy_pass http://127.0.0.1:5678; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_buffering off; proxy_read_timeout 300s; } } ``` Replace the example hostname with your real domain, then enable the site: ```bash sudo ln -sfn /etc/nginx/sites-available/n8n.example.com \ /etc/nginx/sites-enabled/n8n.example.com sudo nginx -t sudo systemctl reload nginx ``` Test the HTTP route: ```bash curl -I http://n8n.example.com ``` Verification is complete when `nginx -t` reports success and the domain reaches Nginx without exposing port `5678` publicly. ## Step 7 — Configure UFW and HTTPS Allow SSH before enabling UFW: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw --force enable sudo ufw status numbered ``` Install Certbot using its snap path: ```bash sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot ``` Request a certificate and enable the redirect: ```bash sudo certbot --nginx --redirect -d n8n.example.com ``` Verify HTTPS and renewal: ```bash curl -I https://n8n.example.com sudo certbot renew --dry-run ``` Do not add a UFW rule for `5678/tcp`. Verification is complete when HTTPS succeeds, renewal simulation passes, and UFW allows only the intended SSH/HTTP/HTTPS paths. ## Step 8 — Create the owner account and verify webhook URLs Open: ```text https://n8n.example.com ``` Create the first owner account using a unique password. Create a small workflow with a **Manual Trigger** and **Edit Fields** node, execute it, and confirm the result appears in the Executions view. Then add a Webhook node and inspect both the test and production webhook URLs. They should use your HTTPS hostname rather than `localhost`, the container name, or port `5678`. From the VM, confirm the configured public values: ```bash cd /opt/n8n docker compose exec n8n env | grep -E '^(N8N_HOST|N8N_PROTOCOL|N8N_EDITOR_BASE_URL|WEBHOOK_URL|N8N_PROXY_HOPS)=' ``` Verification is complete when the editor loads over HTTPS, a manual workflow executes successfully, and generated webhook URLs use the public HTTPS domain. ## Step 9 — Run the n8n security audit Run the built-in security audit: ```bash cd /opt/n8n docker compose exec n8n n8n audit ``` Review every finding rather than treating a clean report as a complete security guarantee. Remove unused credentials, review community nodes before installation, and restrict who can edit production workflows. Verification is complete when the audit runs successfully and each reported item has been reviewed or assigned for remediation. ## Step 10 — Configure retention and create backups The Compose file prunes execution records older than seven days: ```dotenv EXECUTIONS_DATA_PRUNE=true EXECUTIONS_DATA_MAX_AGE=168 ``` Monitor PostgreSQL and host storage: ```bash cd /opt/n8n set -a source .env set +a docker compose exec -T postgres \ psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ -c "SELECT pg_size_pretty(pg_database_size(current_database()));" docker system df df -h / ``` Create a database dump: ```bash docker compose exec -T postgres \ pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ > "backups/n8n-db-$(date +%F).sql" ``` Archive the n8n data volume: ```bash docker run --rm \ -v n8n_data:/data:ro \ -v /opt/n8n/backups:/backup \ alpine \ tar -czf "/backup/n8n-data-$(date +%F).tar.gz" -C /data . ``` Back up `compose.yaml`, the protected `.env`, and the encryption key to a protected off-server location. A database dump without the matching encryption key is not a complete credential recovery plan. Check the files: ```bash ls -lh /opt/n8n/backups ``` n8n external S3 binary storage is a Self-hosted Enterprise feature. Community deployments should plan local persistent-volume capacity and backups instead of assuming an S3 bucket can replace local binary storage. Verification is complete when a fresh PostgreSQL dump and n8n data archive exist and an off-server copy of the configuration and encryption key is defined. ## Step 11 — Update n8n with a rollback path Before an update, create fresh backups and review n8n release notes and breaking changes. Edit the pinned version in `.env` only after choosing the exact target version: ```bash nano /opt/n8n/.env ``` Pull the chosen image and recreate the service: ```bash cd /opt/n8n docker compose pull n8n docker compose up -d n8n ``` Check the running version and logs: ```bash docker compose exec n8n n8n --version docker compose logs --tail=200 n8n curl -I https://n8n.example.com ``` If the update fails, restore the previous `N8N_VERSION` value, pull that image, and recreate the n8n service. Database migrations can make some downgrades unsafe, so read the version-specific migration notes before relying on image rollback alone. Verification is complete when the intended n8n version is running and the HTTPS endpoint still responds after the update. ## Step 12 — Verify the self-hosted n8n deployment end to end Run the final server checks: ```bash cd /opt/n8n docker compose ps docker compose exec n8n n8n --version curl -fsS http://127.0.0.1:5678/healthz curl -I https://n8n.example.com ss -lntp | grep ':5678' sudo ufw status numbered ls -lh /opt/n8n/backups ``` In the n8n UI, confirm all of the following: - The editor loads over HTTPS - The owner account can sign in - A manual workflow executes successfully - The execution appears in the Executions view - Webhook URLs use `https://n8n.example.com/` - The security audit has been reviewed End-to-end verification is complete when PostgreSQL and n8n are healthy, the editor and webhook base URL use HTTPS, port `5678` remains loopback-only, backups exist, and a test workflow executes successfully. :::cta Deploy Your Server Deploy an Ubuntu 24.04 VM for a self-hosted n8n Docker Compose stack. ::: ## Cleanup and rollback For a temporary test, stop the stack without deleting persistent volumes: ```bash cd /opt/n8n docker compose stop ``` Disable public access through Nginx: ```bash sudo rm -f /etc/nginx/sites-enabled/n8n.example.com sudo nginx -t sudo systemctl reload nginx ``` Keep `/opt/n8n`, `n8n_data`, and `n8n_postgres_data` until you have confirmed that no workflow, credential, or database data is needed. To restart the deployment later: ```bash cd /opt/n8n docker compose up -d ``` Do not use `docker compose down -v` unless you intentionally want to delete the persistent n8n and PostgreSQL volumes after verifying backups. ## Troubleshooting ### n8n does not start Check service state and logs: ```bash cd /opt/n8n docker compose ps docker compose logs --tail=200 postgres docker compose logs --tail=200 n8n ``` Common causes include an invalid `.env` value, an unavailable image tag, PostgreSQL health failures, or a permissions problem in the n8n data volume. ### n8n starts but the public URL does not load Check Nginx, DNS, and the local n8n health endpoint: ```bash sudo nginx -t systemctl is-active nginx dig +short n8n.example.com A curl -i http://127.0.0.1:5678/healthz curl -I http://n8n.example.com ``` Fix DNS or Nginx before rerunning Certbot. ### Webhook URLs contain localhost or port 5678 Verify the public URL variables: ```bash cd /opt/n8n docker compose exec n8n env | grep -E '^(N8N_HOST|N8N_PROTOCOL|N8N_EDITOR_BASE_URL|WEBHOOK_URL|N8N_PROXY_HOPS)=' ``` They should reference the public HTTPS hostname, with `N8N_PROXY_HOPS=1` for the single Nginx proxy in this tutorial. ### PostgreSQL is unhealthy Inspect its logs and confirm the configured database variables are present: ```bash cd /opt/n8n docker compose logs --tail=200 postgres docker compose exec postgres env | grep '^POSTGRES_' ``` Do not print or paste the database password into public support channels. ### Restored credentials cannot be decrypted A restored database requires the same `N8N_ENCRYPTION_KEY` used when those credentials were created. Restore the protected key and recreate the n8n container with the correct `.env` file. ### Disk usage grows quickly Check execution retention, Docker storage, the database, and binary-data volume usage: ```bash cd /opt/n8n docker system df df -h / docker compose exec -T postgres \ psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ -c "SELECT pg_size_pretty(pg_database_size(current_database()));" ``` Reduce retention only when it matches your operational requirements, and move backups off the VM instead of keeping unlimited local copies. ## Conclusion and next steps This setup keeps n8n behind Nginx and HTTPS, uses PostgreSQL for persistent workflow state, binds the application port to localhost, protects the encryption key, prunes execution history, and includes a repeatable backup and update process. If you do not need to manage the stack manually, use the [Raff Marketplace n8n template](/marketplace/n8n). For the manual deployment, continue with [How to Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04) and Raff [Data Protection](/products/data-protection) for the surrounding operational controls. --- ### How to Set Up SSH MFA on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/set-up-ssh-mfa-ubuntu-24-04 Description: Set up SSH MFA on Ubuntu 24.04 on Raff with SSH keys, TOTP, PAM, OpenSSH, safe rollback, recovery codes, and end-to-end login verification without lockout. In this tutorial, you will set up SSH multi-factor authentication on Ubuntu 24.04 so an interactive administrator must present both a valid SSH key and a time-based one-time password (TOTP) code. The procedure uses Ubuntu's `libpam-google-authenticator` package, OpenSSH keyboard-interactive authentication, explicit rollback files, and a second-session test before the original SSH connection is closed. SSH MFA is an authentication design that requires more than one independent factor before a login succeeds. In this setup, the SSH private key is the first factor and a rotating TOTP code from an authenticator app is the second factor. Raff Technologies supports 3,000+ customers and 15,000+ VMs. A Raff Linux VM provides the Ubuntu environment, root-level SSH configuration, firewall controls, snapshots, backups, and web console access needed to operate administrative access safely. The original SSH MFA workflow was tested on a Raff Ubuntu 24.04 VM with 1 vCPU and 2 GB RAM. This revision corrects the PAM flow for **SSH key + TOTP** specifically and refreshes the configuration against Ubuntu 24.04's current OpenSSH 9.6p1 and `libpam-google-authenticator` documentation. Ubuntu 24.04 currently ships `libpam-google-authenticator` version `20191231-2build1`. Prerequisites: - A [Raff Ubuntu 24.04 VM](/products/linux-vm) - A non-root administrator account with sudo privileges - Working [SSH key authentication](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04) for every interactive administrator who will use this server - A TOTP-compatible authenticator app - Access to the Raff web console or another recovery path in case SSH configuration must be rolled back > **Scope:** This tutorial configures **SSH key + TOTP**. It deliberately disables SSH password authentication and removes the normal PAM password check from the SSH authentication stack. If automation or service accounts depend on unattended SSH, review those accounts before applying MFA globally. ## Step 1 — Verify SSH key access and create a safe rollback point Keep your current SSH session open for the entire change. Open a second terminal and confirm that your SSH key works before modifying PAM or OpenSSH: ```bash ssh your-user@your-server-ip ``` On the server, confirm the current user and active SSH service: ```bash whoami systemctl is-active ssh ``` Back up the two configuration files that will change: ```bash sudo cp --preserve=all /etc/pam.d/sshd /etc/pam.d/sshd.pre-mfa sudo cp --preserve=all /etc/ssh/sshd_config /etc/ssh/sshd_config.pre-mfa ``` Create a backup directory for any SSH drop-ins you add during this tutorial: ```bash sudo install -d -m 700 /root/ssh-mfa-backup sudo cp -a /etc/ssh/sshd_config.d /root/ssh-mfa-backup/sshd_config.d ``` Verify the backups exist: ```bash sudo ls -l /etc/pam.d/sshd.pre-mfa /etc/ssh/sshd_config.pre-mfa sudo test -d /root/ssh-mfa-backup/sshd_config.d && echo "SSH drop-in backup exists" ``` Verification is complete when SSH key login works in a second session and the PAM, main SSH configuration, and drop-in directory have backup copies. ## Step 2 — Install the Google Authenticator PAM module Update APT metadata and install the Ubuntu 24.04 package: ```bash sudo apt update sudo apt install -y libpam-google-authenticator ``` Check the installed package version: ```bash dpkg-query -W -f='${Package} ${Version}\n' libpam-google-authenticator ``` Ubuntu 24.04 currently provides `20191231-2build1`. The package includes the `google-authenticator` enrollment command and `pam_google_authenticator.so`, which validates TOTP codes during PAM authentication. Verify the PAM module exists: ```bash test -f /usr/lib/x86_64-linux-gnu/security/pam_google_authenticator.so \ || find /usr/lib -name pam_google_authenticator.so -print ``` For package details, see the [Ubuntu 24.04 package record](https://packages.ubuntu.com/noble/admin/libpam-google-authenticator). Verification is complete when the package is installed and `pam_google_authenticator.so` is present on the server. ## Step 3 — Enroll the SSH administrator in TOTP Run the enrollment command as the same non-root user who will log in over SSH: ```bash google-authenticator -t -d -r 3 -R 30 -w 3 -e 5 ``` The options configure: - TOTP rather than counter-based HOTP - Reuse protection for a code that has already authenticated - A maximum of 3 attempts every 30 seconds - The normal three-code time window: previous, current, and next 30-second step - Five emergency codes Scan the QR code with your authenticator app and verify the first code when prompted. Store the emergency codes somewhere protected and separate from the VM. The command writes the user's secret and settings to: ```text ~/.google_authenticator ``` Set the permissions explicitly to the mode expected by the Ubuntu PAM module: ```bash chmod 600 ~/.google_authenticator ``` Verify ownership and permissions without displaying the secret: ```bash stat -c '%U %G %a %n' ~/.google_authenticator ``` Expected state resembles: ```text your-user your-user 600 /home/your-user/.google_authenticator ``` Check server time synchronization because TOTP depends on reasonably accurate time: ```bash timedatectl show -p NTPSynchronized --value ``` Expected output: ```text yes ``` The Ubuntu PAM module requires a per-user secret file unless the weaker `nullok` option is used. This tutorial does **not** use `nullok`; enroll every interactive SSH administrator before enforcing MFA. See the [Ubuntu PAM module documentation](https://manpages.ubuntu.com/manpages/noble/man8/pam_google_authenticator.8.html) for the secret-file and permission rules. Verification is complete when the authenticator app generates matching TOTP codes, `~/.google_authenticator` is owned by the SSH user with mode `600`, and the server clock is synchronized. ## Step 4 — Enroll every other interactive SSH administrator before enforcement If this server has more than one human administrator, each account must run its own enrollment before you enable the global MFA requirement: ```bash google-authenticator -t -d -r 3 -R 30 -w 3 -e 5 chmod 600 ~/.google_authenticator ``` For each expected administrator, verify the secret file exists without reading it: ```bash sudo stat -c '%U %a %n' /home/USERNAME/.google_authenticator ``` Do not share one TOTP secret between multiple people. Each administrator should have an independent secret and recovery codes. If a non-human service account uses SSH keys for automation, do not continue with a global MFA policy until you have designed and tested an explicit exception or a different access path for that service account. Verification is complete when every human SSH administrator who must retain access has an individual `.google_authenticator` file and any unattended SSH accounts have been identified before enforcement. ## Step 5 — Configure PAM for SSH key plus TOTP Ubuntu's default `/etc/pam.d/sshd` includes the common password-authentication stack through: ```text @include common-auth ``` For **SSH key + TOTP**, leaving that line active can cause PAM keyboard-interactive authentication to request a Unix password in addition to the TOTP code. This tutorial removes that password check from the SSH auth stack and uses `pam_google_authenticator.so` as the keyboard-interactive factor. Edit the SSH PAM file: ```bash sudoedit /etc/pam.d/sshd ``` Near the top, comment the normal password-auth line and add the Google Authenticator module: ```text # Standard Un*x authentication. # @include common-auth auth required pam_google_authenticator.so ``` Leave the existing `account`, `session`, and password-update sections unchanged. Verify the relevant lines: ```bash sudo grep -nE 'common-auth|pam_google_authenticator' /etc/pam.d/sshd ``` Expected state: ```text # @include common-auth auth required pam_google_authenticator.so ``` Do not add `nullok`. That option permits accounts without a secret file to bypass the TOTP module during rollout, which conflicts with the mandatory-MFA outcome of this tutorial. Verification is complete when `common-auth` is commented only in `/etc/pam.d/sshd` and `pam_google_authenticator.so` is an active `required` auth module. ## Step 6 — Configure OpenSSH to require the key and PAM TOTP challenge Ubuntu 24.04's OpenSSH configuration includes `/etc/ssh/sshd_config.d/*.conf` before the main settings, and OpenSSH uses the first value it obtains for most keywords. Create an early drop-in so the MFA settings win over later defaults and cloud-init files: ```bash sudo tee /etc/ssh/sshd_config.d/00-raff-ssh-mfa.conf > /dev/null <<'EOF' PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication yes UsePAM yes AuthenticationMethods publickey,keyboard-interactive:pam PermitRootLogin no EOF ``` This requires both methods in sequence: ```text publickey → keyboard-interactive via PAM ``` `keyboard-interactive:pam` explicitly selects PAM as the second authentication device. `PasswordAuthentication no` prevents OpenSSH's separate password method from becoming an alternate login path. `ChallengeResponseAuthentication` is a deprecated alias for `KbdInteractiveAuthentication`; use the modern directive name on Ubuntu 24.04. The current Ubuntu `sshd_config` documentation also confirms that `AuthenticationMethods` can require multiple comma-separated methods in sequence. See the [Ubuntu 24.04 OpenSSH configuration manual](https://manpages.ubuntu.com/manpages/noble/man5/sshd_config.5.html). Validate syntax before touching the running daemon: ```bash sudo sshd -t ``` No output means the syntax is valid. Inspect the effective authentication settings: ```bash sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|usepam|authenticationmethods|permitrootlogin) ' ``` Expected values include: ```text pubkeyauthentication yes passwordauthentication no kbdinteractiveauthentication yes usepam yes authenticationmethods publickey,keyboard-interactive:pam permitrootlogin no ``` Verification is complete when `sshd -t` returns no error and `sshd -T` shows the intended key-plus-PAM authentication policy. ## Step 7 — Reload SSH without closing the recovery session Keep the original SSH session open. Reload OpenSSH rather than stopping it: ```bash sudo systemctl reload ssh ``` Verify the service remains active: ```bash systemctl is-active ssh ``` Expected output: ```text active ``` Re-run the configuration checks after reload: ```bash sudo sshd -t sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication|authenticationmethods) ' ``` If any check fails, restore the backups from Step 1 **from the still-open recovery session** before attempting another login. Verification is complete when SSH remains active after reload and the effective settings still require `publickey,keyboard-interactive:pam`. ## Step 8 — Test SSH key plus TOTP in a new session From a separate terminal, connect with verbose authentication output: ```bash ssh -v your-user@your-server-ip ``` The expected flow is: 1. The SSH public key is accepted. 2. OpenSSH reports partial authentication success or moves to keyboard-interactive. 3. PAM prompts for a verification code. 4. You enter the current TOTP code. 5. The shell opens without a Unix password prompt. After login, confirm the remote identity: ```bash whoami hostname ``` In the original recovery session, inspect recent SSH authentication events: ```bash sudo journalctl -u ssh --since '-10 minutes' --no-pager | tail -n 80 ``` On Ubuntu systems that log SSH authentication to `/var/log/auth.log`, you can also inspect: ```bash sudo tail -n 80 /var/log/auth.log ``` A successful test must require both the key and a valid TOTP code. A key-only login should fail, and a TOTP code without the matching private key must not be enough to authenticate. Verification is complete when a new SSH session succeeds only after the SSH key and TOTP challenge both pass, with no Unix password prompt. ## Step 9 — Verify recovery before closing the original session Test one emergency code from a controlled second session only if your recovery policy permits consuming one. Each emergency code is single-use. At minimum, verify that the protected recovery material exists and that you can reach an out-of-band recovery path such as the Raff web console before closing the original connection. Keep these rollback commands available in the original session: ```bash sudo cp --preserve=all /etc/pam.d/sshd.pre-mfa /etc/pam.d/sshd sudo cp --preserve=all /etc/ssh/sshd_config.pre-mfa /etc/ssh/sshd_config sudo rm -f /etc/ssh/sshd_config.d/00-raff-ssh-mfa.conf sudo rm -rf /etc/ssh/sshd_config.d sudo cp -a /root/ssh-mfa-backup/sshd_config.d /etc/ssh/sshd_config.d sudo sshd -t sudo systemctl reload ssh ``` Use this rollback only from an already authenticated console or SSH session. Do not close the working session until a separate MFA login has succeeded. Verification is complete when a separate MFA login works and you have confirmed a usable recovery path before ending the original session. ## Step 10 — Verify SSH MFA end to end Run the final server checks: ```bash sudo sshd -t sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|usepam|authenticationmethods|permitrootlogin) ' stat -c '%U %a %n' ~/.google_authenticator systemctl is-active ssh ``` From a new client session, verify the full login path again: ```bash ssh your-user@your-server-ip ``` End-to-end verification is complete when all of the following are true: - SSH key authentication succeeds as the first factor - A TOTP prompt is required as the second factor - No Unix password prompt appears - `PasswordAuthentication` is disabled - Root SSH login is disabled - `pam_google_authenticator.so` is required in `/etc/pam.d/sshd` - `~/.google_authenticator` is owned by the user with mode `600` - A second MFA-protected SSH session opens successfully - The original recovery session is not closed until the second session works :::cta Deploy Your Server Deploy an Ubuntu 24.04 VM and secure administrator SSH access with key plus TOTP authentication. ::: ## Troubleshooting ### SSH asks for a Unix password after the TOTP code Check `/etc/pam.d/sshd`: ```bash sudo grep -nE 'common-auth|pam_google_authenticator' /etc/pam.d/sshd ``` For this key-plus-TOTP design, `@include common-auth` should be commented and `auth required pam_google_authenticator.so` should be active. ### The SSH key works but no TOTP prompt appears Inspect the effective OpenSSH settings: ```bash sudo sshd -T | grep -E '^(kbdinteractiveauthentication|usepam|authenticationmethods) ' ``` Expected values are: ```text kbdinteractiveauthentication yes usepam yes authenticationmethods publickey,keyboard-interactive:pam ``` If a different drop-in wins, inspect the files in lexical order: ```bash sudo ls -1 /etc/ssh/sshd_config.d/ sudo grep -RniE 'KbdInteractiveAuthentication|AuthenticationMethods|PasswordAuthentication' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/ ``` ### TOTP codes are rejected Check time synchronization and secret-file permissions: ```bash timedatectl status stat -c '%U %G %a %n' ~/.google_authenticator ``` The server clock should be synchronized and the file should belong to the login user with mode `600`. ### SSH reports Permission denied after the PAM change Do not close the original session. Check syntax and logs: ```bash sudo sshd -t sudo journalctl -u ssh --since '-10 minutes' --no-pager | tail -n 100 sudo tail -n 100 /var/log/auth.log 2>/dev/null || true ``` If necessary, use the rollback block from Step 9 and reload SSH. ### An automation account can no longer connect The global `AuthenticationMethods publickey,keyboard-interactive:pam` policy requires TOTP for every SSH login. Restore the previous configuration first if production automation is affected, then design a narrow `Match`-based exception and test it independently before reenabling the global policy. ### A user lost the authenticator device Use a stored single-use emergency code or an out-of-band console to regain access. After recovery, run `google-authenticator` again for that user to rotate the TOTP secret and store the new emergency codes securely. ## Cleanup and rollback If you decide to remove SSH MFA, do it from an already authenticated SSH or console session and keep that session open while testing the rollback. Restore the PAM configuration: ```bash sudo cp --preserve=all /etc/pam.d/sshd.pre-mfa /etc/pam.d/sshd ``` Restore the original SSH drop-ins and main file: ```bash sudo cp --preserve=all /etc/ssh/sshd_config.pre-mfa /etc/ssh/sshd_config sudo rm -rf /etc/ssh/sshd_config.d sudo cp -a /root/ssh-mfa-backup/sshd_config.d /etc/ssh/sshd_config.d ``` Validate and reload: ```bash sudo sshd -t sudo systemctl reload ssh ``` Open a second terminal and verify the intended pre-MFA login path before deleting any `.google_authenticator` file or backup. Verification is complete when the restored SSH policy has been tested successfully from a new session. ## Conclusion and next steps You now have SSH key + TOTP authentication on Ubuntu 24.04: OpenSSH requires the public key first, PAM supplies the TOTP challenge second, password authentication is disabled, and the original session remains available until the new MFA path has been verified. For the surrounding access controls, continue with [Set Up SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04), [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Install fail2ban on Ubuntu 24.04](/learn/tutorials/install-fail2ban-ubuntu-24-04). Raff [Security](/products/security) provides the infrastructure-level controls that complement host-level SSH hardening. --- ### Install Prometheus and Grafana on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-prometheus-grafana-ubuntu-24-04 Description: Install Prometheus and Grafana on Ubuntu 24.04 on Raff with Node Exporter, localhost-only metrics, SSH-tunneled Grafana, and live dashboard verification. In this tutorial, you will install Prometheus, Node Exporter, and Grafana on Ubuntu 24.04, keep all three web interfaces bound to localhost, connect Grafana to Prometheus, and verify live CPU, memory, disk, and network metrics through an SSH tunnel. Prometheus is a time-series monitoring system that scrapes and stores metrics, Node Exporter exposes Linux host metrics, and Grafana turns those metrics into dashboards. Raff Technologies supports 3,000+ customers and 15,000+ VMs, and a Raff Linux VM provides the persistent Ubuntu environment, NVMe storage, firewall controls, and 3 Gbps unmetered VM traffic needed for a self-hosted monitoring stack. The original workflow was tested on a Raff Ubuntu 24.04 VM with 2 vCPU, 4 GB RAM, and 80 GB NVMe storage. This revision pins **Prometheus 3.5.5 LTS** and **Node Exporter 1.12.1**, the current LTS and exporter releases used for this guide as of August 14, 2026. Grafana is installed from its official stable APT repository so normal package updates can deliver supported stable releases. > **Security model:** Prometheus explicitly recommends against exposing its monitoring endpoints directly to the public internet. This tutorial therefore binds Prometheus to `127.0.0.1:9090`, Node Exporter to `127.0.0.1:9100`, and Grafana to `127.0.0.1:3000`. You reach Grafana through an SSH tunnel instead of opening monitoring ports publicly. Prerequisites: - A [Raff Ubuntu 24.04 VM](/products/linux-vm) with 2 vCPU and 4 GB RAM for this tutorial baseline - SSH access with a non-root sudo user - Working SSH key authentication recommended - Enough free disk space for Prometheus time-series data and Grafana configuration ## Step 1 — Prepare Ubuntu 24.04 Update packages and install the utilities used throughout the tutorial: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y curl wget tar gnupg ca-certificates ufw jq ``` Verify the operating system and available resources: ```bash lsb_release -ds nproc free -h df -h / ``` Expected baseline includes Ubuntu 24.04 LTS, at least 2 vCPU, and about 4 GB RAM for the reference setup. If `/var/run/reboot-required` exists after the upgrade, reboot during a safe window before continuing. Verification is complete when Ubuntu 24.04 is current and the VM has enough CPU, memory, and disk space for the monitoring workload. ## Step 2 — Create dedicated Prometheus and Node Exporter users Create non-login system accounts: ```bash sudo useradd --system --no-create-home --shell /usr/sbin/nologin prometheus 2>/dev/null || true sudo useradd --system --no-create-home --shell /usr/sbin/nologin node_exporter 2>/dev/null || true ``` Create Prometheus configuration and data directories: ```bash sudo install -d -o prometheus -g prometheus /etc/prometheus sudo install -d -o prometheus -g prometheus /var/lib/prometheus ``` Verify the accounts and directories: ```bash getent passwd prometheus getent passwd node_exporter ls -ld /etc/prometheus /var/lib/prometheus ``` Verification is complete when both service accounts exist and the Prometheus directories are owned by `prometheus`. ## Step 3 — Install Prometheus 3.5.5 LTS and verify its checksum Prometheus currently publishes `3.5.5` in its LTS line. Download the Linux AMD64 archive: ```bash cd /tmp PROMETHEUS_VERSION="3.5.5" curl -fLO "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz" ``` Verify the SHA-256 checksum published on the official Prometheus download page: ```bash echo "64d0beab873272b861a91df41668bc852c7e2e5b23f75c16059fb15b5630c577 prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz" | sha256sum -c - ``` Expected output: ```text prometheus-3.5.5.linux-amd64.tar.gz: OK ``` Extract and install the binaries plus console assets: ```bash tar -xzf "prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz" cd "prometheus-${PROMETHEUS_VERSION}.linux-amd64" sudo install -m 0755 prometheus promtool /usr/local/bin/ sudo cp -a consoles console_libraries /etc/prometheus/ sudo chown -R prometheus:prometheus /etc/prometheus/consoles /etc/prometheus/console_libraries ``` Verify the installed version: ```bash prometheus --version | head -n 1 promtool --version | head -n 1 ``` The version output should report `3.5.5`. Verification is complete when the checksum passes and both Prometheus binaries report version `3.5.5`. ## Step 4 — Configure Prometheus to scrape itself and Node Exporter Create `/etc/prometheus/prometheus.yml`: ```bash sudo tee /etc/prometheus/prometheus.yml > /dev/null <<'EOF' global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: "prometheus" static_configs: - targets: ["127.0.0.1:9090"] - job_name: "node_exporter" static_configs: - targets: ["127.0.0.1:9100"] EOF ``` Set ownership and validate the YAML: ```bash sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml promtool check config /etc/prometheus/prometheus.yml ``` Expected output includes a successful configuration check. Prometheus' current documentation uses the same scrape model: a YAML file defines jobs and targets, while `scrape_interval` controls collection frequency. Verification is complete when `promtool check config` succeeds and both localhost targets appear in the configuration. ## Step 5 — Run Prometheus under systemd on localhost only Create the systemd unit: ```bash sudo tee /etc/systemd/system/prometheus.service > /dev/null <<'EOF' [Unit] Description=Prometheus Monitoring Wants=network-online.target After=network-online.target [Service] User=prometheus Group=prometheus Type=simple ExecStart=/usr/local/bin/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus \ --web.listen-address=127.0.0.1:9090 \ --web.console.templates=/etc/prometheus/consoles \ --web.console.libraries=/etc/prometheus/console_libraries Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF ``` Start and enable Prometheus: ```bash sudo systemctl daemon-reload sudo systemctl enable --now prometheus ``` Verify the service, readiness endpoint, and listening address: ```bash systemctl is-active prometheus curl -fsS http://127.0.0.1:9090/-/ready ss -lntp | grep ':9090' ``` Expected state includes `active`, a successful readiness response, and `127.0.0.1:9090` rather than `0.0.0.0:9090`. Prometheus defaults to listening on all interfaces unless `--web.listen-address` is set, so the explicit loopback bind is intentional. Verification is complete when Prometheus is active, ready, and accessible only on localhost port `9090`. ## Step 6 — Install Node Exporter 1.12.1 and verify its checksum Download the current Node Exporter release: ```bash cd /tmp NODE_EXPORTER_VERSION="1.12.1" curl -fLO "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" ``` Verify the official SHA-256 checksum: ```bash echo "b51d8a76aa2a9156a55d501aca6276fae09e262259a5e4e831d2c2222f084e63 node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" | sha256sum -c - ``` Expected output: ```text node_exporter-1.12.1.linux-amd64.tar.gz: OK ``` Extract and install the binary: ```bash tar -xzf "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" sudo install -m 0755 "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter" /usr/local/bin/node_exporter ``` Verify the version: ```bash node_exporter --version | head -n 1 ``` The output should report `1.12.1`. Verification is complete when the checksum passes and Node Exporter reports version `1.12.1`. ## Step 7 — Run Node Exporter under systemd on localhost only Create the Node Exporter unit: ```bash sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<'EOF' [Unit] Description=Prometheus Node Exporter Wants=network-online.target After=network-online.target [Service] User=node_exporter Group=node_exporter Type=simple ExecStart=/usr/local/bin/node_exporter --web.listen-address=127.0.0.1:9100 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF ``` Start and enable the service: ```bash sudo systemctl daemon-reload sudo systemctl enable --now node_exporter ``` Verify metrics and the bind address: ```bash systemctl is-active node_exporter curl -fsS http://127.0.0.1:9100/metrics | head ss -lntp | grep ':9100' ``` Expected state includes `active`, Prometheus-format metric lines, and `127.0.0.1:9100`. Verification is complete when Node Exporter is active and its metrics endpoint is available only on localhost. ## Step 8 — Verify Prometheus is scraping both targets Wait at least one scrape interval, then query the target API: ```bash sleep 20 curl -fsS http://127.0.0.1:9090/api/v1/targets | \ jq -r '.data.activeTargets[] | [.labels.job, .health] | @tsv' ``` Expected result: ```text prometheus up node_exporter up ``` Verify actual host metrics are stored: ```bash curl -fsSG http://127.0.0.1:9090/api/v1/query \ --data-urlencode 'query=node_uname_info' | jq -r '.status' ``` Expected output: ```text success ``` Verification is complete when both scrape targets are `up` and Prometheus can query Node Exporter metrics. ## Step 9 — Install Grafana from the official stable APT repository Grafana's current Ubuntu documentation recommends its signed APT repository for installations that should receive package updates. Add the repository key and stable source: ```bash sudo mkdir -p /etc/apt/keyrings sudo wget -q -O /etc/apt/keyrings/grafana.asc https://apt.grafana.com/gpg-full.key sudo chmod 644 /etc/apt/keyrings/grafana.asc echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" | \ sudo tee /etc/apt/sources.list.d/grafana.list ``` Install Grafana OSS: ```bash sudo apt update sudo apt install -y grafana ``` Bind Grafana to loopback instead of all network interfaces: ```bash sudo sed -i 's/^;\?http_addr =.*/http_addr = 127.0.0.1/' /etc/grafana/grafana.ini ``` Start and enable Grafana: ```bash sudo systemctl enable --now grafana-server ``` Verify the service and bind address: ```bash systemctl is-active grafana-server curl -I http://127.0.0.1:3000/login ss -lntp | grep ':3000' ``` Expected state includes an HTTP response and `127.0.0.1:3000`. Grafana documents `http_addr` as the setting that controls which network interface the server binds to; an empty value binds to all interfaces. Verification is complete when Grafana is active and listening only on localhost port `3000`. ## Step 10 — Keep monitoring ports closed and open an SSH tunnel to Grafana Allow SSH before enabling UFW: ```bash sudo ufw allow OpenSSH sudo ufw --force enable sudo ufw status numbered ``` Do **not** add public allow rules for ports `3000`, `9090`, or `9100`. From your local computer, create an SSH tunnel to Grafana: ```bash ssh -L 3000:127.0.0.1:3000 your-user@your-server-ip ``` Keep that SSH session open and browse to: ```text http://127.0.0.1:3000 ``` Grafana's default first-login credentials are: ```text Username: admin Password: admin ``` Change the administrator password when Grafana prompts you. ![Grafana login page on Ubuntu 24.04 after installation](/uploads/prometheus-grafana-ubuntu-24-04-01-grafana-login.webp) Verify from the VM that the monitoring ports are loopback-only: ```bash ss -lntp | grep -E ':3000|:9090|:9100' ``` All three listeners should show `127.0.0.1`. Verification is complete when Grafana opens through the SSH tunnel and none of the monitoring ports is publicly bound. ## Step 11 — Connect Grafana to Prometheus In Grafana, open: ```text Connections → Data sources → Add data source → Prometheus ``` Set the Prometheus server URL to: ```text http://127.0.0.1:9090 ``` Click **Save & test**. Expected visible result indicates Grafana successfully queried the Prometheus API. ![Grafana Prometheus data source showing a successful connection](/uploads/prometheus-grafana-ubuntu-24-04-02-prometheus-data-source.webp) Verify Prometheus directly from the VM: ```bash curl -fsSG http://127.0.0.1:9090/api/v1/query \ --data-urlencode 'query=up' | jq -r '.status' ``` Expected output: ```text success ``` Verification is complete when Grafana accepts the Prometheus data source and the local Prometheus API query succeeds. ## Step 12 — Import a Node Exporter dashboard In Grafana, open: ```text Dashboards → New → Import ``` For the existing Raff-tested path, use Grafana.com dashboard ID: ```text 1860 ``` Select the Prometheus data source and import the dashboard. ![Grafana dashboard import screen for Node Exporter Full](/uploads/prometheus-grafana-ubuntu-24-04-03-node-exporter-dashboard-import.webp) If a third-party dashboard changes or becomes unavailable, you can still verify the stack by creating a simple panel using a PromQL query such as: ```promql rate(node_cpu_seconds_total{mode!="idle"}[5m]) ``` Verification is complete when Grafana imports the dashboard or a manually created panel returns Node Exporter data from Prometheus. ## Step 13 — Verify Prometheus and Grafana monitoring end to end Open the Node Exporter dashboard through the SSH tunnel, set the time range to **Last 15 minutes**, and refresh it. ![Grafana Node Exporter dashboard showing live server metrics](/uploads/prometheus-grafana-ubuntu-24-04-04-node-exporter-dashboard.webp) Run the final server checks: ```bash systemctl is-active prometheus systemctl is-active node_exporter systemctl is-active grafana-server curl -fsS http://127.0.0.1:9090/-/ready curl -fsS http://127.0.0.1:9100/metrics >/dev/null curl -fsS http://127.0.0.1:3000/api/health | jq curl -fsS http://127.0.0.1:9090/api/v1/targets | \ jq -r '.data.activeTargets[] | [.labels.job, .health] | @tsv' ss -lntp | grep -E ':3000|:9090|:9100' ``` End-to-end verification is complete when: - Prometheus, Node Exporter, and Grafana are active - Prometheus and Node Exporter targets both report `up` - Grafana's health endpoint responds - The dashboard displays live host metrics - Ports `3000`, `9090`, and `9100` are bound only to `127.0.0.1` - Grafana is reachable from your workstation through the SSH tunnel :::cta Deploy Your Server Deploy an Ubuntu 24.04 VM for a self-hosted Prometheus and Grafana monitoring stack. ::: ## Backup and update planning Prometheus time-series data lives under: ```text /var/lib/prometheus ``` Grafana configuration and local state commonly live under: ```text /etc/grafana /var/lib/grafana ``` For a small single-node monitoring deployment, back up Grafana's configuration/database and preserve the Prometheus configuration. Whether you also back up the full Prometheus TSDB depends on your recovery requirements and retention strategy. Before updating Prometheus or Node Exporter, review their release notes, update the pinned version and checksum together, then rerun all service and target checks. Grafana installed from the stable APT repository can be updated through normal Ubuntu package maintenance. Raff [Data Protection](/products/data-protection) can add infrastructure-level recovery, but it does not replace an application-aware decision about which Grafana and Prometheus data must be recoverable. ## Troubleshooting ### Prometheus does not start Validate the configuration and inspect the service log: ```bash promtool check config /etc/prometheus/prometheus.yml sudo journalctl -u prometheus -n 100 --no-pager ``` Confirm the data and configuration paths are accessible to the `prometheus` user: ```bash sudo -u prometheus test -r /etc/prometheus/prometheus.yml && echo readable sudo -u prometheus test -w /var/lib/prometheus && echo writable ``` ### Node Exporter is down in Prometheus Check the service and local metrics endpoint: ```bash systemctl status node_exporter --no-pager curl -fsS http://127.0.0.1:9100/metrics | head ``` Then inspect Prometheus targets: ```bash curl -fsS http://127.0.0.1:9090/api/v1/targets | \ jq -r '.data.activeTargets[] | [.labels.job, .health, .lastError] | @tsv' ``` ### Grafana does not open through the SSH tunnel Confirm Grafana is running locally: ```bash systemctl is-active grafana-server curl -I http://127.0.0.1:3000/login ss -lntp | grep ':3000' ``` On your workstation, recreate the tunnel: ```bash ssh -L 3000:127.0.0.1:3000 your-user@your-server-ip ``` Then browse to `http://127.0.0.1:3000`. ### Grafana cannot query Prometheus Check Prometheus readiness and the query API from the server: ```bash curl -fsS http://127.0.0.1:9090/-/ready curl -fsSG http://127.0.0.1:9090/api/v1/query \ --data-urlencode 'query=up' | jq ``` The Grafana data source URL should be `http://127.0.0.1:9090` because Grafana and Prometheus run on the same VM. ### Dashboard panels show no data Verify that Node Exporter metrics exist: ```bash curl -fsSG http://127.0.0.1:9090/api/v1/query \ --data-urlencode 'query=node_uname_info' | jq -r '.data.result | length' ``` A result greater than `0` confirms Prometheus has Node Exporter samples. Increase the Grafana time range and confirm the panel uses the correct Prometheus data source. ### Disk usage grows faster than expected Check Prometheus data size and free disk space: ```bash sudo du -sh /var/lib/prometheus df -h / ``` Metric cardinality, scrape frequency, retention, and number of targets all affect Prometheus storage growth. Do not reduce retention blindly; choose a retention policy that matches the monitoring and incident-history requirements of the workload. ## Cleanup and rollback For a reversible shutdown, stop the monitoring services first without deleting their data: ```bash sudo systemctl stop grafana-server prometheus node_exporter ``` To restart them later: ```bash sudo systemctl start node_exporter prometheus grafana-server ``` If you permanently decommission the stack, back up any Grafana dashboards/configuration and Prometheus data you need before removing packages, binaries, unit files, `/etc/prometheus`, `/var/lib/prometheus`, `/etc/grafana`, or `/var/lib/grafana`. Remove only monitoring-specific files after verifying the backups. Do not delete unrelated firewall or SSH configuration while cleaning up the monitoring stack. Verification is complete when the services are stopped for a reversible rollback or, for permanent decommissioning, the required backups are verified before monitoring data is removed. ## Conclusion and next steps You now have Prometheus, Node Exporter, and Grafana running on Ubuntu 24.04 with all monitoring interfaces kept on localhost. Prometheus scrapes both itself and Node Exporter, Grafana queries Prometheus locally, and administrators reach the dashboard through an SSH tunnel instead of exposing monitoring endpoints publicly. Continue with [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server), [Install fail2ban on Ubuntu 24.04](/learn/tutorials/install-fail2ban-ubuntu-24-04), and [Deploy Uptime Kuma with Docker on Ubuntu 24.04](/learn/tutorials/deploy-uptime-kuma-docker-ubuntu-24-04) for the surrounding operational baseline. --- ### Generate SSH Keys on Ubuntu 24.04: Ed25519 Setup Guide URL: https://rafftechnologies.com/learn/tutorials/set-up-ssh-keys-ubuntu-24-04 Description: Generate an SSH key on Ubuntu 24.04 with Ed25519, ssh-keygen, ssh-copy-id, ssh-agent, safe password disabling, troubleshooting, and key rotation. SSH key authentication uses a public and private key pair instead of relying on a reusable server password. The private key stays on your local computer, while the public key is added to the Ubuntu account you want to access. In this tutorial, you will generate an Ed25519 SSH key, copy it to Ubuntu 24.04, verify the correct identity is used, configure `ssh-agent`, disable password authentication through an OpenSSH drop-in, and safely rotate or revoke keys later. ## Step 1 — Check for Existing SSH Keys Run this on your local computer: ```bash ls -la ~/.ssh ``` Common key files include: ```text id_ed25519 id_ed25519.pub id_rsa id_rsa.pub ``` Do not overwrite an existing private key unless you intentionally want to replace it. You can create a separate key for Raff servers, a specific environment, or a specific team member. ## Step 2 — Generate an Ed25519 Key Pair Generate a new key on your local computer: ```bash ssh-keygen -t ed25519 -a 100 -C "raff-ubuntu-access" ``` When prompted for a file name, press Enter for the default path or choose a descriptive name such as: ```text ~/.ssh/raff_ed25519 ``` Set a passphrase for interactive administrator keys. The passphrase protects the private key if the local device or key file is copied. The two generated files have different roles: - `id_ed25519` or your custom filename is the private key. Do not upload or share it. - The matching `.pub` file is the public key. This is the file copied to servers. Ed25519 is the preferred default for modern OpenSSH systems. Use RSA only when a legacy system or policy specifically requires it. ## Step 3 — Inspect the Public Key and Fingerprint Display the public key: ```bash cat ~/.ssh/id_ed25519.pub ``` For a custom filename: ```bash cat ~/.ssh/raff_ed25519.pub ``` Display its fingerprint: ```bash ssh-keygen -lf ~/.ssh/id_ed25519.pub ``` Fingerprints help identify keys during audits and rotation without comparing the entire public-key string. ## Step 4 — Copy the Public Key to Ubuntu The simplest method is `ssh-copy-id`: ```bash ssh-copy-id your_user@your_server_ip ``` For a custom public key: ```bash ssh-copy-id -i ~/.ssh/raff_ed25519.pub your_user@your_server_ip ``` The command authenticates using the server's current access method and appends the public key to the user's `~/.ssh/authorized_keys` file. When `ssh-copy-id` is unavailable, use this fallback from your local computer: ```bash cat ~/.ssh/id_ed25519.pub | \ ssh your_user@your_server_ip \ 'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys' ``` On the server, verify ownership and permissions: ```bash chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R "$USER":"$USER" ~/.ssh ``` ## Step 5 — Verify Key Authentication in a New Session Keep the original SSH session open and test a separate connection: ```bash ssh your_user@your_server_ip ``` When using a custom key, specify it explicitly: ```bash ssh -i ~/.ssh/raff_ed25519 your_user@your_server_ip ``` Use verbose output when troubleshooting: ```bash ssh -vv -i ~/.ssh/raff_ed25519 your_user@your_server_ip ``` Look for output showing that the client offered the intended public key and that authentication succeeded. Exact wording varies by OpenSSH version. Confirm the server stored the expected public key: ```bash nl -ba ~/.ssh/authorized_keys ``` Do not disable passwords until a new key-based session succeeds. :::cta Deploy Your Server Create an Ubuntu 24.04 Linux VM and provision it with SSH key access from the first login. ::: ## Step 6 — Load the Key into ssh-agent Start an agent in the current local shell when one is not already available: ```bash eval "$(ssh-agent -s)" ``` Add the key: ```bash ssh-add ~/.ssh/id_ed25519 ``` Or add the custom key: ```bash ssh-add ~/.ssh/raff_ed25519 ``` List loaded identities: ```bash ssh-add -l ``` The agent keeps the decrypted key available for the session so you do not have to re-enter its passphrase for every connection. Desktop operating systems may provide their own agent or secure key integration. ## Step 7 — Disable Password Authentication Safely On the Ubuntu server, create a dedicated OpenSSH drop-in: ```bash sudo nano /etc/ssh/sshd_config.d/99-raff-key-auth.conf ``` Add: ```text PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no ``` Validate the complete configuration: ```bash sudo sshd -t ``` Check the effective values rather than assuming one file wins: ```bash sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication) ' ``` The expected values are: ```text pubkeyauthentication yes passwordauthentication no kbdinteractiveauthentication no ``` Reload the service: ```bash sudo systemctl reload ssh ``` Keep the existing session open and test a new key-based connection. Then explicitly test that password-only authentication is rejected: ```bash ssh -o PreferredAuthentications=password \ -o PubkeyAuthentication=no \ your_user@your_server_ip ``` The connection should be denied rather than presenting a usable password login. ## Step 8 — Disable Root SSH Login After Sudo Access Works First confirm the regular account can run sudo: ```bash sudo whoami ``` The result should be `root`. Add the following to the same drop-in file: ```text PermitRootLogin no ``` Validate and reload again: ```bash sudo sshd -t sudo systemctl reload ssh ``` Test the normal administrative account in another terminal before closing the current session. Root-login restrictions and password restrictions should be applied only after the replacement access path is proven. ## Step 9 — Create a Local SSH Config Entry Create or edit the config file on your local computer: ```bash nano ~/.ssh/config ``` Add: ```text Host raff-production HostName your_server_ip User your_user IdentityFile ~/.ssh/raff_ed25519 IdentitiesOnly yes ServerAliveInterval 60 ``` Protect the file: ```bash chmod 600 ~/.ssh/config ``` Connect using the alias: ```bash ssh raff-production ``` `IdentitiesOnly yes` is useful when your agent contains several keys because it tells the client to use the configured identity rather than offering many unrelated keys. ## Step 10 — Add a Second Administrator Without Sharing Keys Each person should generate and control their own private key. Add only their public key to the appropriate server account. For a separate Linux account: ```bash sudo adduser secondadmin sudo usermod -aG sudo secondadmin sudo install -d -m 700 -o secondadmin -g secondadmin /home/secondadmin/.ssh ``` Add the person's public key to: ```text /home/secondadmin/.ssh/authorized_keys ``` Then set ownership and permissions: ```bash sudo chown secondadmin:secondadmin /home/secondadmin/.ssh/authorized_keys sudo chmod 600 /home/secondadmin/.ssh/authorized_keys ``` Separate accounts and keys make access review, revocation, and log attribution clearer. ## Step 11 — Rotate or Revoke an SSH Key List authorized keys with line numbers: ```bash nl -ba ~/.ssh/authorized_keys ``` Before removing an old key, add and test the replacement key in a separate session. Then edit the file: ```bash nano ~/.ssh/authorized_keys ``` Delete only the line belonging to the key being revoked. You can identify a public key's fingerprint by saving the line to a temporary file or by checking the original `.pub` file: ```bash ssh-keygen -lf ~/.ssh/raff_ed25519.pub ``` If a private key is lost or suspected to be copied, remove its public key from every server that trusts it. Changing the key's local passphrase does not revoke a copy that may already exist elsewhere. ## Step 12 — Troubleshoot Common SSH Key Problems ### The server still asks for a password Check the local key being offered: ```bash ssh -vv -i ~/.ssh/raff_ed25519 your_user@your_server_ip ``` Check server-side permissions: ```bash namei -l ~/.ssh/authorized_keys ``` The home directory must not be writable by unrelated users, `.ssh` should normally be `700`, and `authorized_keys` should normally be `600`. ### Too many authentication failures Specify the key and prevent the client from offering unrelated agent identities: ```bash ssh -o IdentitiesOnly=yes \ -i ~/.ssh/raff_ed25519 \ your_user@your_server_ip ``` ### OpenSSH ignores a configuration change Validate syntax and inspect effective settings: ```bash sudo sshd -t sudo sshd -T | grep -E '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication) ' ``` Review all drop-ins: ```bash sudo grep -RniE '^(PermitRootLogin|PubkeyAuthentication|PasswordAuthentication|KbdInteractiveAuthentication)' \ /etc/ssh/sshd_config /etc/ssh/sshd_config.d ``` ### You lose normal SSH access Use the Raff browser console to inspect SSH configuration, restore an authorized public key, or correct firewall rules. Keep a tested recovery method available before making remote-access changes. ## Conclusion You now have an Ed25519 SSH key, verified public-key authentication, optional agent and client configuration, disabled password access, and a safe process for adding, rotating, and revoking administrator keys. Continue with [How to Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) and [How to Harden an Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server) to complete the initial security baseline. Raff Linux VMs start at $8.49 per month with 2 vCPU, 2 GB RAM, 40 GB NVMe storage, and 3 Gbps unmetered bandwidth. --- ### How to Install Docker on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-docker-ubuntu-24-04 Description: Install Docker Engine on Ubuntu 24.04 from Docker’s official APT repository, add Compose and Buildx, verify hello-world, and avoid common UFW and package conflicts. In this tutorial, you’ll install **Docker Engine on Ubuntu 24.04** from Docker’s official APT repository, install the Docker Compose and Buildx plugins, verify the service with `hello-world`, and run a practical Nginx container test. **Ubuntu 24.04 Docker install — quick answer:** Docker officially supports Ubuntu Noble 24.04 LTS. For an Ubuntu server, the recommended path is Docker Engine from Docker’s official APT repository rather than Docker Desktop or an older distribution package. **Quick install:** if you just need the commands, this is the complete sequence. Every step is explained below. ```bash sudo apt update sudo apt install -y ca-certificates curl for pkg in docker.io docker-doc docker-compose docker-compose-v2 docker-buildx podman-docker containerd runc; do sudo apt remove -y "$pkg" 2>/dev/null || true done sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null </dev/null || true done ``` Docker’s current conflict list includes `docker.io`, `docker-compose`, `docker-compose-v2`, `docker-doc`, `docker-buildx`, `podman-docker`, `containerd`, and `runc` when those packages are already installed. Removing the packages does not automatically delete existing Docker data stored in `/var/lib/docker`. If this is not a fresh VM, review your containers, images, volumes, and backup plan before continuing. Verify whether the Docker CLI is already present: ```bash docker --version ``` Expected output on a fresh VM: ```text Command 'docker' not found ``` ## Step 3 — Add Docker’s official APT repository Docker supports Ubuntu 24.04 LTS and documents installing Docker Engine through its official APT repository. The commands below follow [Docker’s current Ubuntu installation method](https://docs.docker.com/engine/install/ubuntu/). Create the APT keyring directory: ```bash sudo install -m 0755 -d /etc/apt/keyrings ``` Download Docker’s official GPG key: ```bash sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc ``` Make the key readable by APT: ```bash sudo chmod a+r /etc/apt/keyrings/docker.asc ``` Add Docker’s repository: ```bash sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null </dev/null || true sudo docker run -d --name test-nginx -p 127.0.0.1:8080:80 nginx:alpine ``` Binding to `127.0.0.1` prevents the test container from being exposed directly to the public internet. Verify that the container is running: ```bash sudo docker ps --filter name=test-nginx ``` Expected output includes: ```text test-nginx Up 127.0.0.1:8080->80/tcp ``` Test the container from the VM: ```bash curl -I http://127.0.0.1:8080 ``` Expected output includes: ```text HTTP/1.1 200 OK Server: nginx ``` To view the page in your local browser, open a second terminal on your computer and create an SSH tunnel: ```bash ssh -L 8080:127.0.0.1:8080 your_user@your_server_ip ``` Keep that SSH session open, then visit: ```text http://localhost:8080 ``` Visible state check: ```text The browser shows the default Nginx welcome page. The page is served by the Docker container through the SSH tunnel. The URL is http://localhost:8080. ``` ![Nginx container running with Docker on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/docker_nginx_container_ubuntu_24_04_webp_1a7b04939a.png) The test is successful when the browser shows the Nginx welcome page and the local `curl` command returns `HTTP/1.1 200 OK`. > ⚠️ **Docker firewall warning:** Docker’s current Ubuntu documentation warns that ports published by Docker can bypass firewall rules managed by UFW or firewalld. Bind private services to `127.0.0.1`, use an upstream cloud firewall where appropriate, and review Docker’s packet-filtering guidance before publishing production ports. ## Step 8 — Configure non-root Docker access Docker commands require `sudo` by default. On a personal VM, you can add your user to the `docker` group: ```bash sudo usermod -aG docker "$USER" ``` Apply the new group in the current shell: ```bash newgrp docker ``` Verify Docker without `sudo`: ```bash docker ps ``` Expected output includes the running `test-nginx` container. > ⚠️ **Warning:** Membership in the `docker` group grants root-level privileges on the host. Add only trusted users. On shared servers, continue using `sudo docker` or evaluate Docker’s rootless mode. Docker documents this permission model in its [Linux post-installation guidance](https://docs.docker.com/engine/install/linux-postinstall/). ## Step 9 — Verify the complete Docker installation Run the final verification sequence: ```bash echo "Docker Engine:" docker --version || sudo docker --version echo "Docker Compose:" docker compose version || sudo docker compose version echo "Docker service:" systemctl is-active docker echo "Running containers:" sudo docker ps --filter name=test-nginx echo "Nginx response:" curl -I http://127.0.0.1:8080 ``` Expected output includes: ```text Docker version Docker Compose version active test-nginx HTTP/1.1 200 OK ``` The installation is complete when Docker Engine and Docker Compose are available, the service is active, `hello-world` runs successfully, and the Nginx container returns an HTTP response. :::cta Deploy Your Server Launch an Ubuntu 24.04 Linux VM and use this verified Docker installation workflow. ::: ## Basic Docker commands to get started Docker is installed. These are the commands you will use most while working with containers: ```bash docker ps # list running containers docker ps -a # list all containers, including stopped ones docker images # list downloaded images docker pull nginx:alpine # download an image without running it docker run -d --name web -p 127.0.0.1:8080:80 nginx:alpine # run a container in the background docker logs web # view a container's output docker exec -it web sh # open a shell inside a running container docker stop web # stop a container docker start web # start a stopped container docker rm web # remove a stopped container docker image rm nginx:alpine # remove an image docker system df # show disk usage for images, containers, and volumes docker system prune # remove unused data (asks for confirmation) ``` For multi-container applications defined in a Compose file: ```bash docker compose up -d # start all services in the background docker compose ps # list running services docker compose logs -f # follow service logs docker compose down # stop and remove services ``` To put these into practice, follow [deploy a multi-container app with Docker Compose](/learn/tutorials/deploy-multi-container-docker-compose-ubuntu-24-04). ## Cleanup (Optional) Remove the temporary Nginx container: ```bash sudo docker rm -f test-nginx ``` Verify that it is gone: ```bash sudo docker ps --filter name=test-nginx ``` The output should contain only the table headings. Remove the downloaded test images if you no longer need them: ```bash sudo docker image rm hello-world nginx:alpine ``` Do not uninstall Docker if you plan to deploy containerized applications on this VM. ## Troubleshooting ### `docker: command not found` **Cause:** Docker Engine is not installed, or the installation did not complete. **Fix:** ```bash apt-cache policy docker-ce sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker --version ``` ### `Cannot connect to the Docker daemon` **Cause:** The Docker service is stopped, or your user cannot access the Docker socket. **Fix:** ```bash systemctl is-active docker sudo systemctl start docker sudo docker ps ``` After configuring non-root access, log out and back in or run: ```bash newgrp docker docker ps ``` ### The Nginx test does not respond **Cause:** The container failed, port `8080` is already in use, or the local test is using the wrong address. **Fix:** ```bash sudo docker ps -a --filter name=test-nginx sudo docker logs test-nginx sudo ss -tulpn | grep ':8080' curl -I http://127.0.0.1:8080 ``` If another process owns port `8080`, remove the test container and use another loopback port: ```bash sudo docker rm -f test-nginx sudo docker run -d --name test-nginx -p 127.0.0.1:8081:80 nginx:alpine curl -I http://127.0.0.1:8081 ``` ### The browser cannot open the Nginx page **Cause:** The SSH tunnel is not running, the tunnel uses the wrong username or server IP, or local port `8080` is occupied. **Fix:** ```bash ssh -L 8080:127.0.0.1:8080 your_user@your_server_ip ``` Keep the SSH session open and visit `http://localhost:8080`. Use a different local port when necessary: ```bash ssh -L 8081:127.0.0.1:8080 your_user@your_server_ip ``` Then visit `http://localhost:8081`. ### Docker Compose is not available **Cause:** The Docker Compose plugin was not installed. **Fix:** ```bash sudo apt update sudo apt install -y docker-compose-plugin docker compose version ``` ### A published Docker port is reachable despite UFW **Cause:** Docker creates its own firewall rules, and Docker’s documentation warns that published container ports can bypass UFW rules. **Fix:** Bind services that should remain private to `127.0.0.1`. For public services, use an upstream cloud firewall where appropriate and review Docker’s packet-filtering and firewall documentation before adding host-level filtering rules. ## How to uninstall Docker from Ubuntu To update Docker, you do not need to remove anything: run `sudo apt update && sudo apt upgrade`, and the official repository configured in Step 3 delivers newer stable package versions. To remove Docker completely, uninstall the packages: ```bash sudo apt purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras sudo apt autoremove -y ``` > ⚠️ **Warning:** The next command permanently deletes all images, containers, and volumes on this host. Back up any data you need first. ```bash sudo rm -rf /var/lib/docker /var/lib/containerd ``` Optionally remove the repository configuration and key: ```bash sudo rm /etc/apt/sources.list.d/docker.sources /etc/apt/keyrings/docker.asc sudo apt update ``` ## Conclusion You installed Docker Engine on Ubuntu 24.04 from Docker’s official APT repository, installed Docker Compose and Buildx, verified the daemon with `hello-world`, and tested an Nginx container without exposing the test port publicly. Next, use [Docker Compose to deploy a multi-container application](/learn/tutorials/deploy-multi-container-docker-compose-ubuntu-24-04), deploy [Uptime Kuma with Docker](/learn/tutorials/deploy-uptime-kuma-docker-ubuntu-24-04), or review [Kubernetes vs Docker Compose for small teams](/learn/guides/kubernetes-vs-docker-compose-small-teams) before choosing a cluster operating model. For infrastructure planning, read [VPS for Docker Containers](/learn/guides/vps-for-docker-containers), [Docker Volumes vs Bind Mounts](/learn/guides/docker-volumes-vs-bind-mounts-production), and compare the available [Raff Linux VM plans](/products/linux-vm). ## Sources - [Docker Docs — Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/) - [Docker Docs — Linux post-installation steps](https://docs.docker.com/engine/install/linux-postinstall/) - [Docker Docs — Docker Engine 29 release notes](https://docs.docker.com/engine/release-notes/29/) - [Docker Compose — Releases](https://github.com/docker/compose/releases) - Sources re-verified: 2026-08-28 --- ### How to Install WordPress on Ubuntu 24.04 with Nginx URL: https://rafftechnologies.com/learn/tutorials/install-wordpress-ubuntu-24-04-nginx Description: Install WordPress on Ubuntu 24.04 with Nginx, PHP 8.3, MariaDB, secure permissions, and Let's Encrypt HTTPS on a Raff Linux VM step by step. WordPress runs well on Ubuntu 24.04 with Nginx, PHP-FPM, and MariaDB when you want full control over the web server, PHP runtime, database, files, TLS, and backups. In this tutorial, you will install WordPress on a Raff Linux VM, configure the Nginx WordPress server block, keep MariaDB local to the server, protect `wp-config.php`, enable HTTPS with Let's Encrypt, and verify the finished site end to end. Ubuntu 24.04's PHP 8.3 baseline matches WordPress's current recommended PHP requirement, and the MariaDB version available on Ubuntu 24.04 meets WordPress's modern database baseline. This guide uses a single-server WordPress VPS design: Nginx, PHP-FPM, MariaDB, and WordPress all run on the same VM. For a small site, start with at least 2 GB RAM; use more memory when plugins, backups, imports, WooCommerce, or traffic increase PHP and database load. You need a domain whose DNS can point to the VM, SSH access with a non-root sudo user, and a fresh or maintained Ubuntu 24.04 server. Keep the domain placeholder `example.com` until you replace it with your real hostname. ## Step 1 — Confirm DNS and Update Ubuntu Point the domain's A record to the public IPv4 address of your Raff Linux VM. Only add an AAAA record when IPv6 is configured and reachable on the same server. From your workstation, check DNS: ```bash dig +short A example.com dig +short AAAA example.com ``` Then connect over SSH and update Ubuntu: ```bash sudo apt update sudo apt upgrade -y ``` If the upgrade reports that a reboot is required, reboot before continuing and reconnect over SSH: ```bash sudo reboot ``` **Verify:** `dig +short A example.com` should return the VM's public IPv4 address, and `sudo apt update` should complete without repository errors. ## Step 2 — Install Nginx, MariaDB, PHP-FPM, and WordPress Extensions Install Nginx, MariaDB, PHP-FPM, and the PHP extensions commonly needed by WordPress: ```bash sudo apt install -y \ nginx \ mariadb-server \ php-fpm \ php-mysql \ php-curl \ php-gd \ php-intl \ php-mbstring \ php-soap \ php-xml \ php-zip \ php-imagick \ curl \ tar \ openssl ``` Enable the core services: ```bash sudo systemctl enable --now nginx mariadb php8.3-fpm ``` Check the installed versions: ```bash nginx -v php -v mariadb --version ``` WordPress currently recommends PHP 8.3 or newer, MariaDB 10.11 or newer or MySQL 8.0 or newer, plus HTTPS. Ubuntu 24.04's standard PHP-FPM service is `php8.3-fpm`; if you deliberately installed another PHP version, use that service and socket consistently in later steps. **Verify:** Run: ```bash systemctl is-active nginx mariadb php8.3-fpm ``` All three services should return `active`. ## Step 3 — Secure MariaDB Before Creating WordPress Data Run MariaDB's security helper: ```bash sudo mariadb-secure-installation ``` For a local single-server WordPress deployment, keep local administrative access protected, remove anonymous users, remove the test database, and disallow unnecessary remote root access. WordPress will use its own database user rather than the MariaDB root account. Check that MariaDB is listening locally: ```bash sudo ss -ltnp | grep 3306 || true ``` Do not open TCP port `3306` in UFW or another public firewall for this architecture. **Verify:** `sudo mariadb -e "SELECT VERSION();"` should return the database version, and there should be no public firewall rule exposing port `3306`. ## Step 4 — Create a Dedicated WordPress Database and User Generate a strong database password and save it in your password manager: ```bash openssl rand -hex 24 ``` Open the MariaDB shell: ```bash sudo mariadb ``` Create the database and a local-only user. Replace `use_a_unique_password` with the password you generated: ```sql CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'use_a_unique_password'; GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost'; FLUSH PRIVILEGES; EXIT; ``` Test the WordPress account: ```bash mariadb -u wpuser -p wordpress ``` Then run: ```sql SELECT DATABASE(), CURRENT_USER(); EXIT; ``` **Verify:** The query should show `wordpress` as the active database and `wpuser@localhost` as the current user. ## Step 5 — Download WordPress from the Official Source Download the current WordPress archive from WordPress.org: ```bash cd /tmp curl -fLO https://wordpress.org/latest.tar.gz ``` Extract it: ```bash tar -xzf latest.tar.gz ``` Create the site directory and copy the WordPress files: ```bash sudo mkdir -p /var/www/example.com/public sudo cp -a /tmp/wordpress/. /var/www/example.com/public/ ``` Confirm the expected core files exist: ```bash ls -l /var/www/example.com/public/wp-admin/index.php ls -l /var/www/example.com/public/wp-includes/version.php ``` You can inspect the downloaded WordPress version with: ```bash grep -m1 '\$wp_version =' /var/www/example.com/public/wp-includes/version.php ``` **Verify:** `wp-admin/index.php` and `wp-includes/version.php` should both exist, and the version file should contain a WordPress version value. ## Step 6 — Configure wp-config.php and Authentication Salts Create `wp-config.php` from the sample: ```bash sudo cp /var/www/example.com/public/wp-config-sample.php \ /var/www/example.com/public/wp-config.php ``` Open the file: ```bash sudo nano /var/www/example.com/public/wp-config.php ``` Set the database values created in Step 4: ```php define( 'DB_NAME', 'wordpress' ); define( 'DB_USER', 'wpuser' ); define( 'DB_PASSWORD', 'use_a_unique_password' ); define( 'DB_HOST', 'localhost' ); define( 'DB_CHARSET', 'utf8mb4' ); ``` Generate fresh WordPress authentication keys and salts from the official API: ```bash curl -s https://api.wordpress.org/secret-key/1.1/salt/ ``` Replace the placeholder authentication key and salt definitions in `wp-config.php` with the generated values. Disable the built-in plugin and theme file editors by adding this above the final stop-editing comment: ```php define( 'DISALLOW_FILE_EDIT', true ); ``` This removes a common code-editing path from the WordPress dashboard if an administrator account is compromised. **Verify:** Confirm the database constants exist without printing the password to your terminal history again: ```bash sudo grep -E "DB_NAME|DB_USER|DB_HOST|DISALLOW_FILE_EDIT" \ /var/www/example.com/public/wp-config.php ``` You should see the expected database name, user, host, and `DISALLOW_FILE_EDIT` setting. ## Step 7 — Apply Safer WordPress Ownership and File Permissions WordPress's hardening guidance recommends keeping core files writable by the administrative user rather than making every application file writable by the web server. Use your SSH user as the owner and `www-data` as the group: ```bash sudo chown -R "$USER":www-data /var/www/example.com ``` Set directories to `750` and files to `640`: ```bash sudo find /var/www/example.com -type d -exec chmod 750 {} \; sudo find /var/www/example.com -type f -exec chmod 640 {} \; ``` Allow PHP-FPM to write inside `wp-content`, where uploads, caches, and some plugin operations need write access: ```bash sudo find /var/www/example.com/public/wp-content -type d -exec chmod 770 {} \; sudo find /var/www/example.com/public/wp-content -type f -exec chmod 660 {} \; ``` Keep `wp-config.php` restricted: ```bash sudo chmod 640 /var/www/example.com/public/wp-config.php ``` Do not use `chmod 777` on WordPress files or directories. This layout intentionally keeps the WordPress core less writable than `wp-content`; if a dashboard-based core update cannot replace core files, perform the update through your normal administrative deployment workflow instead of loosening the entire document root. **Verify:** Run: ```bash stat -c '%U %G %a %n' \ /var/www/example.com/public/wp-config.php \ /var/www/example.com/public/wp-content ``` The owner should be your Linux user, the group should be `www-data`, and `wp-content` should be writable by the group while `wp-config.php` remains restricted. ## Step 8 — Configure Nginx for WordPress and Block PHP in Uploads Create the Nginx server block: ```bash sudo nano /etc/nginx/sites-available/example.com ``` Add: ```nginx server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/public; index index.php index.html; client_max_body_size 64M; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; location / { try_files $uri $uri/ /index.php?$args; } location = /wp-config.php { deny all; } location ~* /(?:uploads|files)/.*\.php$ { deny all; } location ~ /\.(?!well-known).* { deny all; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location = /xmlrpc.php { deny all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png|svg|webp|woff|woff2)$ { expires 7d; access_log off; } } ``` The `try_files` rule supports WordPress pretty permalinks. The uploads restriction prevents a `.php` file placed under common upload paths from being executed by PHP-FPM. The `xmlrpc.php` block is optional: remove it if you use Jetpack, the WordPress mobile app, remote publishing, or another XML-RPC-dependent integration. Enable the site and remove the default site symlink: ```bash sudo ln -s /etc/nginx/sites-available/example.com \ /etc/nginx/sites-enabled/example.com sudo rm -f /etc/nginx/sites-enabled/default ``` Test and reload Nginx: ```bash sudo nginx -t sudo systemctl reload nginx ``` **Verify:** `sudo nginx -t` should report that the configuration syntax is successful, and `curl -I http://127.0.0.1 -H 'Host: example.com'` should return an HTTP response from the new server block. ## Step 9 — Configure UFW Without Locking Out SSH Check UFW first: ```bash sudo ufw status ``` If UFW is active, allow the existing SSH path before changing web rules: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw status ``` Do not open MariaDB port `3306` publicly for this single-VM WordPress setup. If UFW is currently inactive, review your SSH access and firewall policy before enabling it. Do not blindly enable a firewall on a remote server without confirming that your management path is allowed. **Verify:** When UFW is active, the status should allow SSH plus HTTP/HTTPS and should not contain a public MariaDB rule. ## Step 10 — Enable HTTPS with Let's Encrypt Install Certbot and its Nginx plugin: ```bash sudo apt install -y certbot python3-certbot-nginx ``` Request a certificate and configure an HTTP-to-HTTPS redirect: ```bash sudo certbot --nginx --redirect \ -d example.com \ -d www.example.com ``` Only request hostnames whose public DNS records already point to this VM. Check the certificate and renewal path: ```bash sudo certbot certificates sudo certbot renew --dry-run ``` For deeper certificate troubleshooting, use [How to Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). **Verify:** Open `https://example.com` or run: ```bash curl -I https://example.com ``` The connection should complete over HTTPS, and an HTTP request should redirect to HTTPS after Certbot configures the site. ## Step 11 — Complete the WordPress Browser Installation Open: ```text https://example.com ``` Choose the site language and enter: - Site title - Administrator username - Strong administrator password - Administrator email address - Search-engine visibility preference Avoid predictable administrator usernames such as `admin`. Complete the installer, then sign in at: ```text https://example.com/wp-admin/ ``` After login, immediately review **Dashboard → Updates** and apply required WordPress, theme, and plugin updates using an update method compatible with the file-permission model from Step 7. **Verify:** You should be able to sign in to `/wp-admin/`, open the site homepage in another browser window, and load a WordPress page over HTTPS without a certificate warning. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to build a self-managed WordPress VPS with Nginx, PHP-FPM, MariaDB, and HTTPS. ::: ## Step 12 — Verify WordPress, Nginx, PHP-FPM, and the Uploads Restriction Run the service checks: ```bash systemctl is-active nginx mariadb php8.3-fpm ``` Check the public HTTP and HTTPS behavior: ```bash curl -I http://example.com curl -I https://example.com curl -I https://example.com/wp-login.php ``` The HTTP request should redirect to HTTPS. The HTTPS homepage and login page should return a valid application response. Now test the Nginx uploads restriction with a temporary PHP probe: ```bash sudo mkdir -p /var/www/example.com/public/wp-content/uploads printf '%s\n' '' \ | sudo tee /var/www/example.com/public/wp-content/uploads/raff-php-test.php >/dev/null curl -i https://example.com/wp-content/uploads/raff-php-test.php sudo rm -f /var/www/example.com/public/wp-content/uploads/raff-php-test.php ``` You want Nginx to deny the request rather than execute the PHP file. Check recent service errors: ```bash sudo tail -n 50 /var/log/nginx/example.com.error.log sudo journalctl -u php8.3-fpm -n 50 --no-pager sudo journalctl -u mariadb -n 50 --no-pager ``` **Verify:** All three services should be active, HTTP should redirect to HTTPS, the WordPress homepage and login should load, and the uploads PHP probe should be denied. ## Step 13 — Configure Backups and Production Maintenance A working WordPress installation is not complete until you can restore both the database and site files. At minimum, back up: - the MariaDB `wordpress` database - `/var/www/example.com/public` - the Nginx site configuration - any external DNS or application configuration needed for recovery Create a manual database backup example: ```bash mkdir -p ~/backups mariadb-dump -u wpuser -p wordpress | gzip > ~/backups/wordpress.sql.gz ``` Create a file backup example: ```bash tar -czf ~/backups/wordpress-files.tar.gz \ /var/www/example.com/public ``` Store at least one backup away from the VM. Raff [Data Protection](/products/data-protection) can protect the server layer, while [Object Storage](/products/object-storage) can be used as an off-server destination when your backup workflow supports S3-compatible storage. A backup should not be considered reliable until you have tested restoring it. For ongoing maintenance: - keep Ubuntu, PHP, WordPress core, themes, and plugins patched - remove unused themes and plugins - use multi-factor authentication for administrator accounts - monitor disk usage before large imports or backup jobs - review Nginx, PHP-FPM, and MariaDB logs when application behavior changes - add caching only after measuring the actual bottleneck **Verify:** Confirm both backup files exist and are non-empty: ```bash ls -lh ~/backups/wordpress.sql.gz ~/backups/wordpress-files.tar.gz gzip -t ~/backups/wordpress.sql.gz ``` ## Step 14 — Clean Up or Roll Back the Installation If the installation is working and you are keeping it, remove the downloaded archive and extracted temporary source: ```bash rm -rf /tmp/wordpress /tmp/latest.tar.gz ``` If you are abandoning this test installation, the following rollback is destructive. Back up anything you need first. Disable the Nginx site: ```bash sudo rm -f /etc/nginx/sites-enabled/example.com sudo nginx -t sudo systemctl reload nginx ``` Remove the site files only when you are certain they are no longer needed: ```bash sudo rm -rf /var/www/example.com ``` Drop the WordPress database and user: ```bash sudo mariadb ``` Then run: ```sql DROP DATABASE wordpress; DROP USER 'wpuser'@'localhost'; EXIT; ``` If you also want to remove the Let's Encrypt certificate for this hostname, review the installed certificates first: ```bash sudo certbot certificates ``` Then delete only the certificate name that belongs to this retired site: ```bash sudo certbot delete --cert-name example.com ``` **Verify:** After a full rollback, the Nginx site symlink should be absent, the site directory should be removed, and `SHOW DATABASES LIKE 'wordpress';` should return no WordPress database. ## Conclusion You now have WordPress running on Ubuntu 24.04 with Nginx, PHP 8.3, MariaDB, restricted configuration permissions, HTTPS, and an Nginx rule that blocks PHP execution from the uploads path. The installation also has a dedicated local database account, an explicit end-to-end verification flow, and a backup and rollback path. This setup is a practical WordPress VPS pattern when you want more control than shared hosting. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month; for WordPress, use at least 2 GB RAM and size upward based on PHP workers, database usage, plugins, imports, and traffic. For the underlying server stack, see [How to Set Up a LEMP Stack on Ubuntu 24.04](/learn/tutorials/set-up-lemp-stack-ubuntu-24-04), and use [Data Protection](/products/data-protection) or [Object Storage](/products/object-storage) as part of a tested backup strategy. --- ### How to Set Up a LEMP Stack on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/set-up-lemp-stack-ubuntu-24-04 Description: Set up a LEMP stack on Ubuntu 24.04 with Nginx, PHP 8.3, MariaDB, secure database access, HTTPS, verification, and rollback steps. A LEMP stack combines Linux, Nginx, MariaDB or MySQL, and PHP-FPM to run PHP websites and applications. On Ubuntu 24.04, you can build the stack from the standard Ubuntu repositories without adding third-party package sources. This tutorial sets up a production-oriented LEMP stack on a Raff Linux VM, creates a dedicated local database user, connects Nginx to PHP-FPM, verifies PHP execution, adds a basic firewall and HTTPS path, and finishes with end-to-end checks and cleanup instructions. The current Ubuntu 24.04 package line uses PHP 8.3, and Ubuntu's Noble package repository provides MariaDB 10.11. You can verify those package baselines in the official [Ubuntu PHP package listing](https://packages.ubuntu.com/noble/php) and [Ubuntu MariaDB package listing](https://packages.ubuntu.com/noble/mariadb-server). This guide uses MariaDB, but the same LEMP architecture can use MySQL when your application requires it. You need an Ubuntu 24.04 server with at least 2 GB RAM, SSH access, and a non-root user with sudo privileges. A domain is optional for the initial stack test but required for the HTTPS step. ## Step 1 — Update Ubuntu and Confirm the Server Baseline Update package metadata and install available updates: ```bash sudo apt update sudo apt upgrade -y ``` Check the operating system release: ```bash cat /etc/os-release ``` If the upgrade reports that a reboot is required, reboot and reconnect before continuing: ```bash sudo reboot ``` **Verify:** `/etc/os-release` should identify Ubuntu 24.04, and `sudo apt update` should complete without repository errors. ## Step 2 — Install and Start Nginx Install Nginx: ```bash sudo apt install -y nginx ``` Enable it at boot and start it now: ```bash sudo systemctl enable --now nginx ``` Check the service and installed version: ```bash systemctl is-active nginx nginx -v ``` If UFW is already active, allow HTTP and HTTPS traffic only after confirming that your SSH rule is present: ```bash sudo ufw status sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' ``` For a deeper Nginx-only setup, see [How to Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). **Verify:** `systemctl is-active nginx` should return `active`, and `curl -I http://127.0.0.1` should return an HTTP response from Nginx. ## Step 3 — Install and Secure MariaDB Install MariaDB from the Ubuntu repositories: ```bash sudo apt install -y mariadb-server ``` Enable and start the service: ```bash sudo systemctl enable --now mariadb ``` Run MariaDB's security helper: ```bash sudo mariadb-secure-installation ``` For a single-server LEMP stack, keep local administrative access protected, remove anonymous users and the test database, and avoid unnecessary remote root access. Applications should never connect using the MariaDB root account. Check the database version: ```bash sudo mariadb -e "SELECT VERSION();" ``` Do not expose MariaDB port `3306` publicly for this architecture. **Verify:** `systemctl is-active mariadb` should return `active`, and the version query should return a MariaDB 10.11 release from the Ubuntu 24.04 package line. ## Step 4 — Install PHP-FPM and Common PHP Extensions Install PHP-FPM, the CLI, MySQL/MariaDB support, and common PHP modules: ```bash sudo apt install -y \ php-fpm \ php-cli \ php-mysql \ php-curl \ php-gd \ php-intl \ php-mbstring \ php-xml \ php-zip \ php-bcmath ``` Ubuntu 24.04's standard PHP branch is 8.3. Check the CLI version and PHP-FPM service: ```bash php -v systemctl is-active php8.3-fpm ``` Confirm the PHP-FPM Unix socket exists: ```bash ls -l /run/php/php8.3-fpm.sock ``` If you deliberately install another PHP branch later, update both the service name and Nginx socket path consistently. **Verify:** `php -v` should report PHP 8.3.x on the standard Ubuntu 24.04 package line, `php8.3-fpm` should be active, and `/run/php/php8.3-fpm.sock` should exist. ## Step 5 — Create a Dedicated Database and Application User Generate a strong password and save it in a password manager: ```bash openssl rand -hex 24 ``` Open MariaDB: ```bash sudo mariadb ``` Create an application database and local-only user. Replace `use_a_unique_password` with the generated password: ```sql CREATE DATABASE example_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'use_a_unique_password'; GRANT ALL PRIVILEGES ON example_app.* TO 'example_user'@'localhost'; FLUSH PRIVILEGES; EXIT; ``` Test the application account: ```bash mariadb -u example_user -p example_app ``` Then run: ```sql SELECT DATABASE(), CURRENT_USER(); EXIT; ``` **Verify:** The query should show `example_app` and `example_user@localhost`. Keep port `3306` closed to the public internet. ## Step 6 — Create the Website Directory This tutorial uses `example.com`. Replace it with your domain if you have one. Create the document root: ```bash sudo mkdir -p /var/www/example.com/public sudo chown -R "$USER":www-data /var/www/example.com sudo find /var/www/example.com -type d -exec chmod 750 {} \; sudo find /var/www/example.com -type f -exec chmod 640 {} \; ``` Create a basic HTML page: ```bash cat <<'EOF' | sudo tee /var/www/example.com/public/index.html >/dev/null LEMP stack ready

Nginx is serving the LEMP site

EOF ``` **Verify:** Run `ls -ld /var/www/example.com/public` and confirm that the directory exists, then confirm `index.html` is present with `ls -l /var/www/example.com/public/index.html`. ## Step 7 — Configure the Nginx Server Block for PHP-FPM Create the site configuration: ```bash sudo nano /etc/nginx/sites-available/example.com ``` Add: ```nginx server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/public; index index.php index.html; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location ~ /\.(?!well-known).* { deny all; } } ``` Enable the site and remove the default site symlink: ```bash sudo ln -s /etc/nginx/sites-available/example.com \ /etc/nginx/sites-enabled/example.com sudo rm -f /etc/nginx/sites-enabled/default ``` Test before reloading: ```bash sudo nginx -t sudo systemctl reload nginx ``` Never reload Nginx after a failed `nginx -t` check. **Verify:** `sudo nginx -t` should report successful syntax, and this request should return the site response: ```bash curl -I http://127.0.0.1 -H 'Host: example.com' ``` ## Step 8 — Verify PHP Processing Without Leaving phpinfo() Exposed Create a temporary PHP test file: ```bash cat <<'EOF' | sudo tee /var/www/example.com/public/health.php >/dev/null /tmp/lemp-db-test.php <<'PHP' PDO::ERRMODE_EXCEPTION] ); echo "database-ok\n"; PHP ``` Replace `use_a_unique_password` with the application database password, then run it from the CLI: ```bash php /tmp/lemp-db-test.php ``` Remove the temporary file immediately: ```bash rm -f /tmp/lemp-db-test.php ``` Because the test runs outside the public web root, the database credential is never intentionally exposed over HTTP. **Verify:** The command should print `database-ok`, and the temporary test file should be removed afterward. ## Step 10 — Add HTTPS When the Domain Points to the VM If you have a public domain whose A or AAAA records point to this server, install Certbot and its Nginx plugin: ```bash sudo apt install -y certbot python3-certbot-nginx ``` Request a certificate and redirect HTTP to HTTPS: ```bash sudo certbot --nginx --redirect \ -d example.com \ -d www.example.com ``` Check the certificate and renewal process: ```bash sudo certbot certificates sudo certbot renew --dry-run ``` For certificate troubleshooting, use [How to Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). **Verify:** `curl -I https://example.com` should complete over HTTPS, and `curl -I http://example.com` should redirect to HTTPS after Certbot updates the Nginx configuration. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to build a LEMP stack with Nginx, PHP-FPM, and MariaDB on Ubuntu 24.04. ::: ## Step 11 — Run the Final End-to-End LEMP Verification Check all three services: ```bash systemctl is-active nginx mariadb php8.3-fpm ``` Test the site locally through the configured hostname: ```bash curl -I http://127.0.0.1 -H 'Host: example.com' ``` Check recent service and site errors: ```bash sudo journalctl -u nginx -n 30 --no-pager sudo journalctl -u mariadb -n 30 --no-pager sudo journalctl -u php8.3-fpm -n 30 --no-pager sudo tail -n 30 /var/log/nginx/example.com.error.log ``` Confirm MariaDB is not intentionally exposed through UFW: ```bash sudo ufw status ``` For production workloads, measure actual PHP-FPM worker memory and database usage before tuning process limits. A fixed `pm.max_children` value is not portable across WordPress, Laravel, Drupal, custom PHP applications, and different plugin or request profiles. **Verify:** Nginx, MariaDB, and PHP-FPM should all be active; the configured site should return an HTTP response; logs should not show a repeating fatal configuration error; and port `3306` should not have a public firewall rule. ## Step 12 — Clean Up or Roll Back the LEMP Test Site If you are keeping the stack, there is nothing else to remove after the temporary PHP and database test files from Steps 8 and 9 are deleted. If this was only a test and you want to remove the example site, first disable the Nginx site: ```bash sudo rm -f /etc/nginx/sites-enabled/example.com sudo nginx -t sudo systemctl reload nginx ``` Remove the example files only if they are no longer needed: ```bash sudo rm -rf /var/www/example.com sudo rm -f /etc/nginx/sites-available/example.com ``` Drop the test database and user: ```bash sudo mariadb ``` Then run: ```sql DROP DATABASE example_app; DROP USER 'example_user'@'localhost'; EXIT; ``` If you issued a Let's Encrypt certificate specifically for this retired test domain, inspect certificates before deleting anything: ```bash sudo certbot certificates ``` Then delete only the certificate that belongs to the retired hostname: ```bash sudo certbot delete --cert-name example.com ``` **Verify:** After a full rollback, the Nginx site symlink and document root should be gone, and `SHOW DATABASES LIKE 'example_app';` should return no test database. ## Conclusion You now have a complete LEMP stack on Ubuntu 24.04 with Nginx serving the application, PHP-FPM handling PHP requests, and MariaDB using a dedicated local application account. The stack has explicit Nginx, PHP, database, firewall, HTTPS, end-to-end verification, and rollback paths rather than stopping after package installation. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. For a LEMP stack that runs Nginx, PHP-FPM, and MariaDB on one server, start with at least 2 GB RAM and size upward based on PHP concurrency, database usage, application complexity, and traffic. If you need database lifecycle management separated from the VM, compare this architecture with [managed versus self-hosted databases](/learn/guides/managed-vs-self-hosted-databases). For a concrete application deployment on top of this stack, continue with [WordPress on Ubuntu 24.04 with Nginx](/learn/tutorials/install-wordpress-ubuntu-24-04-nginx). --- ### How to Deploy Gitea with Docker Compose on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-gitea-ubuntu-24-04 Description: Deploy Gitea on Ubuntu 24.04 with Docker Compose, PostgreSQL, Nginx, HTTPS, SSH clone access, backups, upgrades, and verification steps. Gitea is a self-hosted Git server for teams that want repository hosting, pull requests, issues, releases, packages, webhooks, and other development workflows on infrastructure they control. In this tutorial, you will deploy Gitea on a Raff Linux VM with Docker Compose, PostgreSQL, Nginx, HTTPS, and SSH clone access. The web service stays bound to localhost behind Nginx, while Git-over-SSH uses a separate host port so it does not conflict with the VM's administrative SSH service. This guide follows Gitea's current Docker deployment model and uses the official `docker.gitea.com/gitea` image. At the time of this update, Gitea's official installation documentation uses the 1.27.3 release in its stable Docker examples. The official docs also recommend choosing a database early rather than relying on SQLite when you expect the instance to grow; this tutorial uses PostgreSQL for a multi-user setup. See the [Gitea Docker installation documentation](https://docs.gitea.com/installation/install-with-docker/) and [database preparation guidance](https://docs.gitea.com/installation/database-prep/) for the upstream reference. You need Ubuntu 24.04, Docker with Compose v2, Nginx, a domain such as `git.example.com`, SSH access with sudo privileges, and DNS pointing the domain to the VM. ## Step 1 — Confirm Docker, DNS, and the Ubuntu Host Check the Ubuntu release: ```bash cat /etc/os-release ``` Confirm Docker and Compose are available: ```bash docker --version docker compose version ``` Check that your Gitea hostname resolves to the VM: ```bash dig +short A git.example.com ``` If Docker is not installed yet, follow [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04). If Nginx is missing, use [How to Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). **Verify:** Ubuntu should report 24.04, `docker compose version` should work, and the DNS A record should return the VM's public IPv4 address. ## Step 2 — Create the Gitea Project and Protect Database Secrets Create a dedicated project directory: ```bash mkdir -p ~/gitea cd ~/gitea ``` Generate a strong PostgreSQL password: ```bash openssl rand -hex 32 ``` Create an environment file: ```bash nano .env ``` Add the generated password: ```dotenv POSTGRES_PASSWORD=replace_with_your_generated_password ``` Restrict the file so other local users cannot read it: ```bash chmod 600 .env ``` Do not commit this `.env` file to a Git repository. **Verify:** Run `stat -c '%a %n' .env`. It should show permission mode `600` for `.env`. ## Step 3 — Create the Docker Compose Stack Create the Compose file: ```bash nano compose.yaml ``` Add: ```yaml services: gitea: image: docker.gitea.com/gitea:1.27.3 container_name: gitea restart: unless-stopped environment: USER_UID: "1000" USER_GID: "1000" GITEA__database__DB_TYPE: postgres GITEA__database__HOST: db:5432 GITEA__database__NAME: gitea GITEA__database__USER: gitea GITEA__database__PASSWD: ${POSTGRES_PASSWORD} GITEA__server__DOMAIN: git.example.com GITEA__server__ROOT_URL: https://git.example.com/ GITEA__server__SSH_DOMAIN: git.example.com GITEA__server__SSH_PORT: "2222" volumes: - gitea_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "127.0.0.1:3000:3000" - "2222:22" depends_on: db: condition: service_healthy db: image: postgres:16-alpine container_name: gitea-db restart: unless-stopped environment: POSTGRES_USER: gitea POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: gitea volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U gitea -d gitea"] interval: 10s timeout: 5s retries: 5 volumes: gitea_data: postgres_data: ``` Replace every `git.example.com` value with your real hostname. Gitea supports PostgreSQL 12 and newer, so PostgreSQL 16 is within the supported range. The web port is published only on `127.0.0.1`; Nginx will be the public HTTP entry point. Host port `2222` carries Git-over-SSH and stays separate from the VM's normal SSH port 22. Check the rendered Compose configuration without printing secret values into a public log: ```bash docker compose config --services ``` **Verify:** The command should list exactly `gitea` and `db`, and `docker compose config -q` should exit without a validation error. ## Step 4 — Start Gitea and PostgreSQL Start the stack: ```bash docker compose up -d ``` Check container state: ```bash docker compose ps ``` Review recent logs: ```bash docker compose logs --tail=50 gitea docker compose logs --tail=50 db ``` Test the local Gitea HTTP endpoint: ```bash curl -I http://127.0.0.1:3000 ``` The first startup may take longer while the database initializes and Gitea prepares its data directory. **Verify:** `docker compose ps` should show the database healthy and Gitea running, while `curl -I http://127.0.0.1:3000` should return an HTTP response. ## Step 5 — Configure Nginx as the Public Reverse Proxy Create an Nginx server block: ```bash sudo nano /etc/nginx/sites-available/git.example.com ``` Add: ```nginx server { listen 80; listen [::]:80; server_name git.example.com; location / { client_max_body_size 512M; proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Connection $http_connection; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` Gitea's reverse-proxy guidance requires the public `ROOT_URL` to match the external URL and expects the proxy to preserve the host and forwarded protocol. The upload-size limit prevents Nginx from rejecting larger web uploads with `413 Request Entity Too Large`. See the [official Gitea reverse proxy documentation](https://docs.gitea.com/administration/reverse-proxies/). Enable the site: ```bash sudo ln -s /etc/nginx/sites-available/git.example.com \ /etc/nginx/sites-enabled/git.example.com ``` Test and reload Nginx: ```bash sudo nginx -t sudo systemctl reload nginx ``` **Verify:** `sudo nginx -t` should report successful syntax, and `curl -I http://git.example.com` should reach the Gitea site through Nginx. ## Step 6 — Enable HTTPS and Open Only the Required Public Ports If UFW is active, first confirm administrative SSH is allowed: ```bash sudo ufw status sudo ufw allow OpenSSH ``` Allow HTTP/HTTPS and the Gitea SSH clone port: ```bash sudo ufw allow 'Nginx Full' sudo ufw allow 2222/tcp ``` Install Certbot and request a certificate: ```bash sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx --redirect -d git.example.com ``` Test renewal: ```bash sudo certbot renew --dry-run ``` Do not expose container port 3000 publicly; it should remain bound to localhost. **Verify:** `curl -I https://git.example.com` should complete over HTTPS, HTTP should redirect to HTTPS, and `sudo ss -ltnp` should show Gitea's web port bound to `127.0.0.1:3000` rather than `0.0.0.0:3000`. ## Step 7 — Complete the Gitea Installation and Create the First Administrator Open: ```text https://git.example.com ``` The Docker environment variables already provide the PostgreSQL connection values and public server URL. Confirm the database host is `db:5432`, database name is `gitea`, and the public site URL matches your HTTPS hostname. Create the initial administrator account with a strong unique password. After the installation finishes, sign in and review the site administration settings. For a private team instance, consider disabling open user registration after you have created the accounts you need. Also require multi-factor authentication for administrator accounts and keep a separate day-to-day user account instead of using the administrator identity for normal Git work. **Verify:** You should be able to sign in as the administrator over HTTPS and reach the Site Administration area without a certificate warning. ## Step 8 — Configure and Test Git-over-SSH In Gitea, add your public SSH key under your user settings. From your workstation, test the dedicated Git SSH port: ```bash ssh -T -p 2222 git@git.example.com ``` The connection may report that interactive shell access is disabled; that is expected for a Git service. The important result is that the connection reaches Gitea rather than the VM's normal SSH daemon. If port 2222 is not reachable, check: ```bash sudo ufw status docker compose ps sudo ss -ltnp | grep 2222 ``` **Verify:** `ssh -T -p 2222 git@git.example.com` should reach the Gitea SSH service associated with your account. ## Step 9 — Create a Repository and Push the First Commit Create a repository in the Gitea web interface, for example `demo-repo`. Then clone it from your workstation using the SSH URL shown by Gitea: ```bash git clone ssh://git@git.example.com:2222/your_username/demo-repo.git cd demo-repo ``` Create a file and push a commit: ```bash printf '# Gitea test repository\n' > README.md git add README.md git commit -m "Add README" git push origin main ``` If the repository was created with a different default branch, use the branch name shown by Gitea instead of assuming `main`. **Verify:** Refresh the repository in the browser. The new commit and README should appear, proving that SSH authentication, repository storage, Git receive hooks, and the database are working together. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to run a self-hosted Gitea Git server with Docker Compose, PostgreSQL, Nginx, and HTTPS. ::: ## Step 10 — Add a Consistent Backup Workflow Gitea contains repositories, configuration, application data, and database state. Gitea's official backup guidance recommends stopping the Gitea application while taking a consistency-sensitive backup so the database and repository state cannot change independently during the operation. See [Gitea Backup and Restore](https://docs.gitea.com/administration/backup-and-restore/). Create a backup directory: ```bash mkdir -p ~/gitea-backups BACKUP_DIR="$HOME/gitea-backups/$(date +%F-%H%M%S)" mkdir -p "$BACKUP_DIR" ``` Stop the application container but keep PostgreSQL available for the database dump: ```bash cd ~/gitea docker compose stop gitea ``` Dump PostgreSQL: ```bash docker compose exec -T db \ pg_dump -U gitea -d gitea > "$BACKUP_DIR/gitea-db.sql" ``` Back up the Gitea data volume: ```bash docker run --rm \ -v gitea_gitea_data:/data:ro \ -v "$BACKUP_DIR":/backup \ alpine \ tar -czf /backup/gitea-data.tar.gz -C /data . ``` Copy the deployment configuration: ```bash cp compose.yaml .env "$BACKUP_DIR/" chmod 600 "$BACKUP_DIR/.env" ``` Start Gitea again: ```bash docker compose start gitea ``` The named volume is normally `gitea_gitea_data` when the Compose project directory is `~/gitea`. Confirm the real name with `docker volume ls` before using the backup command if you changed the project name. Store at least one backup away from the VM. Raff [Data Protection](/products/data-protection) can protect the server layer, and [Object Storage](/products/object-storage) can be used as an off-server destination for backup archives when your workflow supports S3-compatible storage. **Verify:** Confirm `gitea-db.sql`, `gitea-data.tar.gz`, `compose.yaml`, and `.env` exist in the timestamped backup directory and are non-empty. ## Step 11 — Upgrade Gitea Safely Before an upgrade, read the Gitea changelog and create a backup. Gitea explicitly recommends having a backup even for production patch upgrades because startup can perform database migrations and an older binary may not be able to use a migrated database. Check the current version: ```bash docker exec gitea gitea --version ``` After reviewing the target release, edit `compose.yaml` and change the pinned image tag to the version you intend to run. Then pull the image: ```bash docker compose pull gitea ``` After your backup is complete, recreate the Gitea container: ```bash docker compose up -d gitea ``` Review startup logs and the reported version: ```bash docker compose logs --tail=100 gitea docker exec gitea gitea --version ``` Do not upgrade PostgreSQL to a new major version merely by changing `postgres:16-alpine` to another major tag. PostgreSQL major-version upgrades require a proper `pg_upgrade` or dump-and-restore workflow. **Verify:** The Gitea container should start without repeating migration errors, the expected version should be reported, and an existing repository should still open and accept a test fetch. ## Step 12 — Troubleshoot the Most Common Gitea Deployment Failures If Gitea cannot connect to PostgreSQL, inspect both services: ```bash docker compose logs --tail=100 gitea docker compose logs --tail=100 db ``` Confirm both services receive the same `POSTGRES_PASSWORD` through the Compose configuration and that the Gitea database host is `db:5432`, not `localhost:5432`. If generated links or clone URLs use the wrong scheme or hostname, verify: - `GITEA__server__ROOT_URL=https://git.example.com/` - the Nginx `Host` header - the Nginx `X-Forwarded-Proto` header If large uploads fail with HTTP 413, increase `client_max_body_size` deliberately based on your repository and package-upload policy rather than removing the limit entirely. If SSH clone URLs show the wrong port, confirm `GITEA__server__SSH_PORT` matches the public host port in Compose. **Verify:** After each fix, run `docker compose ps`, `curl -I https://git.example.com`, and `ssh -T -p 2222 git@git.example.com` to confirm the affected path is healthy. ## Step 13 — Run the Final End-to-End Verification Check containers: ```bash docker compose ps ``` Check the public HTTPS endpoint: ```bash curl -I https://git.example.com ``` Check the localhost-only backend: ```bash curl -I http://127.0.0.1:3000 ``` Check Git SSH access: ```bash ssh -T -p 2222 git@git.example.com ``` From a cloned test repository, verify a fetch: ```bash git fetch origin ``` Review recent errors: ```bash docker compose logs --tail=100 gitea docker compose logs --tail=100 db sudo tail -n 50 /var/log/nginx/error.log ``` **Verify:** The database should be healthy, Gitea should be running, HTTPS should load through Nginx, port 3000 should remain localhost-only, SSH authentication should reach Gitea, and an existing repository should fetch successfully. ## Step 14 — Clean Up or Roll Back the Test Deployment If you are keeping Gitea, remove only temporary test repositories or local clones you no longer need. To stop the deployment without deleting data: ```bash cd ~/gitea docker compose down ``` Named volumes remain after a normal `docker compose down`. To remove the Nginx site: ```bash sudo rm -f /etc/nginx/sites-enabled/git.example.com sudo rm -f /etc/nginx/sites-available/git.example.com sudo nginx -t sudo systemctl reload nginx ``` If this was only a disposable test and you intentionally want to destroy Gitea and PostgreSQL data, first verify your backups. Then run: ```bash cd ~/gitea docker compose down -v ``` The `-v` flag deletes the named volumes and therefore removes repositories, Gitea application data, and the PostgreSQL database for this Compose project. If you issued a Let's Encrypt certificate only for this retired hostname, inspect certificates first: ```bash sudo certbot certificates ``` Then delete only the relevant certificate: ```bash sudo certbot delete --cert-name git.example.com ``` **Verify:** For a non-destructive stop, `docker volume ls` should still show the data volumes. After an intentional destructive cleanup with `down -v`, the project containers and volumes should be gone. ## Conclusion You now have a self-hosted Gitea Git server on Ubuntu 24.04 with Docker Compose, PostgreSQL, Nginx, HTTPS, and Git-over-SSH. The deployment keeps the web backend off the public interface, separates Git SSH from administrative SSH, uses a dedicated database service, and includes backup, upgrade, troubleshooting, verification, and rollback procedures. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. For a small Gitea team, start with at least 2 GB RAM and size upward based on repository activity, package storage, search/indexing, concurrent users, and CI workloads. Keep CI runners separate when builds become resource-intensive so build jobs do not compete with the Git service and database for the same CPU, memory, and disk I/O. --- ### How to Install Portainer with Docker on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-portainer-docker-ubuntu-24-04 Description: Install Portainer CE on Ubuntu 24.04 with Docker, Nginx, trusted HTTPS, private admin access, backups, secure updates, and verification steps. Portainer provides a web interface for managing Docker containers, images, networks, volumes, and Compose stacks. In this tutorial, you will install Portainer Community Edition on a Raff Linux VM running Ubuntu 24.04, keep the management UI off the public Docker port, place it behind Nginx and Let's Encrypt, create the first administrator, manage the local Docker environment, deploy a test stack, back up Portainer's configuration, and verify the deployment end to end. Portainer has privileged access to the Docker daemon when you mount `/var/run/docker.sock`, so the Portainer administrator effectively has control over the Docker host. Treat the dashboard as an administrative interface, not a public application. This guide therefore binds Portainer's HTTPS port to localhost and publishes it through an authenticated administrator-facing hostname such as `portainer.example.com` instead of opening port 9443 directly to the internet. For production workloads, Portainer recommends its LTS release stream. As of September 2026, Portainer 2.45.0 LTS includes the fix for a critical Docker API authorization issue affecting earlier supported releases, so use the current `lts` image and verify the running version after deployment. You need Docker with Compose v2, Nginx, a domain pointed to the VM, and a non-root user with sudo privileges. ## Step 1 — Confirm Ubuntu, Docker, and DNS Check the operating system: ```bash cat /etc/os-release ``` Check Docker and Compose: ```bash docker --version docker compose version ``` Check that the management hostname resolves to the VM: ```bash dig +short A portainer.example.com ``` If Docker is not installed, follow [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04). If Nginx is missing, use [How to Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). **Verify:** Ubuntu should report 24.04, Docker Compose v2 should respond, and the DNS A record should return the VM's public IPv4 address. ## Step 2 — Create Persistent Portainer Storage Create the Docker volume that stores Portainer's configuration database and settings: ```bash docker volume create portainer_data ``` Inspect it: ```bash docker volume inspect portainer_data ``` This volume is separate from the Portainer container. Removing and recreating the container does not delete the configuration unless you also remove the volume. **Verify:** `docker volume inspect portainer_data` should return the volume metadata without an error. ## Step 3 — Deploy Portainer CE on the LTS Release Stream Run Portainer with its management HTTPS port bound only to localhost: ```bash docker run -d \ --name portainer \ --restart=always \ -p 127.0.0.1:9443:9443 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:lts ``` Portainer's official Docker installation uses port 9443 for the HTTPS UI. Port 8000 is optional and is only required when you use Edge Agent tunnel features, so this single-host deployment does not publish it. The Docker socket mount gives Portainer broad control over the Docker daemon. Anyone who gains Portainer administrator access can perform actions equivalent to administrative Docker access, so protect this service accordingly. Check the container: ```bash docker ps --filter name=portainer ``` Review startup logs: ```bash docker logs --tail=50 portainer ``` **Verify:** The container should be running and `sudo ss -ltnp | grep 9443` should show `127.0.0.1:9443`, not `0.0.0.0:9443`. ## Step 4 — Verify the Portainer Version Before Continuing Check the installed Portainer version: ```bash docker exec portainer /portainer --version ``` As of September 2026, do not run an affected 2.40.x through 2.44.x build. Portainer 2.45.0 LTS and 2.39.7 LTS contain the August 2026 fix for the Docker API authorization bypass. The `lts` tag should track the supported LTS stream, but verifying the actual running version prevents an unexpectedly stale local image from going unnoticed. If the version is stale, pull the LTS image and recreate Portainer: ```bash docker pull portainer/portainer-ce:lts docker stop portainer docker rm portainer ``` Then rerun the deployment command from Step 3. **Verify:** The reported version should be a supported, patched LTS release. At the time of this update, that means 2.45.0 LTS or a later patched release. ## Step 5 — Configure Nginx as the Public Entry Point Create an Nginx server block: ```bash sudo nano /etc/nginx/sites-available/portainer.example.com ``` Add: ```nginx server { listen 80; listen [::]:80; server_name portainer.example.com; location / { proxy_pass https://127.0.0.1:9443; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_ssl_verify off; proxy_read_timeout 600s; proxy_send_timeout 600s; } } ``` Portainer generates a self-signed certificate for its internal HTTPS listener by default. Because this upstream connection stays on loopback, Nginx can proxy to it while public users receive the trusted Let's Encrypt certificate configured in the next step. `proxy_ssl_verify off` applies only to the local self-signed upstream connection in this configuration. Enable the site: ```bash sudo ln -s /etc/nginx/sites-available/portainer.example.com \ /etc/nginx/sites-enabled/portainer.example.com sudo nginx -t sudo systemctl reload nginx ``` **Verify:** `sudo nginx -t` should report successful syntax and `curl -I http://portainer.example.com` should reach the Nginx virtual host. ## Step 6 — Add HTTPS and Keep Portainer's Direct Port Private If UFW is active, make sure SSH remains allowed before changing firewall rules: ```bash sudo ufw status sudo ufw allow OpenSSH ``` Allow Nginx traffic: ```bash sudo ufw allow 'Nginx Full' ``` Do not add a public UFW rule for port 9443 because Docker is already binding it to localhost only. Install Certbot and request a certificate: ```bash sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx --redirect -d portainer.example.com ``` Test certificate renewal: ```bash sudo certbot renew --dry-run ``` **Verify:** `curl -I https://portainer.example.com` should complete over HTTPS, HTTP should redirect to HTTPS, and `sudo ss -ltnp | grep 9443` should still show the backend bound to localhost only. ## Step 7 — Create the First Administrator Within the Setup Window Open: ```text https://portainer.example.com ``` Create the first administrator. Portainer requires the initial password to be at least 12 characters. Use a unique password stored in a password manager. Portainer intentionally times out an uninitialized installation if the first administrator is not created within five minutes. If the instance reports that it timed out for security purposes, restart it: ```bash docker stop portainer docker start portainer ``` Then complete the initial setup promptly. After the administrator is created, Portainer should automatically detect the local Docker environment. Select **Get Started** to manage it. **Verify:** You should be able to sign in over the public HTTPS hostname and see the local Docker environment without a browser certificate warning. ## Step 8 — Inspect the Local Docker Environment Safely Open the local environment in Portainer and review: - Containers - Images - Networks - Volumes - Stacks Use the UI for routine inspection and lifecycle actions, but remember that Portainer is an administrative control plane. Avoid granting dashboard access merely as a substitute for application-level access. From the command line, compare what Docker sees: ```bash docker ps -a docker volume ls docker network ls ``` The resources shown by these commands should correspond with the Portainer dashboard. **Verify:** An existing Docker container should appear in both `docker ps -a` and the Portainer Containers view with matching state. ## Step 9 — Deploy and Remove a Test Docker Compose Stack In Portainer, open **Stacks** and create a stack named `portainer-test`. Use the web editor with: ```yaml services: web: image: nginx:alpine restart: unless-stopped ports: - "127.0.0.1:8080:80" ``` Deploy the stack. The test container is deliberately bound to localhost so you do not need to expose another public firewall port just to verify the stack workflow. Test it from the VM: ```bash curl -I http://127.0.0.1:8080 ``` Then remove the test stack from Portainer when the check is complete. Confirm cleanup: ```bash sudo ss -ltnp | grep 8080 || echo 'test port removed' ``` **Verify:** The local curl should return an Nginx HTTP response before cleanup, and port 8080 should no longer be listening after the test stack is removed. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to install Portainer as a private Docker management UI behind Nginx and HTTPS. ::: ## Step 10 — Back Up the Portainer Configuration Portainer's built-in backup contains the configuration stored in its `/data` volume. It does not back up the application containers, Docker volumes, or databases that Portainer manages. In the Portainer UI, sign in as an administrator and open **Settings**. In **Back up Portainer**, download a configuration backup. Password-protect the archive if your operational process supports securely storing the backup password. For infrastructure recovery, protect Docker application state separately. Depending on your workloads, that can include database-native backups, volume backups, application configuration, and VM-level recovery points. Raff [Data Protection](/products/data-protection) can cover the VM recovery layer, while application-aware backups should remain part of the workload's own recovery design. After downloading the Portainer backup, store it somewhere other than the VM itself. **Verify:** Confirm the Portainer backup archive exists off-server and that your separate application backup process covers any persistent Docker workloads you would need to restore. ## Step 11 — Update Portainer Without Losing Configuration Before updating, create a Portainer configuration backup from Step 10. Then pull the supported LTS image: ```bash docker pull portainer/portainer-ce:lts ``` Stop and remove only the Portainer container: ```bash docker stop portainer docker rm portainer ``` Recreate it with the same `portainer_data` volume: ```bash docker run -d \ --name portainer \ --restart=always \ -p 127.0.0.1:9443:9443 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:lts ``` Check the version and logs: ```bash docker exec portainer /portainer --version docker logs --tail=100 portainer ``` Your Portainer users and settings remain in `portainer_data`. Removing the Portainer container does not remove other Docker containers on the host. **Verify:** You should be able to log in with the existing administrator account, the local environment should still be present, and the reported Portainer version should match the intended patched LTS release. ## Step 12 — Troubleshoot Common Portainer Problems If the UI returns a proxy error, first confirm Portainer itself is running: ```bash docker ps --filter name=portainer docker logs --tail=100 portainer curl -kI https://127.0.0.1:9443 ``` If the local HTTPS request works but the public hostname fails, test Nginx: ```bash sudo nginx -t sudo tail -n 50 /var/log/nginx/error.log ``` If Portainer appears to be a fresh installation after an update, confirm the correct data volume is mounted: ```bash docker inspect portainer \ --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}' ``` You should see a mount ending in `-> /data` and the Docker socket mount ending in `-> /var/run/docker.sock`. If setup timed out before the first administrator was created, restart the container as shown in Step 7. **Verify:** The backend request, Nginx configuration, Docker mounts, and Portainer logs should all agree on the failure path before you change the deployment. ## Step 13 — Run the Final End-to-End Verification Check the container and version: ```bash docker ps --filter name=portainer docker exec portainer /portainer --version ``` Check that 9443 remains private: ```bash sudo ss -ltnp | grep 9443 ``` Check the public HTTPS path: ```bash curl -I https://portainer.example.com ``` Check recent logs: ```bash docker logs --tail=100 portainer sudo tail -n 50 /var/log/nginx/error.log ``` Finally, sign in through the browser and confirm the local environment shows the same containers as: ```bash docker ps -a ``` **Verify:** Portainer should be running on a patched LTS release, port 9443 should be localhost-only, the public hostname should use trusted HTTPS, the administrator should be able to sign in, and Docker resources should be visible in the local environment. ## Step 14 — Remove Portainer Without Accidentally Deleting Other Containers To remove only the Portainer container: ```bash docker stop portainer docker rm portainer ``` This does not remove the other application containers that Portainer was managing. Remove the Nginx site if it is no longer needed: ```bash sudo rm -f /etc/nginx/sites-enabled/portainer.example.com sudo rm -f /etc/nginx/sites-available/portainer.example.com sudo nginx -t sudo systemctl reload nginx ``` Keep `portainer_data` if you may reinstall Portainer later. If this is a disposable test and you intentionally want to erase Portainer's users and configuration, first verify your backup and then remove the volume: ```bash docker volume rm portainer_data ``` If the Let's Encrypt certificate is no longer needed, inspect certificates before deleting anything: ```bash sudo certbot certificates ``` Then delete only the retired hostname's certificate: ```bash sudo certbot delete --cert-name portainer.example.com ``` **Verify:** `docker ps -a` should show that your unrelated application containers still exist, while the Portainer container is gone. Remove `portainer_data` only when intentional configuration loss is acceptable. ## Conclusion You now have Portainer CE installed on Ubuntu 24.04 as a Docker management UI with persistent configuration, localhost-only backend exposure, Nginx, trusted HTTPS, a verified LTS release, a working local Docker environment, a tested Compose stack workflow, configuration backup, update instructions, troubleshooting, and cleanup steps. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. Portainer can share a VM with other Docker workloads, but size the server for the applications and databases you actually run rather than for the dashboard alone. If you are building multi-container applications, continue with the [Docker Compose](/learn/tutorials/install-docker-compose-ubuntu-24-04) workflow or use [Gitea with Docker Compose](/learn/tutorials/deploy-gitea-ubuntu-24-04) as a more complete self-hosted application example. --- ### How to Install fail2ban on Ubuntu 24.04 for SSH Protection URL: https://rafftechnologies.com/learn/tutorials/install-fail2ban-ubuntu-24-04 Description: Install and configure fail2ban on Ubuntu 24.04 for SSH brute-force protection with systemd journal monitoring, safe ban testing, tuning, and rollback. fail2ban monitors authentication events and temporarily blocks source IP addresses that repeatedly match failure patterns. On an internet-facing Ubuntu server, it is useful as an additional SSH protection layer alongside SSH keys, restricted firewall rules, timely updates, and disabled password authentication where practical. In this tutorial, you will install fail2ban on a Raff Linux VM running Ubuntu 24.04, enable the SSH jail, use the systemd journal backend, tune retry and ban windows, validate the configuration, test a ban without locking yourself out, inspect logs, and cleanly roll the setup back if needed. Ubuntu 24.04 provides fail2ban 1.0.2 in the Noble package line. The package supports systemd journal monitoring and works with modern firewall backends including nftables. This guide does not claim that every public server receives a fixed number of attacks or that fail2ban eliminates brute-force traffic; actual login noise varies by IP, exposure, SSH configuration, and time. fail2ban reduces repeated attempts from matching sources, but it should not replace SSH key authentication or firewall access controls. You need Ubuntu 24.04, SSH access using a non-root sudo user, and preferably SSH key authentication already working before you change ban rules. ## Step 1 — Confirm Ubuntu and Your SSH Access Path Check the operating system: ```bash cat /etc/os-release ``` Confirm the SSH service is active: ```bash systemctl is-active ssh ``` Before changing fail2ban settings, keep your current SSH session open and confirm you can open a second SSH session from your normal workstation. This gives you a recovery path if you make a configuration mistake. If you have not configured SSH keys yet, follow [How to Set Up SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04) first. **Verify:** Ubuntu should report 24.04, the SSH service should be active, and a second SSH session should connect successfully before you continue. ## Step 2 — Install fail2ban from the Ubuntu Repository Update package metadata and install fail2ban: ```bash sudo apt update sudo apt install -y fail2ban ``` Check the installed package version: ```bash apt-cache policy fail2ban ``` Ubuntu 24.04's Noble package line uses fail2ban 1.0.2, with Ubuntu security and maintenance revisions applied through package updates. You can verify the current Ubuntu package at [packages.ubuntu.com](https://packages.ubuntu.com/noble/fail2ban). Enable fail2ban at boot: ```bash sudo systemctl enable fail2ban ``` Do not assume the SSH jail is enabled simply because the service package is installed; jails are disabled by default unless distribution or local configuration enables them. **Verify:** `fail2ban-client --version` should report Fail2Ban 1.0.2 on the standard Ubuntu 24.04 package line, and `systemctl is-enabled fail2ban` should report `enabled`. ## Step 3 — Create a Local SSH Jail Override Do not edit `/etc/fail2ban/jail.conf` directly. Upstream fail2ban recommends putting local overrides in `jail.local` or `.local` files under `/etc/fail2ban/jail.d/`, so package upgrades can update defaults without overwriting your custom settings. Create a dedicated SSH override: ```bash sudo nano /etc/fail2ban/jail.d/sshd.local ``` Add: ```ini [sshd] enabled = true backend = systemd port = ssh bantime = 1h findtime = 10m maxretry = 5 ``` The `systemd` backend reads authentication events from the journal. When this backend is used, do not add a `logpath` directive; fail2ban's systemd backend uses the filter's `journalmatch` instead. This avoids depending on `/var/log/auth.log` being present on every Ubuntu installation. If SSH listens on a custom port, replace `port = ssh` with the actual port number. **Verify:** Run `sudo cat /etc/fail2ban/jail.d/sshd.local` and confirm the jail is enabled, the backend is `systemd`, and the SSH port matches the server's real SSH listener. ## Step 4 — Decide Whether Any Administrative IP Should Be Ignored fail2ban can exclude trusted addresses with `ignoreip`, but only add addresses or networks that are stable and under your control. Whitelisting a temporary hotel, mobile, ISP, or shared office address can create an unintended bypass later if that address is reassigned. If you have a stable administrative IP or VPN subnet, add it to a `[DEFAULT]` override: ```bash sudo nano /etc/fail2ban/jail.d/00-local-defaults.local ``` For example: ```ini [DEFAULT] ignoreip = 127.0.0.1/8 ::1 203.0.113.10 ``` Replace `203.0.113.10` with a stable source you actually control, or omit it entirely if you do not have one. Check your current public source address from the workstation you use for SSH and compare it with any configured `ignoreip` entry before testing bans. **Verify:** Run `sudo fail2ban-client -d | grep -i ignoreip` after the configuration test in the next step and confirm only intended trusted addresses are excluded. ## Step 5 — Validate the Configuration Before Restarting Test the full fail2ban configuration: ```bash sudo fail2ban-client -t ``` A successful test should end without a configuration error. If it fails, inspect the local files you just created before restarting the service. You can also inspect the resolved configuration for the SSH jail: ```bash sudo fail2ban-client -d | grep -A 20 "'sshd'" ``` Do not restart fail2ban after a failed configuration test. **Verify:** `sudo fail2ban-client -t` should report that the configuration is OK. ## Step 6 — Start fail2ban and Confirm the SSH Jail Restart fail2ban so the local SSH jail is loaded: ```bash sudo systemctl restart fail2ban ``` Check the service: ```bash systemctl is-active fail2ban ``` List active jails: ```bash sudo fail2ban-client status ``` Then inspect SSH specifically: ```bash sudo fail2ban-client status sshd ``` The SSH jail status shows currently failed attempts, total failures, current bans, total bans, and the banned IP list. A new server may legitimately show zero bans. **Verify:** `systemctl is-active fail2ban` should return `active`, and `sudo fail2ban-client status` should list `sshd` as an active jail. ## Step 7 — Confirm fail2ban Is Reading SSH Journal Events Inspect the SSH journal directly: ```bash sudo journalctl -u ssh --since '30 minutes ago' --no-pager ``` Then check fail2ban's SSH jail: ```bash sudo fail2ban-client status sshd ``` Review fail2ban service logs: ```bash sudo journalctl -u fail2ban -n 100 --no-pager ``` The jail may show zero failed attempts if no matching authentication failures occurred during the observation window. That is not itself an error. If the SSH jail is active but never sees events that are visible in the SSH journal, check the backend and filter configuration before changing retry thresholds. **Verify:** The SSH jail should remain active without repeated backend or journal errors in the fail2ban service log. ## Step 8 — Test the Ban Action Without Locking Yourself Out Do not intentionally enter bad SSH passwords repeatedly from your only administrative connection. Instead, use fail2ban's manual ban command with a documentation-only test address that is not your own source IP: ```bash sudo fail2ban-client set sshd banip 198.51.100.25 ``` Check the jail: ```bash sudo fail2ban-client status sshd ``` The test address should appear in the banned IP list. On systems using nftables, inspect fail2ban-created rules or sets: ```bash sudo nft list ruleset | grep -i -A 8 f2b ``` Do not assume a fail2ban ban must appear as a permanent UFW rule. fail2ban's active action backend can manage its own firewall rules independently of the rules shown by `ufw status`. Remove the test ban: ```bash sudo fail2ban-client set sshd unbanip 198.51.100.25 ``` **Verify:** The test IP should appear while banned and disappear from `sudo fail2ban-client status sshd` after the unban command. ## Step 9 — Tune Ban Time and Retry Thresholds Conservatively The initial values in this guide are: ```ini bantime = 1h findtime = 10m maxretry = 5 ``` These mean that five matching failures within ten minutes trigger a one-hour ban. There is no universal ideal value. Shared administrator addresses, automation, monitoring systems, and users behind NAT can make aggressive thresholds more likely to block legitimate access. If repeated offenders are a problem, fail2ban supports incremental ban times. Add these settings under `[DEFAULT]` in `/etc/fail2ban/jail.d/00-local-defaults.local`: ```ini [DEFAULT] bantime.increment = true bantime.factor = 2 bantime.maxtime = 1d ``` After changing values, validate before restart: ```bash sudo fail2ban-client -t sudo systemctl restart fail2ban ``` **Verify:** `sudo fail2ban-client -t` should pass, and `sudo fail2ban-client get sshd bantime` should show the effective base ban duration in seconds. ## Step 10 — Manage Bans and Review Activity List SSH jail status: ```bash sudo fail2ban-client status sshd ``` Ban an address manually when there is a specific operational reason: ```bash sudo fail2ban-client set sshd banip 203.0.113.50 ``` Unban it: ```bash sudo fail2ban-client set sshd unbanip 203.0.113.50 ``` To inspect recent fail2ban activity through systemd: ```bash sudo journalctl -u fail2ban --since today --no-pager ``` Do not interpret raw ban counts as a security score. Higher or lower counts can result from IP exposure, scanning activity, logging configuration, retry thresholds, and whether password authentication is enabled. **Verify:** Manual ban and unban commands should change the SSH jail's banned IP list immediately. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to add fail2ban SSH protection as one layer of a hardened Ubuntu 24.04 server. ::: ## Step 11 — Harden SSH Beyond fail2ban fail2ban reacts to matching failures; it does not remove the underlying SSH authentication surface. For administrative servers, prioritize SSH keys and disable password authentication only after confirming key-based login works from a second session. Check effective SSH settings: ```bash sudo sshd -T | grep -E 'passwordauthentication|permitrootlogin|pubkeyauthentication' ``` If you change SSH configuration, validate it before reload: ```bash sudo sshd -t ``` Then reload SSH only after a successful validation: ```bash sudo systemctl reload ssh ``` Keep your existing session open until you confirm a new session works. Combine this with [UFW firewall rules](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) and the broader [Ubuntu server hardening](/learn/tutorials/secure-ubuntu-24-04-server) checklist. **Verify:** A new SSH session should authenticate successfully using the intended method after any SSH hardening change. ## Step 12 — Troubleshoot Common fail2ban Problems If fail2ban will not start, test configuration first: ```bash sudo fail2ban-client -t sudo journalctl -u fail2ban -n 100 --no-pager ``` If `sshd` does not appear in the jail list, confirm: ```bash sudo cat /etc/fail2ban/jail.d/sshd.local sudo fail2ban-client status ``` If the jail starts but does not detect SSH failures, confirm SSH events exist: ```bash sudo journalctl -u ssh --since '30 minutes ago' --no-pager ``` For a jail using `backend = systemd`, do not configure `logpath`; fail2ban's documentation states that `logpath` is not valid for the systemd backend because journal matching is used instead. If bans are created but connectivity is unaffected, inspect the active action and firewall rules rather than assuming UFW must contain the ban: ```bash sudo fail2ban-client get sshd actions sudo nft list ruleset | grep -i -A 8 f2b ``` **Verify:** Resolve configuration errors first, then confirm the service, jail, log source, and firewall action in that order. ## Step 13 — Run the Final End-to-End Verification Check the service and jail: ```bash systemctl is-active fail2ban sudo fail2ban-client status sudo fail2ban-client status sshd ``` Validate the configuration again: ```bash sudo fail2ban-client -t ``` Confirm SSH is healthy: ```bash systemctl is-active ssh sudo sshd -t ``` Review recent fail2ban errors: ```bash sudo journalctl -u fail2ban -p warning --since today --no-pager ``` If you want one final action test, repeat the documentation-address ban and immediately remove it: ```bash sudo fail2ban-client set sshd banip 198.51.100.25 sudo fail2ban-client status sshd sudo fail2ban-client set sshd unbanip 198.51.100.25 ``` **Verify:** fail2ban and SSH should both be active, the `sshd` jail should be loaded, configuration validation should pass, and the manual test ban/unban should work without affecting your administrator IP. ## Step 14 — Roll Back or Remove fail2ban Safely To disable only the custom SSH jail while keeping fail2ban installed, move the local override out of the active configuration path: ```bash sudo mv /etc/fail2ban/jail.d/sshd.local \ /etc/fail2ban/sshd.local.disabled sudo fail2ban-client -t sudo systemctl restart fail2ban ``` Confirm the SSH jail is gone: ```bash sudo fail2ban-client status ``` To stop fail2ban entirely: ```bash sudo fail2ban-client unban --all sudo systemctl disable --now fail2ban ``` If you intentionally want to remove the package and its configuration: ```bash sudo apt purge -y fail2ban sudo apt autoremove -y ``` Do not remove or weaken SSH key authentication or firewall rules merely because fail2ban has been removed; those controls solve different problems. **Verify:** After a full removal, `systemctl status fail2ban` should report that the unit is unavailable or inactive, while SSH access should continue to work through your existing SSH configuration. ## Conclusion You now have fail2ban protecting SSH on Ubuntu 24.04 with a dedicated local jail override, systemd journal monitoring, explicit retry and ban windows, configuration validation, safe ban testing, activity inspection, troubleshooting, and rollback instructions. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. Treat fail2ban as one layer in the server security model: use SSH keys, minimize public ports, keep packages updated, validate SSH changes before reload, and maintain a recovery path for administrative access. --- ### How to Install Caddy Web Server on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-caddy-ubuntu-24-04 Description: Install Caddy web server on Ubuntu 24.04, serve a static site, enable automatic HTTPS, validate the Caddyfile, troubleshoot TLS, and roll back safely. Caddy is a web server that can serve static sites and manage HTTPS automatically when you configure a qualifying public domain. In this tutorial, you will install Caddy on a Raff Linux VM running Ubuntu 24.04, serve a static website from `/var/www`, point a domain to the server, enable ports 80 and 443, validate the Caddyfile, verify automatic HTTPS, inspect certificate and service state, and safely roll the setup back if needed. This page focuses on installing Caddy as a web server for a static site. Raff has a separate tutorial for [using Caddy as a reverse proxy](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy), so the two workflows do not need to duplicate each other. Caddy's official Ubuntu package installs a systemd service named `caddy`, and Caddy's automatic HTTPS can obtain and renew publicly trusted certificates for qualifying domain names while redirecting HTTP traffic to HTTPS. See the [official Caddy installation documentation](https://caddyserver.com/docs/install) and [Automatic HTTPS documentation](https://caddyserver.com/docs/automatic-https) for the upstream behavior used here. You need Ubuntu 24.04, a domain or subdomain pointed to the VM's public IPv4 address, SSH access with sudo privileges, and ports 80 and 443 available for Caddy. ## Step 1 — Confirm Ubuntu, DNS, and Existing Web Services Check the operating system: ```bash cat /etc/os-release ``` Check whether another service is already listening on ports 80 or 443: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` Check your domain's current A record: ```bash dig +short A your-domain.com ``` Replace `your-domain.com` throughout this tutorial with the real hostname you plan to serve. If Nginx or Apache is already serving production traffic on this VM, do not stop it blindly. Decide whether Caddy will replace it, coexist on different ports, or be deployed on another server before continuing. **Verify:** Ubuntu should report 24.04, your domain should resolve to the intended public IPv4 address, and you should know whether ports 80 and 443 are already in use. ## Step 2 — Install Caddy from the Official Repository Caddy recommends using its official distribution package on supported production systems. Install the repository prerequisites: ```bash sudo apt update sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl ``` Add the official stable signing key: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \ sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg ``` Add the stable repository: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \ sudo tee /etc/apt/sources.list.d/caddy-stable.list ``` Make the APT files readable: ```bash sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list ``` Install Caddy: ```bash sudo apt update sudo apt install -y caddy ``` The official Debian/Ubuntu package starts Caddy as a systemd service automatically. **Verify:** Run `caddy version` and `systemctl is-active caddy`. The version command should return a Caddy v2 release and the service should report `active`. ## Step 3 — Allow SSH, HTTP, and HTTPS Through the Host Firewall If UFW is already active, inspect the current rules first: ```bash sudo ufw status numbered ``` Make sure your actual SSH port is allowed before enabling or changing the firewall. For a standard SSH service on port 22: ```bash sudo ufw allow OpenSSH ``` Allow standard web traffic: ```bash sudo ufw allow 80/tcp sudo ufw allow 443/tcp ``` If UFW is currently inactive and you intend to enable it, confirm SSH access is allowed first, then enable it: ```bash sudo ufw enable ``` For normal public automatic HTTPS, Caddy's documentation expects the server to be externally reachable on ports 80 and 443. Port 80 is also used for automatic HTTP-to-HTTPS redirects. **Verify:** `sudo ufw status` should show your SSH rule plus inbound access for TCP 80 and 443 without removing any rules required by other services. ## Step 4 — Create a Read-Only Static Site for the Caddy Service Caddy's systemd documentation recommends serving static files from locations such as `/srv` or `/var/www` rather than user home directories. Create the site directory with root ownership: ```bash sudo install -d -o root -g root -m 755 /var/www/caddy-demo ``` Create a simple test page: ```bash cat <<'EOF' | sudo tee /var/www/caddy-demo/index.html > /dev/null Caddy on Ubuntu 24.04

Caddy is serving this site

This page is being served from Ubuntu 24.04.

EOF ``` Set the file to a normal world-readable static-file mode: ```bash sudo chmod 644 /var/www/caddy-demo/index.html ``` There is no need to make the entire tree writable by the `caddy` service account or apply `chmod -R 755` to every file. The service only needs read and directory-traversal permission for this static site. **Verify:** Run `namei -l /var/www/caddy-demo/index.html` and confirm the `caddy` service can traverse the directories and read the file through normal directory `755` and file `644` permissions. ## Step 5 — Back Up and Write the Caddyfile Back up the packaged configuration before replacing it: ```bash sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak ``` Edit the active file: ```bash sudo nano /etc/caddy/Caddyfile ``` Use this configuration: ```caddyfile your-domain.com { root /var/www/caddy-demo encode zstd gzip file_server } ``` The `root` directive defines the site root and `file_server` enables static-file serving. `encode zstd gzip` enables response compression when supported by the client. Caddy's current documentation allows the simplified `root /path` syntax; older releases required `root * /path`, which is why older tutorials may show the wildcard form. **Verify:** Save the file and run `sudo caddy validate --config /etc/caddy/Caddyfile`. It should report a valid configuration before you reload the service. ## Step 6 — Format the Caddyfile and Reload Without Downtime Caddy can format the Caddyfile into its canonical style: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile ``` Validate again: ```bash sudo caddy validate --config /etc/caddy/Caddyfile ``` Reload the running systemd service: ```bash sudo systemctl reload caddy ``` Caddy's official service guidance recommends reloads for configuration changes instead of stopping the service, because a graceful reload avoids unnecessary downtime. Check recent service logs: ```bash sudo journalctl -u caddy -n 80 --no-pager ``` **Verify:** Configuration validation should succeed, `systemctl is-active caddy` should return `active`, and the recent journal should not show a repeating configuration or bind error. ## Step 7 — Verify Automatic HTTPS Test the HTTPS endpoint: ```bash curl -I https://your-domain.com ``` Then test the HTTP endpoint: ```bash curl -I http://your-domain.com ``` For a qualifying public hostname, Caddy automatically manages a trusted certificate and normally redirects HTTP to HTTPS. Certificate issuance can fail if DNS does not point to this server, ports 80/443 are unreachable, another service owns the ports, or the public CA cannot validate the hostname. ![caddy-ubuntu-24-04-01-https-static-site.webp](https://raff-images.s3.raffusercloud.com/caddy_ubuntu_24_04_01_https_static_site_webp_81a80245e5.png) **Verify:** The HTTPS request should return a successful HTTP response from your site, while the HTTP request should redirect to the HTTPS URL. ## Step 8 — Verify the Browser Certificate and Static Content Open: ```text https://your-domain.com ``` Confirm the test page loads and the browser reports a trusted HTTPS connection for the hostname. ![Caddy static website loading over HTTPS on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/caddy_ubuntu_24_04_02_browser_padlock_webp_05387b84ec.png) Check the exact page content from the terminal: ```bash curl -fsS https://your-domain.com | grep 'Caddy is serving this site' ``` **Verify:** The browser should show the expected hostname over trusted HTTPS, and the terminal command should return the test-page heading. ## Step 9 — Confirm Service, Ports, and Caddy Storage State Confirm Caddy is enabled at boot: ```bash systemctl is-enabled caddy ``` Check its listeners: ```bash sudo ss -lntp | grep -E ':(80|443)\b' ``` Check the service account: ```bash systemctl show caddy -p User -p Group ``` The packaged service runs as the `caddy` user and stores its application data, including certificate state, under the Caddy service user's data directory in `/var/lib/caddy`. Check that the data directory exists without printing private key material: ```bash sudo test -d /var/lib/caddy/.local/share/caddy && echo 'Caddy data directory present' ``` **Verify:** Caddy should be enabled, active, listening on the required web ports, running under the expected service account, and have its data directory present. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to install Caddy on Ubuntu 24.04 with automatic HTTPS for a static website. ::: ## Step 10 — Add a Second Static Site Safely To host another domain on the same Caddy service, first point that domain to the VM and create a separate document root: ```bash sudo install -d -o root -g root -m 755 /var/www/site-two printf '

Second Caddy site

\n' | \ sudo tee /var/www/site-two/index.html > /dev/null sudo chmod 644 /var/www/site-two/index.html ``` Add another site block to `/etc/caddy/Caddyfile`: ```caddyfile site-two.example.com { root /var/www/site-two file_server } ``` Format, validate, and reload: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo caddy validate --config /etc/caddy/Caddyfile sudo systemctl reload caddy ``` Each qualifying hostname can receive its own automatically managed certificate. **Verify:** `curl -fsS https://site-two.example.com` should return the second site's HTML after DNS and certificate issuance are ready. ## Step 11 — Troubleshoot Common Caddy Installation Problems If certificate issuance fails, check DNS: ```bash dig +short A your-domain.com ``` Check whether Caddy owns the web ports: ```bash sudo ss -lntp | grep -E ':(80|443)\b' ``` Check the firewall: ```bash sudo ufw status numbered ``` Check Caddy's journal: ```bash sudo journalctl -u caddy -n 120 --no-pager ``` If the site returns `403`, inspect path permissions instead of recursively making every file executable: ```bash namei -l /var/www/caddy-demo/index.html ls -l /var/www/caddy-demo/index.html ``` A typical static site can use directory mode `755` and regular file mode `644`, with root ownership, as long as Caddy can traverse the path and read the files. If Caddy fails after editing the configuration, validate it before another reload: ```bash sudo caddy validate --config /etc/caddy/Caddyfile ``` **Verify:** Identify whether the failure is DNS, port ownership, firewall, filesystem permission, or Caddyfile syntax before changing unrelated settings. ## Step 12 — Run the Final End-to-End Verification Check configuration and service state: ```bash sudo caddy validate --config /etc/caddy/Caddyfile systemctl is-active caddy systemctl is-enabled caddy ``` Check network listeners: ```bash sudo ss -lntp | grep -E ':(80|443)\b' ``` Check both HTTP paths: ```bash curl -I http://your-domain.com curl -I https://your-domain.com ``` Check the static page content: ```bash curl -fsS https://your-domain.com | grep 'Caddy is serving this site' ``` Review recent warnings or errors: ```bash sudo journalctl -u caddy -p warning --since today --no-pager ``` **Verify:** The Caddyfile should validate, the service should be active and enabled, ports 80 and 443 should be served by Caddy, HTTP should redirect to HTTPS, HTTPS should return the static page, and the journal should not show unresolved repeating errors. ## Step 13 — Roll Back or Remove the Demo Site If you want to keep Caddy but restore the original packaged configuration, validate the backup first: ```bash sudo caddy validate --config /etc/caddy/Caddyfile.bak ``` Then restore it and reload: ```bash sudo cp /etc/caddy/Caddyfile.bak /etc/caddy/Caddyfile sudo systemctl reload caddy ``` Remove only the demo content when it is no longer needed: ```bash sudo rm -rf /var/www/caddy-demo ``` If you intentionally want to uninstall Caddy completely: ```bash sudo systemctl disable --now caddy sudo apt purge -y caddy sudo apt autoremove -y ``` Before deleting `/var/lib/caddy`, remember that it contains Caddy-managed application state such as certificate data. Remove it only when you are intentionally decommissioning the service and do not need that state: ```bash sudo rm -rf /var/lib/caddy ``` Remove the repository files only if you no longer want the Caddy package source: ```bash sudo rm -f /etc/apt/sources.list.d/caddy-stable.list sudo rm -f /usr/share/keyrings/caddy-stable-archive-keyring.gpg ``` Remove firewall rules for 80/443 only if no remaining service on this VM needs them. **Verify:** If you restored the previous config, Caddy should remain active with that configuration. After a full uninstall, the Caddy service should no longer be active and your unrelated SSH/firewall access should remain intact. ## Conclusion You now have Caddy installed on Ubuntu 24.04 as a static web server with automatic HTTPS, a systemd-managed service, a validated Caddyfile, safe file permissions, HTTPS verification, multi-site expansion, troubleshooting, and rollback instructions. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. Size the VM for the application or sites you actually host rather than for Caddy alone. If your next goal is to put an application behind Caddy, continue with [How to Install Caddy on Ubuntu 24.04 as a Reverse Proxy](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy) instead of duplicating reverse-proxy configuration on this page. --- ### How to Deploy a Multi-Container App with Docker Compose on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-multi-container-docker-compose-ubuntu-24-04 Description: Deploy a multi-container Docker Compose app on Ubuntu 24.04 with Node.js, PostgreSQL, Redis, secrets, health checks, private networking, backups, and persistence. Docker Compose lets you define a multi-container application in one `compose.yaml` file and manage the stack with commands such as `docker compose up`, `docker compose ps`, and `docker compose down`. In this tutorial, you will deploy a small Node.js API with PostgreSQL and Redis on a Raff Linux VM running Ubuntu 24.04. The database and cache stay on the internal Compose network, PostgreSQL uses a named volume for persistent data, the database password is mounted as a Compose secret instead of being hardcoded in YAML, and the application port is bound to localhost rather than exposed directly to the internet. This tutorial focuses on a single-host Docker Compose deployment. Docker's current documentation supports health-check-aware startup ordering through `depends_on` with `condition: service_healthy`, named volumes for persistent state, and the Compose plugin through the `docker compose` command. Docker also recommends using secrets rather than ordinary environment variables for sensitive values. See the [Docker Compose plugin installation guide](https://docs.docker.com/compose/install/linux/), [startup-order documentation](https://docs.docker.com/compose/how-tos/startup-order/), and [environment-variable guidance](https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/) for the upstream behavior used here. You need Ubuntu 24.04, Docker Engine with the Compose plugin, SSH access with sudo privileges, and enough capacity for the application, PostgreSQL, and Redis you intend to run. ## Step 1 — Verify Docker Engine and the Compose Plugin Confirm Docker and Compose are installed: ```bash docker --version docker compose version ``` If `docker compose` is missing but Docker Engine is already installed from Docker's official repository, install the plugin: ```bash sudo apt update sudo apt install -y docker-compose-plugin ``` Docker's current Linux documentation treats `docker compose` as the supported plugin command. The old standalone `docker-compose` installation is retained only for backward compatibility. If Docker Engine itself is not installed, follow [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) instead of mixing package sources. **Verify:** `docker info` should complete successfully and `docker compose version` should report an installed Compose plugin. ## Step 2 — Create the Project and Secret Directories Create a project directory: ```bash mkdir -p ~/task-api/src ~/task-api/secrets cd ~/task-api ``` Generate a random PostgreSQL password directly into a local secret file: ```bash openssl rand -hex 32 > secrets/postgres_password chmod 600 secrets/postgres_password ``` Prevent local secret material from being committed to Git: ```bash cat > .gitignore <<'EOF' secrets/ .env EOF ``` Do not paste the generated password into `compose.yaml`, shell history, screenshots, or support tickets. **Verify:** `stat -c '%a %n' secrets/postgres_password` should show mode `600`, and `wc -c secrets/postgres_password` should confirm the file is non-empty without printing the secret. ## Step 3 — Create the Node.js API Create the application package file: ```bash cat > src/package.json <<'EOF' { "name": "compose-task-api", "version": "1.0.0", "private": true, "main": "index.js", "dependencies": { "express": "^4.21.0", "pg": "^8.13.0", "redis": "^4.7.0" } } EOF ``` Create the API: ```bash cat > src/index.js <<'EOF' const fs = require('fs'); const express = require('express'); const { Pool } = require('pg'); const { createClient } = require('redis'); const app = express(); app.use(express.json()); const dbPassword = fs.readFileSync( process.env.POSTGRES_PASSWORD_FILE || '/run/secrets/postgres_password', 'utf8' ).trim(); const pool = new Pool({ host: process.env.POSTGRES_HOST || 'db', port: 5432, user: process.env.POSTGRES_USER || 'taskuser', password: dbPassword, database: process.env.POSTGRES_DB || 'taskdb' }); const redis = createClient({ url: `redis://${process.env.REDIS_HOST || 'cache'}:6379` }); redis.on('error', (err) => console.error('Redis error:', err.message)); app.get('/health', async (req, res) => { try { await pool.query('SELECT 1'); await redis.ping(); res.json({ status: 'ok' }); } catch (err) { res.status(503).json({ status: 'error' }); } }); app.get('/tasks', async (req, res) => { const cached = await redis.get('tasks'); if (cached) return res.json(JSON.parse(cached)); const { rows } = await pool.query( 'SELECT id, title, done, created_at FROM tasks ORDER BY id DESC' ); await redis.setEx('tasks', 30, JSON.stringify(rows)); res.json(rows); }); app.post('/tasks', async (req, res) => { const title = String(req.body.title || '').trim(); if (!title || title.length > 255) { return res.status(400).json({ error: 'title must contain 1-255 characters' }); } const { rows } = await pool.query( 'INSERT INTO tasks (title) VALUES ($1) RETURNING id, title, done, created_at', [title] ); await redis.del('tasks'); res.status(201).json(rows[0]); }); async function start() { await redis.connect(); await pool.query(` CREATE TABLE IF NOT EXISTS tasks ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, done BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ) `); app.listen(3000, '0.0.0.0', () => { console.log('Task API listening on port 3000'); }); } start().catch((err) => { console.error(err); process.exit(1); }); EOF ``` The API verifies both PostgreSQL and Redis on `/health`, uses parameterized SQL for task creation, and reads the database password from a mounted secret file. **Verify:** Run `node --check src/index.js` if Node.js is installed on the host. If it is not, continue to the container build and use the container logs as the syntax/runtime check. ## Step 4 — Create the Application Dockerfile Create `src/Dockerfile`: ```bash cat > src/Dockerfile <<'EOF' FROM node:22-slim WORKDIR /app COPY package.json ./ RUN npm install --omit=dev && npm cache clean --force COPY index.js ./ EXPOSE 3000 USER node CMD ["node", "index.js"] EOF ``` The application runs as the image's non-root `node` user. The Dockerfile does not copy your project-level `secrets/` directory into the image. Create a Docker build ignore file: ```bash cat > src/.dockerignore <<'EOF' node_modules npm-debug.log EOF ``` **Verify:** Run `docker build -t task-api-check ./src`. The image build should finish successfully without copying secret files into the build context. ## Step 5 — Define the Multi-Container Compose Stack Create `compose.yaml`: ```bash cat > compose.yaml <<'EOF' services: app: build: ./src restart: unless-stopped environment: POSTGRES_HOST: db POSTGRES_USER: taskuser POSTGRES_DB: taskdb POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password REDIS_HOST: cache secrets: - postgres_password ports: - "127.0.0.1:3000:3000" depends_on: db: condition: service_healthy restart: true cache: condition: service_healthy restart: true networks: - backend db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: taskuser POSTGRES_DB: taskdb POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password secrets: - postgres_password volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U taskuser -d taskdb"] interval: 10s timeout: 5s retries: 5 start_period: 20s networks: - backend cache: image: redis:7-alpine restart: unless-stopped command: ["redis-server", "--appendonly", "yes"] volumes: - redisdata:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - backend secrets: postgres_password: file: ./secrets/postgres_password volumes: pgdata: redisdata: networks: backend: driver: bridge EOF ``` The database and Redis services have no `ports` section, so they are not published on the host. The API is published only on `127.0.0.1:3000`. Docker Compose waits for the PostgreSQL and Redis health checks because both dependencies use `condition: service_healthy`. **Verify:** Run `docker compose config -q` and `docker compose config --services`. Validation should pass and the service list should contain `app`, `db`, and `cache`. ## Step 6 — Start the Stack and Wait for Healthy Dependencies Build and start the application: ```bash cd ~/task-api docker compose up -d --build ``` Check the containers: ```bash docker compose ps ``` Review the application logs: ```bash docker compose logs --tail=100 app ``` Compose starts dependencies in order, but simple startup ordering alone does not mean a database is ready to accept connections. The health checks in this tutorial provide the readiness condition before the app is started. **Verify:** PostgreSQL and Redis should report healthy status, the app should be running, and the app log should contain `Task API listening on port 3000` without a repeating database or Redis connection error. ## Step 7 — Test the Application End to End Check the health endpoint from the VM: ```bash curl -fsS http://127.0.0.1:3000/health ``` Expected result: ```json {"status":"ok"} ``` Create a task: ```bash curl -fsS -X POST http://127.0.0.1:3000/tasks \ -H 'Content-Type: application/json' \ -d '{"title":"Deploy with Docker Compose"}' ``` Retrieve tasks: ```bash curl -fsS http://127.0.0.1:3000/tasks ``` The request path now exercises the application container, PostgreSQL service, Redis service, Compose network, secret mount, and database volume together. **Verify:** `/health` should return `status: ok`, the POST should return the created task, and the GET should return that task. ## Step 8 — Confirm Internal Services Are Not Published Publicly List listening host ports: ```bash sudo ss -lntp | grep -E ':(3000|5432|6379)\b' || true ``` Only the API's localhost mapping should appear: ```text 127.0.0.1:3000 ``` PostgreSQL port 5432 and Redis port 6379 should not be listening on the host merely because the containers use those ports internally. Inspect Compose port mappings: ```bash docker compose ps ``` For a public application, place Nginx or Caddy in front of `127.0.0.1:3000` and terminate HTTPS there instead of changing the API mapping to `0.0.0.0:3000`. See [How to Install Caddy on Ubuntu 24.04 as a Reverse Proxy](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy) or [How to Secure Nginx with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). **Verify:** The host should not expose 5432 or 6379, and port 3000 should remain bound to `127.0.0.1`. ## Step 9 — Inspect Logs, Health, and Resource Usage Check service state: ```bash docker compose ps ``` View recent logs without following indefinitely: ```bash docker compose logs --tail=100 app docker compose logs --tail=100 db docker compose logs --tail=100 cache ``` View a current resource snapshot: ```bash docker compose stats --no-stream ``` Treat the output as a measurement of your current workload, not as a universal sizing rule. CPU and memory use vary with image versions, database state, traffic, query patterns, and application behavior. **Verify:** Services should remain running, PostgreSQL and Redis should remain healthy, and logs should not show unresolved repeating errors. :::cta Deploy Your Server Deploy a Raff Linux VM and use this tutorial to run a multi-container Docker Compose application with persistent data and private service networking. ::: ## Step 10 — Verify Named-Volume Persistence Create another task: ```bash curl -fsS -X POST http://127.0.0.1:3000/tasks \ -H 'Content-Type: application/json' \ -d '{"title":"Persistence test"}' ``` Remove the containers and Compose network without deleting volumes: ```bash docker compose down ``` Confirm the project volumes still exist: ```bash docker volume ls | grep -E 'pgdata|redisdata' ``` Recreate the stack: ```bash docker compose up -d ``` Wait for the health checks, then query the API: ```bash curl -fsS http://127.0.0.1:3000/tasks ``` A normal `docker compose down` does not delete named volumes. `docker compose down -v` does. **Verify:** The `Persistence test` task should still exist after the containers are recreated. ## Step 11 — Back Up PostgreSQL Before Updates or Destructive Changes Create a protected backup directory: ```bash mkdir -p ~/task-api/backups chmod 700 ~/task-api/backups ``` Create a PostgreSQL dump: ```bash cd ~/task-api docker compose exec -T db \ pg_dump -U taskuser -d taskdb \ > "backups/taskdb-$(date +%F-%H%M%S).sql" ``` Check that the file exists and is non-empty: ```bash ls -lh backups/ test -s "$(ls -1t backups/taskdb-*.sql | head -n 1)" && echo 'Database dump is non-empty' ``` A backup stored only on the same VM is not a complete disaster-recovery plan. Copy production backups to separate protected storage and test restore procedures before relying on them. **Verify:** A timestamped, non-empty SQL dump should exist before you perform an update or any command that may delete data. ## Step 12 — Update the Stack with a Controlled Recreate Before changing image tags or application code, create a fresh backup and review the relevant release notes. Pull service images: ```bash docker compose pull db cache ``` Rebuild the application image and recreate changed services: ```bash docker compose up -d --build ``` Check state and logs: ```bash docker compose ps docker compose logs --tail=100 app ``` Do not upgrade PostgreSQL to a new major version by simply changing `postgres:16-alpine` to another major tag while reusing the same data directory. PostgreSQL major-version upgrades require an appropriate upgrade or dump-and-restore procedure. **Verify:** The expected containers should be running after the recreate, the dependencies should be healthy, and `/health` should return `status: ok`. ## Step 13 — Troubleshoot Common Docker Compose Failures If Compose rejects the YAML, validate it: ```bash docker compose config -q ``` If the application exits, inspect its logs and dependency health: ```bash docker compose ps docker compose logs --tail=150 app docker compose logs --tail=150 db docker compose logs --tail=150 cache ``` If PostgreSQL never becomes healthy, check readiness directly: ```bash docker compose exec -T db pg_isready -U taskuser -d taskdb ``` If Redis is unhealthy: ```bash docker compose exec -T cache redis-cli ping ``` If the application cannot read the database secret, confirm the secret is mounted without printing it: ```bash docker compose exec -T app sh -lc 'test -s /run/secrets/postgres_password && echo secret-mounted' ``` If port 3000 cannot bind, identify the current listener: ```bash sudo ss -lntp | grep ':3000' ``` **Verify:** Fix one layer at a time in this order: Compose validation, dependency health, secret mount, application logs, then host port binding. ## Step 14 — Run the Final End-to-End Verification and Clean Up Safely Run the final checks: ```bash cd ~/task-api docker compose config -q docker compose ps curl -fsS http://127.0.0.1:3000/health curl -fsS http://127.0.0.1:3000/tasks sudo ss -lntp | grep -E ':(3000|5432|6379)\b' || true ls -lh backups/ ``` The deployment is complete when the Compose file validates, dependencies are healthy, the API can read PostgreSQL and Redis, data survives a normal container recreate, and only the intended localhost API port is published. To stop the application while keeping data: ```bash docker compose down ``` To restart later: ```bash docker compose up -d ``` Only use the following destructive command when you intentionally want to delete the project's named volumes and have verified any backups you need: ```bash docker compose down -v ``` Remove the project files only after confirming they are no longer needed: ```bash rm -rf ~/task-api ``` **Verify:** After a normal `down`, the named volumes should remain. After an intentional `down -v`, the Compose project volumes should be removed. ## Conclusion You now have a multi-container Docker Compose application running on Ubuntu 24.04 with a Node.js API, PostgreSQL, Redis, health-check-aware dependency startup, a mounted database secret, private service networking, named-volume persistence, backup steps, troubleshooting, and cleanup instructions. Raff [Linux VM](/products/linux-vm) plans start at $4.99 per month. Choose VM capacity from actual application, database, cache, traffic, and storage measurements rather than a fixed Compose-specific size. Docker Compose is a practical fit for single-host deployments; when your architecture requires scheduling workloads across multiple nodes, evaluate an orchestrator such as [Managed Kubernetes](/products/kubernetes) instead. --- ### How to Use Raff S3-Compatible Object Storage with AWS CLI URL: https://rafftechnologies.com/learn/tutorials/raff-s3-object-storage-aws-cli Description: Use AWS CLI with Raff S3-compatible object storage on Ubuntu 24.04. Configure scoped credentials, transfer files, sync safely, and create presigned URLs. Raff Object Storage exposes an S3-compatible API, so you can use the AWS CLI for bucket operations, uploads, downloads, directory syncs, and presigned URLs by pointing commands at `https://s3.raffusercloud.com`. In this tutorial, you will configure a dedicated AWS CLI profile, use a bucket-scoped access key where possible, create and verify a bucket, transfer files, test a safe sync workflow, create a temporary download URL, and clean up test objects without exposing credentials. This tutorial targets Raff's current Object Storage feature set. Standard object operations, multipart uploads, presigned URLs, bucket policies and ACLs, and SigV4 authentication are supported. Versioning, lifecycle rules, Object Lock, cross-region replication, and static website hosting are not currently supported, so this guide does not depend on those features. See [Raff Object Storage](/products/object-storage) for the current compatibility and pricing matrix. AWS documents `--endpoint-url` as the option for overriding a service endpoint, and its current `aws s3` commands include `cp`, `ls`, `mb`, `rm`, `rb`, `sync`, and `presign`. AWS CLI v2 also requires an explicit signing region for presigned URLs. This tutorial uses the existing Raff-compatible signing value `us-east-1` and the Raff endpoint on every S3 command. ## Step 1 — Install and Verify AWS CLI v2 On Ubuntu 24.04, install the utilities needed for the official AWS CLI v2 installer: ```bash sudo apt update sudo apt install -y curl unzip ``` Download and install the current AWS CLI v2 package for x86_64 Linux: ```bash curl -fsSLo awscliv2.zip \ https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip unzip -q awscliv2.zip sudo ./aws/install rm -rf aws awscliv2.zip ``` If your VM uses ARM64, use AWS's ARM64 package instead of the x86_64 archive. AWS also provides a current install script and Snap package; follow the [official AWS CLI installation documentation](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) if you need another architecture or update method. **Verify:** ```bash aws --version ``` The command should report AWS CLI `2.x` and exit without an error. ## Step 2 — Create a Scoped Raff Object Storage Access Key Open the Raff dashboard and go to **Object Storage**. Create or select the bucket you want this CLI profile to access, then create an access key with the narrowest permissions your workflow needs. For an upload/download workflow, prefer a key limited to the intended bucket with read-write access instead of sharing a full-access key across multiple applications. Raff currently supports bucket-scoped read and read-write grants for access keys. Record the access key ID and secret access key in a password manager when the secret is shown. Do not paste the secret into Git, source code, screenshots, shell scripts, tickets, or chat messages. **Verify:** You should have the endpoint `https://s3.raffusercloud.com`, an access key ID, a secret access key, and the name of the bucket or permission to create one. ## Step 3 — Configure a Dedicated AWS CLI Profile Set a restrictive shell umask before creating the credential files: ```bash umask 077 aws configure --profile raff ``` Enter: ```text AWS Access Key ID: YOUR_RAFF_ACCESS_KEY AWS Secret Access Key: YOUR_RAFF_SECRET_KEY Default region name: us-east-1 Default output format: json ``` AWS CLI stores profile credentials under `~/.aws/credentials` and non-secret profile settings under `~/.aws/config`. These files contain sensitive material and should only be readable by your user. Enforce restrictive permissions: ```bash chmod 700 ~/.aws chmod 600 ~/.aws/credentials ~/.aws/config ``` Do not print the credential file contents as a verification step. Instead, check the profile exists: ```bash aws configure list --profile raff ``` **Verify:** The profile should show a configured access key source and `us-east-1` region without displaying the full secret key. ## Step 4 — Test Authentication Against the Raff S3 Endpoint List buckets using Raff's custom endpoint: ```bash aws s3 ls \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` If the scoped key can only access a specific bucket, a global bucket listing may be restricted. In that case, test the intended bucket directly: ```bash aws s3 ls s3://YOUR_BUCKET_NAME/ \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` An empty bucket can produce no object lines while still returning successfully. **Verify:** The command should complete without an authentication or signature error. A permission-denied response is only acceptable when the key is intentionally scoped away from the attempted operation. ## Step 5 — Create a Bucket When Your Key Allows It Skip this step if you already have a bucket or your key is intentionally limited to an existing bucket. Choose a bucket name using lowercase letters, numbers, and hyphens. Avoid sensitive information in bucket names and avoid periods for better compatibility with HTTPS virtual-hosted addressing. Create the bucket: ```bash BUCKET="my-project-files-$(date +%Y%m%d)" aws s3 mb "s3://$BUCKET" \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` AWS's general S3 naming guidance uses 3-63 characters, lowercase letters, numbers, periods, and hyphens, with names beginning and ending in a letter or number. Raff may enforce its own namespace availability, so use a name that is unlikely to collide. **Verify:** ```bash aws s3 ls "s3://$BUCKET/" \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` The command should return successfully, even if the new bucket is empty. ## Step 6 — Upload, List, Download, and Compare an Object Create a small test object: ```bash printf 'Raff Object Storage verification\n' > /tmp/raff-s3-test.txt ``` Upload it: ```bash aws s3 cp /tmp/raff-s3-test.txt "s3://$BUCKET/raff-s3-test.txt" \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` List the object: ```bash aws s3 ls "s3://$BUCKET/raff-s3-test.txt" \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` Download it to a different local path: ```bash aws s3 cp "s3://$BUCKET/raff-s3-test.txt" /tmp/raff-s3-downloaded.txt \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` Compare the files locally: ```bash cmp /tmp/raff-s3-test.txt /tmp/raff-s3-downloaded.txt \ && echo 'Upload/download verification passed' ``` **Verify:** The `cmp` command should print `Upload/download verification passed`. ## Step 7 — Sync a Directory Safely with a Dry Run First Create a small local directory: ```bash mkdir -p ~/raff-s3-sync-demo printf 'alpha\n' > ~/raff-s3-sync-demo/a.txt printf 'beta\n' > ~/raff-s3-sync-demo/b.txt ``` Preview the sync before transferring anything: ```bash aws s3 sync ~/raff-s3-sync-demo/ "s3://$BUCKET/sync-demo/" \ --dryrun \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` If the preview is correct, run the sync: ```bash aws s3 sync ~/raff-s3-sync-demo/ "s3://$BUCKET/sync-demo/" \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` AWS documents `sync` as recursively copying new and updated files from source to destination. Do not add `--delete` casually: that option can delete destination objects that no longer exist in the source. Also note that a sync is not a versioned backup. Raff Object Storage does not currently support object versioning, so overwriting the same key does not provide a built-in object-history recovery mechanism. **Verify:** ```bash aws s3 ls "s3://$BUCKET/sync-demo/" \ --recursive \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1 ``` Both `a.txt` and `b.txt` should appear. ## Step 8 — Generate a Temporary Presigned Download URL Generate a one-hour presigned URL for the test object: ```bash PRESIGNED_URL="$(aws s3 presign "s3://$BUCKET/raff-s3-test.txt" \ --expires-in 3600 \ --endpoint-url https://s3.raffusercloud.com \ --profile raff \ --region us-east-1)" ``` AWS CLI currently supports presigned expiry values up to 604800 seconds, or seven days. Anyone who has a valid presigned URL can use it until it expires, so treat the URL like a temporary bearer credential. Test it without printing the full URL into shared logs: ```bash curl -fsS "$PRESIGNED_URL" -o /tmp/raff-s3-presigned.txt cmp /tmp/raff-s3-test.txt /tmp/raff-s3-presigned.txt \ && echo 'Presigned URL verification passed' ``` Unset the shell variable after the test: ```bash unset PRESIGNED_URL ``` **Verify:** The comparison should print `Presigned URL verification passed`. :::cta Explore Object Storage Create a Raff Object Storage bucket and connect your existing S3 tooling to `s3.raffusercloud.com`. ::: ## Step 9 — Use Public Read Only for Intentionally Public Objects Raff currently supports bucket policies and public-read access, but it does not currently support S3 static website hosting. Public-read should therefore be used only when the underlying objects are intentionally public, such as downloadable assets. Create a policy only for a bucket dedicated to public content. Replace `YOUR_PUBLIC_BUCKET` before running these commands: ```bash PUBLIC_BUCKET="YOUR_PUBLIC_BUCKET" cat > /tmp/raff-public-read-policy.json < /srv/myapp/app.js <<'EOF' const express = require('express'); const app = express(); const host = '127.0.0.1'; const port = Number(process.env.PORT || 3000); app.get('/', (req, res) => { res.json({ message: 'Node.js is running under PM2', pid: process.pid, }); }); app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', pid: process.pid }); }); const server = app.listen(port, host, () => { console.log(`Listening on http://${host}:${port}`); if (process.send) process.send('ready'); }); function shutdown(signal) { console.log(`${signal} received; closing HTTP server`); const forceExit = setTimeout(() => { console.error('Graceful shutdown timed out'); process.exit(1); }, 8000); forceExit.unref(); server.close((error) => { clearTimeout(forceExit); if (error) { console.error(error); process.exit(1); } process.exit(0); }); } process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM')); EOF ``` PM2's graceful-shutdown guidance recommends handling the stop signal, stopping new connections, finishing active work, closing external resources, and then exiting. In a real application, add database, queue, or cache cleanup before `process.exit(0)`. **Verify:** ```bash node --check /srv/myapp/app.js ``` The command should exit with no syntax error. ## Step 4 — Test the Node.js App Before Adding PM2 Start the application in the foreground: ```bash cd /srv/myapp NODE_ENV=production PORT=3000 node app.js ``` In a second SSH session, test both routes: ```bash curl -fsS http://127.0.0.1:3000/ curl -fsS http://127.0.0.1:3000/health ``` Check the listening address: ```bash ss -lntp | grep ':3000' ``` The listener should be on `127.0.0.1:3000`, not `0.0.0.0:3000` or `[::]:3000`. Return to the first session and press `Ctrl+C`. The app should log that it received `SIGINT` and exit. **Verify:** Both local requests should succeed, the health route should return `"status":"ok"`, and port 3000 should be loopback-only. ## Step 5 — Install PM2 on Ubuntu 24.04 If Node.js was installed system-wide with the NodeSource method from the Raff Node.js tutorial, install PM2 globally with: ```bash sudo npm install -g pm2 ``` If your Node.js runtime is managed by nvm under your user account, run the same npm command without `sudo`: ```bash npm install -g pm2 ``` Do not mix a system-wide Node.js runtime and an nvm-managed PM2 installation unless you deliberately manage both paths. Verify PM2: ```bash pm2 --version command -v pm2 ``` If an existing application already has a `start` script in `package.json`, PM2 can run that npm script directly: ```bash pm2 start npm --name myapp -- start ``` For this tutorial we continue with an ecosystem file because it keeps the worker count, readiness, restart, and environment settings together. **Verify:** `pm2 --version` should return a version number and `command -v pm2` should resolve to the installation associated with your intended Node.js runtime. ## Step 6 — Create a PM2 Ecosystem File for the Tested 2 vCPU Setup Create the PM2 configuration: ```bash cat > /srv/myapp/ecosystem.config.js <<'EOF' module.exports = { apps: [ { name: 'myapp', script: './app.js', cwd: '/srv/myapp', instances: 2, exec_mode: 'cluster', wait_ready: true, listen_timeout: 10000, kill_timeout: 10000, restart_delay: 1000, watch: false, merge_logs: true, env: { NODE_ENV: 'production', PORT: 3000, }, }, ], }; EOF ``` The tested Raff VM has 2 vCPU, so this example uses two workers explicitly instead of `instances: 'max'`. On a 1 vCPU VM, set `instances: 1`. On larger machines, increase workers only after measuring your application and confirming that it is stateless. Do not put secrets in this ecosystem file if it is committed to source control. Use your deployment's secret-management method or a restrictive runtime configuration file that is excluded from Git. PM2's ecosystem-file reference documents `instances`, `exec_mode`, `wait_ready`, `listen_timeout`, `kill_timeout`, and restart controls. The combination here lets PM2 wait for the app's explicit `ready` message and gives the app time to finish requests during a reload. **Verify:** ```bash node --check /srv/myapp/ecosystem.config.js ``` The configuration should pass Node.js syntax validation. ## Step 7 — Run Node.js with PM2 Cluster Mode Start the ecosystem configuration: ```bash cd /srv/myapp pm2 start ecosystem.config.js ``` Check status: ```bash pm2 status pm2 describe myapp ``` Make several local requests: ```bash for i in 1 2 3 4 5 6; do curl -fsS http://127.0.0.1:3000/health echo done ``` On the tested 2-worker setup, the responses should normally show more than one process ID over repeated requests. Do not depend on a strict alternating order. If your application stores sessions or other state in process memory, do not enable multiple workers until that state has been moved to a shared store. **Verify:** `pm2 status` should show two `myapp` instances online on the tested 2 vCPU setup, and repeated health requests should succeed. ## Step 8 — Configure PM2 to Restore the App After Reboot Generate the startup hook as your normal deployment user: ```bash pm2 startup systemd ``` PM2 prints a `sudo` command containing the correct user, home directory, PM2 path, and Node.js path. Copy and run the exact command PM2 prints rather than copying a path from another server. Save the current process list: ```bash pm2 save ``` PM2's startup documentation uses the saved process list to resurrect applications after boot. Check the generated service: ```bash sudo systemctl is-enabled "pm2-$USER" sudo systemctl status "pm2-$USER" --no-pager ``` If you later change an nvm-managed Node.js version, PM2 recommends regenerating the startup hook because the Node.js path embedded in the service can change. **Verify:** The `pm2-$USER` service should be enabled, and `pm2 save` should complete successfully. ## Step 9 — Put Nginx in Front of the Private Node.js Port Install Nginx if it is not already present: ```bash sudo apt update sudo apt install -y nginx ``` Create a server block. Replace `your-domain.com` with your domain or the server address you use for testing: ```bash sudo tee /etc/nginx/sites-available/myapp > /dev/null <<'EOF' server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 60s; } } EOF ``` PM2 and Nginx solve different problems. PM2 keeps the Node.js process running and manages its workers; Nginx owns the public HTTP/HTTPS edge and proxies requests to the private application port. Using both keeps process management separate from public web traffic. Enable the site and validate Nginx before reloading: ```bash sudo ln -sfn /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp sudo nginx -t sudo systemctl reload nginx ``` For HTTPS, continue with [Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04) after the HTTP proxy works. **Verify:** ```bash curl -fsS http://your-domain.com/health ``` The response should contain `"status":"ok"`. ## Step 10 — Confirm the Node.js Port Is Not Publicly Exposed Check the local listener again: ```bash ss -lntp | grep ':3000' ``` Expected listening address: ```text 127.0.0.1:3000 ``` Do not add a firewall rule that exposes TCP 3000 to the internet when Nginx is the intended public entry point. Only Nginx needs to accept public HTTP/HTTPS traffic for this architecture. You can also test locally that Nginx and the app are separate layers: ```bash curl -fsS http://127.0.0.1:3000/health curl -fsS http://your-domain.com/health ``` **Verify:** Both requests should succeed, while `ss` should still show the application itself bound only to `127.0.0.1:3000`. ## Step 11 — Test a Rolling Reload and Graceful Shutdown PM2 cluster mode supports rolling reloads for HTTP applications: ```bash pm2 reload myapp ``` Watch the application state: ```bash pm2 status pm2 logs myapp --lines 30 ``` The app's signal handler should allow active HTTP connections to finish before the worker exits. PM2's current cluster documentation states that `reload` keeps workers available one by one, but also notes that a failed reload can fall back to a normal restart. Treat reloads as a safer deployment mechanism, not as an unconditional availability guarantee. For applications with database or queue connections, close those resources inside the shutdown handler before exiting. **Verify:** The app should remain online after `pm2 reload myapp`, and a new request should succeed: ```bash curl -fsS http://127.0.0.1:3000/health ``` ## Step 12 — Check Logs, Restarts, and Runtime State Inspect the PM2 process details: ```bash pm2 status pm2 describe myapp ``` View recent logs without leaving a long-running terminal session: ```bash pm2 logs myapp --lines 50 --nostream ``` For interactive CPU and memory observation: ```bash pm2 monit ``` Exit the monitor when finished. Use the measurements from your own workload to decide worker count, memory thresholds, and VM sizing; this tutorial does not assume a universal requests-per-second or latency figure for Node.js applications. **Verify:** Both workers should remain online on the tested setup, restart counts should be understandable from your deployment actions, and recent logs should not show crash loops or binding errors. :::cta Deploy Your Server Launch a Raff Linux VM and use this tutorial to run a Node.js application behind PM2 and Nginx. ::: ## Step 13 — Run the Final End-to-End Verification Run the complete verification set: ```bash node --version pm2 --version pm2 status sudo systemctl is-enabled "pm2-$USER" sudo nginx -t ss -lntp | grep ':3000' curl -fsS http://127.0.0.1:3000/health curl -fsS http://your-domain.com/health ``` The deployment is complete when Node.js 24 LTS is active, PM2 shows the intended worker count online, the PM2 systemd startup unit is enabled, Nginx configuration is valid, the application listens only on loopback, and both the direct local health check and Nginx-proxied health check succeed. If you want to verify reboot recovery, schedule an appropriate maintenance window and reboot the VM. After reconnecting, run `pm2 status` and the health checks again rather than rebooting a production server casually during deployment. **Verify:** Every command above should complete successfully, and the Node.js listener must remain `127.0.0.1:3000`. ## Step 14 — Clean Up or Roll Back Safely If this was only a test deployment, remove the application from PM2 first: ```bash pm2 delete myapp ``` If other PM2 applications still run on the VM, save the remaining process list: ```bash pm2 save ``` If `myapp` was the last PM2 application and you intentionally want an empty resurrect list, PM2's startup documentation provides: ```bash pm2 cleardump ``` Remove the Nginx site and reload Nginx: ```bash sudo rm -f /etc/nginx/sites-enabled/myapp sudo rm -f /etc/nginx/sites-available/myapp sudo nginx -t sudo systemctl reload nginx ``` Remove the sample application only after confirming the path contains no production data: ```bash rm -rf /srv/myapp ``` Do not run `pm2 unstartup` or uninstall PM2 if the server hosts other PM2-managed applications. **Verify:** `pm2 status` should no longer list `myapp`, `nginx -t` should still succeed, and the removed site should no longer proxy to the sample application. ## Conclusion You installed PM2 on Ubuntu 24.04 and deployed a Node.js 24 application with explicit cluster sizing for the tested 2 vCPU VM, graceful shutdown handling, systemd startup persistence, and Nginx as the public reverse proxy. The application port stays on `127.0.0.1`, PM2 manages worker lifecycle, and the final checks verify both local application health and the Nginx path. The main production decisions should come from your own workload rather than generic performance numbers. Scale PM2 workers only when the app is stateless, measure CPU and memory before changing worker counts, keep secrets out of committed ecosystem files, and regenerate the PM2 startup hook when an nvm-managed Node.js path changes. For HTTPS, continue with the [Nginx Let's Encrypt tutorial](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). --- ### Nginx 1.24 on Ubuntu 24.04: Install & Configure URL: https://rafftechnologies.com/learn/tutorials/install-nginx-ubuntu-24-04 Description: Install Nginx 1.24 on Ubuntu 24.04, verify the full Ubuntu package revision, configure UFW and server blocks, and understand why nginx -v still shows 1.24.0. In this tutorial, you’ll install **Nginx on Ubuntu 24.04**, verify the Ubuntu-packaged **Nginx 1.24.0** build, allow HTTP traffic through UFW, create a custom server block, inspect logs, and complete an end-to-end web server check. Ubuntu 24.04 LTS (Noble) currently ships the Nginx **1.24.0** branch through its supported repositories. As of August 28, 2026, Ubuntu’s Noble updates/security package is `1.24.0-2ubuntu7.17`. The important detail is the Ubuntu package revision: `nginx -v` may still display `nginx/1.24.0`, while Canonical can deliver security fixes through Ubuntu package revisions without changing the upstream base version shown in that short version string. ![Diagram showing how a web request flows through an Ubuntu 24.04 VPS setup: user browser, VPS public IP, UFW firewall, Nginx, server block, and website files.](https://raff-images.s3.raffusercloud.com/nginx_ubuntu_24_04_vps_d00449b0e5.png) **Quick install:** these commands install the Ubuntu-supported Nginx package, open HTTP through UFW, and verify the local response. Every step is explained below. ```bash sudo apt update sudo apt install -y nginx sudo ufw allow 'Nginx HTTP' curl -I http://127.0.0.1 ``` Nginx is a web server, reverse proxy, load balancer, HTTP cache, and TCP/UDP proxy. For most Ubuntu 24.04 servers, the distribution package is the simplest choice because it follows Ubuntu’s package lifecycle and security-update process. If you specifically need a newer Nginx release from nginx.org, this guide also explains that separate repository path later. Prerequisites: * A Raff Linux VM running Ubuntu 24.04 * SSH access with a user that has sudo privileges * The VM’s public IPv4 address * Port `22/tcp` available for SSH and port `80/tcp` available for the HTTP test * A domain is optional for this tutorial but required before enabling production HTTPS The original workflow was tested on a Raff VM with 2 vCPU and 2 GB RAM. Ubuntu’s Nginx package version, Canonical installation guidance, firewall guidance, and nginx.org repository instructions were re-verified on August 28, 2026. ## Ubuntu 24.04 Nginx version: why it shows 1.24.0 A common Ubuntu 24.04 question is why `nginx -v` reports a version such as: ```text nginx version: nginx/1.24.0 (Ubuntu) ``` Ubuntu 24.04’s supported package is based on the Nginx 1.24.0 source branch. Ubuntu then applies its own package revisions and security fixes. To see the **full installed Ubuntu package version**, use APT or dpkg rather than relying only on `nginx -v`: ```bash apt-cache policy nginx dpkg-query -W -f='${Version}\n' nginx ``` On a fully updated Noble system in late August 2026, the package can report: ```text 1.24.0-2ubuntu7.17 ``` The exact Ubuntu revision can increase as updates are published. Therefore: - `nginx -v` tells you the upstream base version compiled into the binary; - `dpkg-query` and `apt-cache policy` tell you which Ubuntu package revision is installed; - `sudo apt update && sudo apt upgrade` is how the Ubuntu repository delivers supported package updates. Do not assume an Ubuntu server is unpatched merely because the short Nginx version remains `1.24.0`. ## Step 1 — Update Ubuntu and install Nginx Update the package index and install current package updates before exposing a web service: ```bash sudo apt update sudo apt upgrade -y ``` Install Nginx, UFW, and curl from Ubuntu’s repositories: ```bash sudo apt install -y nginx ufw curl ``` Canonical documents the same core installation path in its Ubuntu Server Nginx guide: ```bash sudo apt update && sudo apt install nginx ``` Verify the Ubuntu release and both Nginx version views: ```bash lsb_release -ds nginx -v 2>&1 dpkg-query -W -f='${Version}\n' nginx ``` Expected output follows this pattern: ```text Ubuntu 24.04.x LTS nginx version: nginx/1.24.0 (Ubuntu) 1.24.0-2ubuntu7.x ``` The Ubuntu package revision may change as security and maintenance updates are published. ## Step 2 — Verify the Nginx service Nginx should start automatically after installation. Confirm that the service is active: ```bash systemctl is-active nginx ``` Expected output: ```text active ``` Confirm that Nginx is enabled at boot: ```bash systemctl is-enabled nginx ``` Expected output: ```text enabled ``` View the full service state without opening an interactive pager: ```bash sudo systemctl status nginx --no-pager ``` Expected output includes: ```text Active: active (running) ``` Useful service commands: ```bash sudo systemctl start nginx sudo systemctl stop nginx sudo systemctl restart nginx sudo systemctl reload nginx sudo systemctl enable nginx ``` Use `reload` after a successful configuration test when you want to apply changes without fully stopping the web server. ## Step 3 — Configure the UFW firewall UFW is Ubuntu’s host-based firewall management tool. Allow SSH before enabling it so you do not lock yourself out of the VM. ```bash sudo ufw allow OpenSSH ``` If the `OpenSSH` application profile is unavailable, allow the SSH port directly: ```bash sudo ufw allow 22/tcp ``` List the application profiles registered by Nginx: ```bash sudo ufw app list ``` Expected output includes: ```text Nginx Full Nginx HTTP Nginx HTTPS ``` Allow HTTP traffic for this installation test: ```bash sudo ufw allow 'Nginx HTTP' ``` Enable UFW: ```bash sudo ufw --force enable ``` Verify the active rules: ```bash sudo ufw status numbered ``` Expected output includes: ```text Status: active OpenSSH ALLOW IN Nginx HTTP ALLOW IN ``` > ⚠️ **Warning:** Always permit your current SSH access path before enabling UFW. If you also use an upstream cloud firewall, allow TCP port `80` there for the public browser test. Canonical’s Ubuntu firewall documentation explains UFW’s role and rule management in more detail. ## Step 4 — Test the default Nginx page Verify the web server locally first: ```bash curl -I http://127.0.0.1 ``` Expected output includes: ```text HTTP/1.1 200 OK Server: nginx ``` Get the VM’s public IPv4 address from the Raff dashboard or run: ```bash curl -4s https://icanhazip.com ``` Open the address in a browser: ```text http://your_server_ip ``` Visible state check: ```text The browser shows the default Nginx welcome page. The page includes the message "Welcome to nginx!" The browser uses HTTP because HTTPS is not configured yet. ``` ![Default Nginx welcome page running on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/nginx_default_page_ubuntu_24_04_webp_f0858d74f5.png) This confirms that Nginx is installed, the service is running, and HTTP traffic can reach the VM. ## Step 5 — Create a custom Nginx server block Nginx uses server blocks to select the site or application configuration for an incoming request. Ubuntu stores available site configurations in `/etc/nginx/sites-available/` and enables them with symbolic links in `/etc/nginx/sites-enabled/`. Create a document root for the demo site: ```bash sudo mkdir -p /var/www/raff-nginx-demo/html ``` Create the custom HTML page: ```bash sudo tee /var/www/raff-nginx-demo/html/index.html > /dev/null <<'EOF' Nginx server block is working on Raff

Nginx server block is working on Raff

This custom Nginx page is served from an Ubuntu 24.04 Linux VM.

EOF ``` Create a server block for the demo site: ```bash sudo tee /etc/nginx/sites-available/raff-nginx-demo > /dev/null <<'EOF' server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /var/www/raff-nginx-demo/html; index index.html; access_log /var/log/nginx/raff-nginx-demo.access.log; error_log /var/log/nginx/raff-nginx-demo.error.log; location / { try_files $uri $uri/ =404; } } EOF ``` Disable the default site and enable the new server block: ```bash sudo rm -f /etc/nginx/sites-enabled/default sudo ln -sf /etc/nginx/sites-available/raff-nginx-demo \ /etc/nginx/sites-enabled/raff-nginx-demo ``` Test the complete Nginx configuration before reloading: ```bash sudo nginx -t ``` Expected output: ```text nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` Reload Nginx only after the configuration test succeeds: ```bash sudo systemctl reload nginx ``` ## Step 6 — Verify the custom server block Test the page locally: ```bash curl -s http://127.0.0.1 | grep 'Nginx server block is working on Raff' ``` Expected output includes: ```text

Nginx server block is working on Raff

``` Test the public response: ```bash SERVER_IP="$(curl -4s https://icanhazip.com)" curl -I "http://$SERVER_IP" ``` Expected output includes: ```text HTTP/1.1 200 OK Server: nginx ``` Open the public IP in your browser again: ```text http://your_server_ip ``` Visible state check: ```text The browser shows the custom Nginx server block page. The page includes the message "Nginx server block is working on Raff". The page is served from /var/www/raff-nginx-demo/html. ``` ![Custom Nginx server block page on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/Nginx_server_block_is_working_on_Raff_658f202c47.png) The custom server block works when the command-line request and browser both return the demo page. > 📌 **Production note:** Replace `server_name _;` with your real domain names before enabling HTTPS. Only the public Nginx edge should be internet-facing; application servers, databases, caches, and internal services should use private traffic paths where possible. See [Public vs Private Traffic in Cloud Infrastructure](/learn/guides/private-networking-public-vs-private-traffic). ## Step 7 — Review Nginx files and logs Important Nginx paths on Ubuntu include: ```text /etc/nginx/nginx.conf /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ /etc/nginx/conf.d/ /var/www/ /var/log/nginx/ ``` Files created by this tutorial: ```text /var/www/raff-nginx-demo/html/index.html /etc/nginx/sites-available/raff-nginx-demo /etc/nginx/sites-enabled/raff-nginx-demo /var/log/nginx/raff-nginx-demo.access.log /var/log/nginx/raff-nginx-demo.error.log ``` Review recent access requests: ```bash sudo tail -n 20 /var/log/nginx/raff-nginx-demo.access.log ``` Review recent errors: ```bash sudo tail -n 20 /var/log/nginx/raff-nginx-demo.error.log ``` Confirm which configuration files Nginx loaded: ```bash sudo nginx -T 2>/dev/null | grep -E 'configuration file|server_name|root ' ``` Use `nginx -T` carefully on shared systems because the complete output can include internal hostnames and configuration details. ## Step 8 — Verify the complete Nginx setup Run the final verification sequence: ```bash SERVER_IP="$(curl -4s https://icanhazip.com)" echo "Ubuntu package:" dpkg-query -W -f='${Version}\n' nginx echo "Nginx binary:" nginx -v 2>&1 echo "Service:" systemctl is-active nginx echo "Boot status:" systemctl is-enabled nginx echo "Configuration:" sudo nginx -t echo "Firewall:" sudo ufw status numbered echo "Local HTTP response:" curl -I http://127.0.0.1 echo "Public HTTP response:" curl -I "http://$SERVER_IP" echo "Custom page:" curl -s http://127.0.0.1 | grep 'Nginx server block is working on Raff' ``` Expected state includes: ```text an Ubuntu nginx package revision nginx/1.24.0 (Ubuntu) active enabled nginx: configuration file /etc/nginx/nginx.conf test is successful Status: active HTTP/1.1 200 OK Nginx server block is working on Raff ``` The setup is complete when the package is current, the service is active and enabled, the configuration test passes, UFW allows HTTP traffic, and both local and public requests return the custom page. :::cta Deploy Your Server Launch an Ubuntu 24.04 Linux VM and use this Nginx setup for websites, reverse proxies, or application traffic. ::: ## Optional: install a newer Nginx release from nginx.org Ubuntu’s package is the recommended path when you want Ubuntu-managed updates and the Noble configuration layout. If you specifically need a newer stable or mainline Nginx release, nginx.org publishes official packages for Ubuntu 24.04. Do **not** mix Ubuntu’s distribution packages and the nginx.org repository casually. The packaging and default configuration layout differ, so review the migration before switching an existing production server. Install the prerequisites listed by nginx.org: ```bash sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring ``` Import the official nginx signing key: ```bash curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null ``` Verify the key fingerprint before trusting it: ```bash gpg --dry-run --quiet --no-keyring --import \ --import-options import-show \ /usr/share/keyrings/nginx-archive-keyring.gpg ``` The nginx.org documentation currently lists this signing-key fingerprint: ```text 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 ``` For the nginx.org **stable** repository: ```bash echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \ | sudo tee /etc/apt/sources.list.d/nginx.list ``` Pin nginx.org packages above distribution-provided nginx packages: ```bash echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \ | sudo tee /etc/apt/preferences.d/99nginx ``` Then update APT and inspect the candidate **before** installing: ```bash sudo apt update apt-cache policy nginx ``` If the candidate is the repository you intend to use, install it: ```bash sudo apt install nginx ``` If you need nginx.org **mainline** packages instead, use the repository URL documented by nginx.org for `/packages/mainline/ubuntu` rather than the stable path. > ⚠️ **Configuration warning:** Ubuntu’s distribution package commonly uses `/etc/nginx/sites-available/` and `/etc/nginx/sites-enabled/`. The nginx.org packages use a different default layout centered on `/etc/nginx/conf.d/`. Do not copy this tutorial’s Ubuntu server-block workflow blindly after changing package sources. ## Cleanup (optional) Remove the demo server block and web root: ```bash sudo rm -f /etc/nginx/sites-enabled/raff-nginx-demo sudo rm -f /etc/nginx/sites-available/raff-nginx-demo sudo rm -rf /var/www/raff-nginx-demo ``` Restore Ubuntu’s default site if the configuration file still exists: ```bash if [ -f /etc/nginx/sites-available/default ]; then sudo ln -sf /etc/nginx/sites-available/default \ /etc/nginx/sites-enabled/default fi ``` Test and reload Nginx: ```bash sudo nginx -t sudo systemctl reload nginx ``` Remove the HTTP firewall rule only when the VM no longer needs to serve HTTP traffic: ```bash sudo ufw delete allow 'Nginx HTTP' sudo ufw status numbered ``` Do not close port `80` when it is still required for a website, redirect, or ACME HTTP challenge. ## Troubleshooting ### The browser does not load the Nginx page **Cause:** Nginx is stopped, the VM’s public IP is wrong, port `80` is blocked, or an upstream firewall does not allow HTTP traffic. **Fix:** ```bash systemctl is-active nginx sudo ufw status numbered curl -I http://127.0.0.1 curl -4s https://icanhazip.com sudo ss -lntp | grep ':80' ``` Expected state: ```text Nginx is active Nginx HTTP is allowed 127.0.0.1 returns HTTP/1.1 200 OK Nginx listens on port 80 ``` ### Why does Nginx still show 1.24.0 after `apt upgrade`? On Ubuntu 24.04, `nginx -v` can continue to show the upstream base version `1.24.0` after Ubuntu security updates. Check the complete package revision instead: ```bash dpkg-query -W -f='${Version}\n' nginx apt-cache policy nginx ``` If the installed version matches the current candidate from your configured Ubuntu repositories, the package is current even though the short binary version remains `1.24.0`. ### `sudo nginx -t` reports a syntax error **Cause:** A file in `/etc/nginx/` contains an invalid directive, missing semicolon, or unmatched brace. **Fix:** ```bash sudo nginx -t sudo nano /etc/nginx/sites-available/raff-nginx-demo ``` Correct the file, test again, and reload only after validation succeeds: ```bash sudo nginx -t sudo systemctl reload nginx ``` ### The default Nginx page still appears **Cause:** Ubuntu’s default site is still enabled, the new symbolic link is missing, or Nginx was not reloaded. **Fix:** ```bash ls -l /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo ln -sf /etc/nginx/sites-available/raff-nginx-demo \ /etc/nginx/sites-enabled/raff-nginx-demo sudo nginx -t sudo systemctl reload nginx ``` Verify the selected site: ```bash curl -s http://127.0.0.1 | grep 'Nginx server block is working on Raff' ``` ### UFW does not show the Nginx profiles **Cause:** Nginx was not installed correctly, or the application profile files are missing. **Fix:** ```bash dpkg -s nginx ls -l /etc/ufw/applications.d/nginx sudo ufw app list ``` You can allow HTTP directly when necessary: ```bash sudo ufw allow 80/tcp ``` ### Nginx reload fails **Cause:** Nginx refuses to reload an invalid configuration or another service is already using port `80`. **Fix:** ```bash sudo nginx -t sudo ss -lntp | grep ':80' sudo journalctl -u nginx --no-pager -n 50 ``` Resolve the reported problem, then reload: ```bash sudo systemctl reload nginx ``` ### The site works over HTTP but shows “Not Secure” **Cause:** This tutorial intentionally verifies the server over plain HTTP. HTTPS has not been configured yet. **Fix:** Point a domain to the VM, replace the catch-all `server_name`, and follow [Secure Nginx with Let’s Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). ## How to uninstall Nginx from Ubuntu To update Nginx, no removal is needed: `sudo apt update && sudo apt upgrade` delivers new package revisions from your configured repository. To remove Nginx completely, stop the service and purge the packages: ```bash sudo systemctl stop nginx sudo apt purge -y nginx nginx-common sudo apt autoremove -y ``` > ⚠️ **Warning:** `purge` deletes Nginx configuration in `/etc/nginx`. Your website files in `/var/www/` are not removed; delete them manually only if you no longer need them. ## Conclusion You installed Nginx 1.24 on Ubuntu 24.04 through Ubuntu’s supported package repositories, verified the full Ubuntu package revision, configured UFW, created and enabled a custom server block, inspected logs, and completed an end-to-end HTTP check. The key versioning point is that Ubuntu can maintain the Nginx 1.24.0 base branch with Ubuntu security package revisions. Use `dpkg-query` or `apt-cache policy` when you need to know whether the installed package is current rather than judging only from `nginx -v`. Next, configure [free HTTPS with Let’s Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04), build a [LEMP stack on Ubuntu 24.04](/learn/tutorials/set-up-lemp-stack-ubuntu-24-04), or use [Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) for containerized applications behind Nginx. As the architecture grows, review [public vs private cloud traffic](/learn/guides/private-networking-public-vs-private-traffic) and [load balancing explained](/learn/guides/load-balancing-explained) before exposing multiple application servers. ## Sources - [Ubuntu Server — How to install nginx](https://ubuntu.com/server/docs/how-to/web-services/install-nginx/) - [Ubuntu Packages — nginx in Noble](https://packages.ubuntu.com/noble/nginx) - [Ubuntu Packages — nginx in Noble Updates](https://packages.ubuntu.com/noble-updates/nginx) - [Ubuntu Server — Firewall](https://documentation.ubuntu.com/server/how-to/security/firewalls/) - [nginx.org — Linux packages](https://nginx.org/en/linux_packages.html) - Sources verified: 2026-08-28 --- ### Host Your App on a VPS with Cloudflare: Step-by-Step Tutorial URL: https://rafftechnologies.com/learn/tutorials/host-app-on-vps-with-cloudflare Description: Host an app on a VPS with Cloudflare using a Raff Ubuntu 24.04 VM, Node.js 24 LTS, Nginx, proxied DNS, Full (strict) TLS, UFW, and health checks. In this tutorial, you will host a Node.js app on a VPS with Cloudflare, Nginx, HTTPS, proxied DNS records, firewall rules, a systemd service, and an end-to-end production check. To host an app on a VPS with Cloudflare means the application runs on your Linux VM while Cloudflare sits in front of the origin for DNS and proxied web traffic. The deployment pattern is: **Cloudflare → VPS public IP → Nginx on ports 80/443 → app on 127.0.0.1:3000**. Public users should never connect directly to the Node.js runtime port. Raff Technologies supports 3,000+ customers and 15,000+ VMs. Raff Linux VMs provide NVMe storage, 3 Gbps unmetered VM traffic, root access, snapshots, backups, firewall controls, and private networking for application deployments. This revision uses Node.js 24 LTS rather than the Ubuntu 24.04 Node.js 18 package because Node.js 18 is end-of-life. The existing article record was prepared for a Raff Ubuntu 24.04 VM with 2 vCPU, 4 GB RAM, and 40 GB NVMe storage; the revised procedure requires a fresh end-to-end Raff + Cloudflare validation before it should be marked fully tested. Prerequisites: - A [Raff Ubuntu 24.04 VM](/products/linux-vm) - SSH access with sudo privileges - A non-root deployment user such as `deploy` - A domain active in Cloudflare - Access to Cloudflare DNS and SSL/TLS settings - The VPS public IPv4 address - Ports `80` and `443` available for web traffic Use these placeholders throughout the tutorial: | Placeholder | Replace with | |---|---| | `your_server_ip` | Your Raff VM public IPv4 address | | `example.com` | Your root domain | | `www.example.com` | Your `www` hostname | | `deploy` | Your non-root deployment user | | `/opt/raff-node-app` | Application directory on the VM | ## Step 1 — Verify the Raff Ubuntu 24.04 VM Connect to the VM: ```bash ssh deploy@your_server_ip ``` Confirm the operating system and basic resources: ```bash lsb_release -ds nproc free -h lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS ``` Expected baseline: ```text Ubuntu 24.04.x LTS 2 or more vCPU for the reference setup 4 GB RAM for the reference setup ``` Update package metadata and install the utilities used later: ```bash sudo apt update sudo apt install -y curl ca-certificates git nginx ufw snapd dnsutils ``` Verification is complete when Ubuntu 24.04 is running, SSH works through the non-root user, and Nginx, UFW, `curl`, and `dig` are installed. ## Step 2 — Configure UFW before exposing the application Allow SSH before enabling the firewall: ```bash sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw --force enable ``` Review the active rules: ```bash sudo ufw status numbered ``` Expected public ports are: ```text 22/tcp 80/tcp 443/tcp ``` Do **not** open port `3000`. The Node.js app will listen only on loopback and Nginx will reach it locally. Verification is complete when UFW is active, your SSH session remains connected, and there is no public allow rule for port `3000`. ## Step 3 — Install Node.js 24 LTS for the deployment user Node.js recommends using supported LTS releases for production applications. Download the current nvm installer referenced by the Node.js download page to a file first: ```bash curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh -o /tmp/nvm-install.sh ``` Inspect the installer before running it: ```bash sed -n '1,120p' /tmp/nvm-install.sh ``` Run the installer as the non-root `deploy` user: ```bash bash /tmp/nvm-install.sh ``` Load nvm into the current shell: ```bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" ``` Install and select Node.js 24 LTS: ```bash nvm install 24 nvm alias default 24 nvm use 24 ``` Verify the runtime: ```bash node -v npm -v ``` Expected result: Node.js reports `v24.x.x` and npm is available. Verification is complete when Node.js 24 LTS and npm run successfully as the deployment user. ## Step 4 — Create a localhost-only Node.js application Create the application directory: ```bash sudo mkdir -p /opt/raff-node-app sudo chown deploy:deploy /opt/raff-node-app cd /opt/raff-node-app ``` Initialize the project and install Express: ```bash npm init -y npm install express ``` Create the sample server: ```bash cat > server.js <<'EOF' const express = require("express"); const app = express(); const host = "127.0.0.1"; const port = Number(process.env.PORT || 3000); app.get("/", (req, res) => { res.type("text/plain").send("Raff VPS app behind Cloudflare is running\n"); }); app.get("/health", (req, res) => { res.status(200).json({ status: "ok" }); }); app.listen(port, host, () => { console.log(`App listening on http://${host}:${port}`); }); EOF ``` Run the app temporarily: ```bash node server.js ``` In a second SSH session, verify the health route: ```bash curl http://127.0.0.1:3000/health ``` Expected output: ```json {"status":"ok"} ``` Confirm the listening address: ```bash ss -lntp | grep ':3000' ``` Expected output includes `127.0.0.1:3000`, not `0.0.0.0:3000`. Stop the temporary foreground process with `Ctrl+C` after verification. Verification is complete when `/health` returns `{"status":"ok"}` and the app listens only on `127.0.0.1:3000`. ## Step 5 — Run the app with systemd Resolve the Node.js binary installed for the deployment user: ```bash NODE_BIN="$(command -v node)" echo "$NODE_BIN" ``` Create the service using that exact runtime path: ```bash sudo tee /etc/systemd/system/raff-node-app.service > /dev/null < /dev/null <<'NGINX' server { listen 80; listen [::]:80; server_name example.com www.example.com; access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } NGINX ``` Enable the site and disable the Ubuntu default site: ```bash sudo ln -sfn /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com sudo rm -f /etc/nginx/sites-enabled/default ``` Test and reload Nginx: ```bash sudo nginx -t sudo systemctl enable --now nginx sudo systemctl reload nginx ``` Test Nginx locally using the intended host header: ```bash curl -H 'Host: example.com' http://127.0.0.1/health ``` Expected output: ```json {"status":"ok"} ``` Verification is complete when `nginx -t` succeeds and Nginx returns the application health response while proxying to `127.0.0.1:3000`. ## Step 7 — Add proxied Cloudflare DNS records In Cloudflare, open the DNS records for your domain and create: | Type | Name | Content | Proxy status | TTL | |---|---|---|---|---| | A | `@` | `your_server_ip` | Proxied | Auto | | CNAME | `www` | `example.com` | Proxied | Auto | Cloudflare can proxy A, AAAA, and CNAME records used for web traffic. With proxying enabled, public DNS queries return Cloudflare anycast addresses instead of the origin IP. Wait for the records to become active, then check them from your local computer: ```bash dig +short example.com dig +short www.example.com ``` Expected result: the proxied hostnames return Cloudflare addresses rather than the VPS origin IP. Test the HTTP route through Cloudflare: ```bash curl -I http://example.com ``` At this stage, an HTTP response from the application or a redirect is acceptable. Verification is complete when the records are `Proxied`, DNS resolves through Cloudflare, and HTTP reaches the Nginx origin through the domain. ## Step 8 — Issue a trusted TLS certificate on the Nginx origin Cloudflare Full (strict) requires a valid origin certificate. This tutorial uses a publicly trusted certificate so the origin can also be validated independently. Install Certbot using its recommended snap package: ```bash sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot ``` Request certificates for the hostnames and let Certbot configure Nginx: ```bash sudo certbot --nginx -d example.com -d www.example.com --redirect ``` Follow the prompts for your email address and the terms of service. Test automatic renewal: ```bash sudo certbot renew --dry-run ``` Verify the origin Nginx configuration remains valid: ```bash sudo nginx -t ``` Then verify HTTPS through the public domain: ```bash curl -I https://example.com ``` If validation fails, first check DNS, port `80`, Nginx, and the ACME challenge path. Do not make DNS-only exposure the default troubleshooting step; switching a web record to DNS-only publishes the origin IP and removes Cloudflare proxy protections for that hostname. Verification is complete when Certbot succeeds, the renewal dry run passes, `nginx -t` succeeds, and the domain responds over HTTPS. ## Step 9 — Set Cloudflare SSL/TLS to Full (strict) In the Cloudflare dashboard, open: ```text SSL/TLS → Overview ``` Set the encryption mode to: ```text Full (strict) ``` Full (strict) encrypts the visitor-to-Cloudflare connection and the Cloudflare-to-origin connection while validating the certificate presented by Nginx. Avoid Flexible mode for this architecture because it leaves the Cloudflare-to-origin leg on HTTP and can conflict with origin HTTPS redirects. Verify the public HTTPS response: ```bash curl -I https://example.com ``` Check for Cloudflare response headers: ```bash curl -sI https://example.com | grep -Ei 'server:|cf-ray:|cf-cache-status:' ``` Expected output commonly includes: ```text server: cloudflare cf-ray: ... ``` Verification is complete when Cloudflare is set to Full (strict), HTTPS succeeds, and the response contains Cloudflare proxy headers. ## Step 10 — Verify the application stays private behind Nginx Confirm the app still listens only on loopback: ```bash ss -lntp | grep ':3000' ``` Expected output includes: ```text 127.0.0.1:3000 ``` Review UFW again: ```bash sudo ufw status numbered ``` Port `3000` should not have a public allow rule. From a computer outside the VM, attempt to reach the runtime port directly: ```bash curl --connect-timeout 5 http://your_server_ip:3000 ``` Expected result: the connection fails. Verification is complete when the app works through Nginx but cannot be reached directly on the VPS public IP at port `3000`. ## Step 11 — Verify the full Cloudflare deployment end to end Run these public checks from your local computer: ```bash curl -I https://example.com curl https://example.com/health curl -sI https://example.com | grep -Ei 'server:|cf-ray:' ``` Expected results include: ```text HTTPS response succeeds {"status":"ok"} Cloudflare response headers are present ``` On the VM, verify both runtime services: ```bash systemctl is-active nginx systemctl is-active raff-node-app curl http://127.0.0.1:3000/health sudo nginx -t ``` Confirm the intended request path: ```text Visitor → Cloudflare proxied DNS and edge TLS → HTTPS to Nginx on the Raff VM → local proxy to 127.0.0.1:3000 → Node.js application ``` Finally, reboot the VM during a safe test window: ```bash sudo reboot ``` After reconnecting, repeat: ```bash systemctl is-active nginx systemctl is-active raff-node-app curl https://example.com/health ``` End-to-end verification is complete when HTTPS works through Cloudflare, `/health` returns `{"status":"ok"}`, Nginx and the Node.js service survive reboot, Full (strict) is enabled, and port `3000` remains private. :::cta Deploy Your Server Deploy an Ubuntu VM for your Cloudflare-backed application server. ::: ## Step 12 — Add basic production monitoring and recovery checks Review recent application logs: ```bash journalctl -u raff-node-app -n 50 --no-pager ``` Review Nginx logs: ```bash sudo tail -n 50 /var/log/nginx/example.com.access.log sudo tail -n 50 /var/log/nginx/example.com.error.log ``` Check resource headroom: ```bash free -h df -h / uptime ``` Before sending production traffic, configure backups for application configuration and persistent data, document your deployment and rollback process, and review [Raff Data Protection](/products/data-protection) for infrastructure-level recovery options. If your application stores uploads, databases, queues, or other state, back those components up separately instead of assuming a VM snapshot alone is sufficient. Verification is complete when logs are readable, disk and memory have headroom, and a recovery plan exists for the data the application actually depends on. ## Cleanup and rollback To take the sample app offline without deleting its files, stop and disable the service: ```bash sudo systemctl disable --now raff-node-app ``` Disable its Nginx site: ```bash sudo unlink /etc/nginx/sites-enabled/example.com sudo nginx -t sudo systemctl reload nginx ``` This leaves `/opt/raff-node-app`, the systemd unit file, and certificate material intact for rollback or inspection. If you permanently decommission the sample deployment, back up anything you need and then remove only the application files, systemd service, Nginx site, and certificates that belong to this hostname. Remove Cloudflare DNS records only when the hostname should stop resolving. Verification is complete when the Nginx site is disabled and the application is no longer publicly served. ## Troubleshooting ### Nginx returns 502 Bad Gateway Confirm the app service and local health endpoint: ```bash systemctl status raff-node-app --no-pager journalctl -u raff-node-app -n 50 --no-pager curl http://127.0.0.1:3000/health ``` If the service is stopped, restart it and recheck the local health route: ```bash sudo systemctl restart raff-node-app curl http://127.0.0.1:3000/health ``` ### Cloudflare returns 521 or 522 These are origin-connectivity failures. Check Nginx, firewall rules, DNS content, and local HTTP/HTTPS listeners: ```bash systemctl is-active nginx sudo ufw status numbered sudo ss -lntp | grep -E ':80|:443' curl -I http://127.0.0.1 ``` Confirm the Cloudflare A record contains the current Raff VM public IP. ### Cloudflare returns 526 A 526 error with Full (strict) indicates Cloudflare could not validate the origin certificate. Check the certificate hostname, expiration, Nginx TLS configuration, and renewal status: ```bash sudo certbot certificates sudo certbot renew --dry-run sudo nginx -t ``` ### HTTPS enters a redirect loop Confirm Cloudflare uses Full (strict), not Flexible: ```text SSL/TLS → Overview → Full (strict) ``` Then check the redirect chain: ```bash curl -IL https://example.com ``` A normal deployment should settle on the canonical HTTPS URL instead of repeating redirects. ### The app port is publicly reachable Confirm Node.js binds to loopback: ```bash ss -lntp | grep ':3000' ``` The address must be `127.0.0.1:3000`. Check for accidental UFW rules: ```bash sudo ufw status numbered ``` Remove a public port-3000 rule only if one exists and you have identified it correctly. ### DNS returns the VPS IP instead of Cloudflare addresses Open the Cloudflare DNS record and confirm `Proxy status` is `Proxied`. Cloudflare web records configured as DNS-only return the origin record value instead of Cloudflare anycast addresses. Verify again: ```bash dig +short example.com ``` ## Production checklist Before sending real users to the application, confirm: - The app runs under a non-root user - Node.js uses a supported LTS release - The app binds only to `127.0.0.1:3000` - UFW does not expose the runtime port - Nginx is active and starts at boot - The app systemd service is active and starts at boot - Cloudflare A/CNAME web records are Proxied - The origin has a valid TLS certificate - Cloudflare SSL/TLS mode is Full (strict) - HTTP redirects to HTTPS - `/health` works through the public hostname - A reboot test passes - Logs, backups, and rollback procedures are documented ## Conclusion and next steps You now have the production pattern for hosting an app on a VPS with Cloudflare: the Node.js application remains private on `127.0.0.1:3000`, Nginx handles the public origin ports, Cloudflare proxies the web records, and Full (strict) keeps the Cloudflare-to-origin connection encrypted and certificate-validated. For related deployment work, continue with [Install Node.js on Ubuntu 24.04](/learn/tutorials/install-nodejs-ubuntu-24-04), [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), and [Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). --- ### How to Install Certbot for Nginx on Ubuntu 24.04 with Let's Encrypt URL: https://rafftechnologies.com/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04 Description: Install Certbot for Nginx on Ubuntu 24.04, issue a Let's Encrypt SSL certificate, redirect HTTP to HTTPS, test renewal, and troubleshoot common errors. Certbot is an ACME client that can request a free TLS certificate from Let's Encrypt, install it into an Nginx server block, configure an HTTP-to-HTTPS redirect, and renew the certificate automatically. On Ubuntu 24.04, the safest workflow is to verify DNS and Nginx first, keep port 80 reachable for HTTP-01 validation, install a current Certbot build, request the certificate with the Nginx plugin, and test renewal before treating HTTPS as complete. Raff users can apply this workflow to a Linux VM running Nginx on Ubuntu 24.04. The tutorial assumes your domain already resolves to the VM and Nginx serves the site over HTTP. If Nginx is not installed yet, complete [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04) first. Let's Encrypt recommends keeping port 80 open for general web servers and redirecting HTTP to HTTPS rather than blocking HTTP entirely. Certbot's current Nginx instructions also support having Certbot edit the Nginx configuration directly, then testing automatic renewal with `certbot renew --dry-run`. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - Nginx installed and serving the intended hostname over HTTP - A domain name with DNS records pointing to the VM - A non-root user with sudo privileges - Public access to TCP ports 80 and 443 ## Step 1 — Verify DNS Before Running Certbot Check the IPv4 records for every hostname you want on the certificate: ```bash dig +short A example.com dig +short A www.example.com ``` If the domain publishes IPv6, check the AAAA records too: ```bash dig +short AAAA example.com dig +short AAAA www.example.com ``` Each hostname included in the certificate request must resolve to this server. A stale AAAA record can send validation traffic to the wrong IPv6 host even when the A record is correct. Compare the DNS result with the VM's public address. If a hostname should not be used, do not include it in the Certbot command. **Verify:** All requested hostnames should resolve to the intended server, and any published AAAA record should reach the same Nginx deployment. ## Step 2 — Verify Nginx Serves the Domain Over HTTP Check the active Nginx configuration: ```bash sudo nginx -t ``` Confirm the site responds over HTTP: ```bash curl -I http://example.com ``` Inspect the server block if needed: ```bash sudo nginx -T 2>/dev/null | grep -A8 -B3 'server_name example.com' ``` The active server block should contain the hostname you plan to request with Certbot, for example: ```nginx server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/public; } ``` Certbot's Nginx plugin needs to identify the matching server block before it can install the certificate cleanly. **Verify:** `sudo nginx -t` should succeed and `curl -I http://example.com` should return an HTTP response from the intended Nginx site. ## Step 3 — Keep Ports 80 and 443 Reachable Check UFW status: ```bash sudo ufw status numbered ``` If UFW is active, allow SSH and the Nginx profile for HTTP and HTTPS: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' ``` Review the result: ```bash sudo ufw status numbered ``` Do not close port 80 after enabling HTTPS when using the HTTP-01 validation path. Let's Encrypt recommends serving HTTP and redirecting it to HTTPS. Also verify that any upstream cloud firewall or network policy allows TCP 80 and 443 to this VM. **Verify:** The server remains reachable over SSH, HTTP reaches port 80, and HTTPS traffic is allowed on port 443. ## Step 4 — Install Certbot for Nginx on Ubuntu 24.04 Certbot's current Linux instructions support installing the Certbot snap maintained by the Certbot team. Avoid mixing multiple Certbot installation methods on the same server. First check for an existing installation: ```bash command -v certbot || true snap list certbot 2>/dev/null || true dpkg -l | grep -E 'certbot|python3-certbot-nginx' || true ``` If Certbot is already managing production certificates successfully, do not replace it only for this tutorial. Continue with the existing supported installation and verify renewal. For a new installation, make sure `snap` is available: ```bash command -v snap || sudo apt install -y snapd ``` Install Certbot: ```bash sudo snap install --classic certbot ``` Create the standard command path if needed: ```bash sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot ``` Check the installed version and Nginx plugin: ```bash certbot --version certbot plugins | grep -A3 nginx ``` Do not depend on a specific Certbot version string in automation because the package is updated over time. **Verify:** `certbot --version` should succeed and `certbot plugins` should list the Nginx plugin. ## Step 5 — Request and Install a Let's Encrypt Certificate with Certbot and Nginx Request the certificate and let Certbot update the matching Nginx server block: ```bash sudo certbot --nginx --redirect \ -d example.com \ -d www.example.com ``` Certbot will ask for an email address and agreement to the Let's Encrypt terms. The `--redirect` option configures HTTP requests to redirect to HTTPS after successful issuance. If you use only the apex hostname, request only that name: ```bash sudo certbot --nginx --redirect -d example.com ``` Do not request hostnames that do not resolve to this server. After issuance, list managed certificates: ```bash sudo certbot certificates ``` Do not manually edit files inside `/etc/letsencrypt/live/` or `/etc/letsencrypt/renewal/`; Certbot manages those paths. **Verify:** `sudo certbot certificates` should list the requested hostname and `sudo nginx -t` should still pass. ## Step 6 — Verify HTTPS, the HTTP Redirect, and the Certificate Test HTTPS: ```bash curl -I https://example.com ``` Test the HTTP redirect: ```bash curl -I http://example.com ``` The HTTP response should redirect to the HTTPS URL, commonly with `301` or `308`. Inspect the certificate presented by Nginx: ```bash openssl s_client \ -connect example.com:443 \ -servername example.com \ /dev/null | openssl x509 -noout -subject -issuer -dates ``` Check that the certificate matches the hostname and has valid start and expiry dates. **Verify:** HTTPS should complete without a certificate error, HTTP should redirect to HTTPS, and the certificate dates should be valid. ## Step 7 — Test Certbot Automatic Renewal for Nginx Most Certbot installations include a scheduled renewal task. Check both common scheduling paths: ```bash systemctl list-timers --all | grep -i certbot || true sudo grep -R 'certbot renew' /etc/crontab /etc/cron.* 2>/dev/null || true ``` Run Certbot's renewal simulation: ```bash sudo certbot renew --dry-run ``` This tests the renewal path without replacing your active production certificate. Review managed certificate details again: ```bash sudo certbot certificates ``` You normally should not create an extra custom cron job when your Certbot installation already provides automatic renewal. **Verify:** `sudo certbot renew --dry-run` should complete successfully and a scheduled renewal mechanism should be present for the installation method in use. ## Step 8 — Add Security Headers Without Breaking the Site TLS does not automatically configure application security headers. Add only headers that match your application's requirements. Open the active HTTPS server block and add a conservative baseline inside the `server` block: ```nginx add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header X-Frame-Options "SAMEORIGIN" always; ``` `X-Frame-Options: SAMEORIGIN` is not appropriate when the site must be embedded by another origin. Treat HSTS separately. Enable it only after HTTPS, redirects, certificate renewal, and every required hostname are working reliably. Start with a short test duration: ```nginx add_header Strict-Transport-Security "max-age=300" always; ``` Do not add `includeSubDomains` until every required subdomain supports HTTPS. Validate and reload: ```bash sudo nginx -t sudo systemctl reload nginx ``` Check the headers: ```bash curl -I https://example.com ``` **Verify:** `nginx -t` should pass, the site should remain reachable over HTTPS, and only the intended headers should appear. ## Step 9 — Troubleshoot Common Certbot and Nginx Errors ### Certbot cannot find a matching Nginx server block Confirm the hostname appears in an enabled server block: ```bash sudo nginx -T 2>/dev/null | grep -n 'server_name' ``` Correct `server_name`, then run: ```bash sudo nginx -t sudo systemctl reload nginx ``` ### The Nginx plugin is not installed Check available plugins: ```bash certbot plugins ``` With the Certbot snap, the Nginx plugin should be included. If Certbot comes from another installation method, follow the instructions for that method rather than mixing packages. ### HTTP-01 validation fails Check DNS and port 80: ```bash dig +short A example.com dig +short AAAA example.com sudo ss -ltnp | grep ':80' sudo ufw status numbered curl -I http://example.com ``` A wrong A/AAAA record, blocked port 80, or incorrect Nginx routing can all break validation. ### `/.well-known/acme-challenge/` returns 404 If a custom Nginx rule intercepts hidden paths or rewrites all requests, inspect the active configuration before retrying: ```bash sudo nginx -T 2>/dev/null | grep -n -E 'well-known|rewrite|return|location' ``` Fix the conflicting routing rule instead of repeatedly requesting new certificates. ### Certbot hits a Let's Encrypt rate limit Stop retrying the same broken production request. Fix DNS, firewall, or Nginx first. Use Certbot's dry-run or staging workflow while validating renewal behavior. ### Renewal works but Nginx serves an old certificate Check the certificate Certbot manages, validate Nginx, and reload it: ```bash sudo certbot certificates sudo nginx -t sudo systemctl reload nginx ``` Then inspect the live certificate again with `openssl s_client`. **Verify:** After troubleshooting, `sudo nginx -t`, `curl -I https://example.com`, and `sudo certbot renew --dry-run` should all succeed. :::cta Deploy Your Server Launch a Raff Ubuntu VM and use Certbot with Nginx to serve your application over HTTPS. ::: ## Step 10 — Run the Final End-to-End HTTPS Verification Run the complete verification sequence: ```bash sudo nginx -t systemctl is-active nginx curl -I http://example.com curl -I https://example.com sudo certbot certificates sudo certbot renew --dry-run openssl s_client \ -connect example.com:443 \ -servername example.com \ /dev/null | openssl x509 -noout -subject -issuer -dates ``` The deployment is complete when Nginx configuration is valid, HTTP redirects to HTTPS, the HTTPS endpoint presents the expected certificate, and the renewal dry run succeeds. If this Nginx instance proxies a Node.js application, keep the application port private and let Nginx own the public HTTPS edge. See [Install PM2 and Deploy Node.js on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04) for that architecture. **Verify:** Every command above should succeed without certificate, redirect, Nginx syntax, or renewal errors. ## Step 11 — Clean Up a Test Certificate Safely Do not delete a certificate that is still serving a production hostname. List Certbot-managed certificates first: ```bash sudo certbot certificates ``` If this was only a disposable test hostname and the Nginx site no longer depends on the certificate, remove the test certificate through Certbot: ```bash sudo certbot delete --cert-name example.com ``` Then inspect the Nginx configuration for references to the removed certificate: ```bash sudo nginx -T 2>/dev/null | grep -n '/etc/letsencrypt/live/' || true ``` Remove or update only the server block that belonged to the decommissioned test hostname, then validate before reloading: ```bash sudo nginx -t sudo systemctl reload nginx ``` Do not uninstall Certbot while it still manages certificates for other sites on the server. **Verify:** `sudo certbot certificates` should no longer list the deleted test certificate, and `sudo nginx -t` should still succeed. ## Conclusion You installed Certbot for Nginx on Ubuntu 24.04, requested a Let's Encrypt certificate, configured HTTP-to-HTTPS redirection, verified the live certificate, tested automatic renewal, and added a conservative security-header baseline. The most important production checks are simple: keep DNS correct, keep port 80 available for the HTTP-01 workflow, validate Nginx before reloads, do not mix Certbot installation methods casually, and treat `certbot renew --dry-run` as part of the deployment rather than an optional afterthought. For related setup work, continue with [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), [Install PM2 and Deploy Node.js on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04), or [Install WordPress on Ubuntu 24.04 with Nginx](/learn/tutorials/install-wordpress-ubuntu-24-04-nginx). ## Sources - [Certbot — Nginx on Linux (snap)](https://certbot.eff.org/instructions?ws=nginx&os=snap) - [Certbot User Guide — Automated Renewals](https://eff-certbot.readthedocs.io/en/latest/using.html#automated-renewals) - [Let's Encrypt — Keep Port 80 Open](https://letsencrypt.org/docs/allow-port-80/) - Sources verified: 2026-09-04 --- ### How to Deploy Django with Gunicorn and Nginx on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-django-nginx-gunicorn-ubuntu-24-04 Description: Deploy Django on Ubuntu 24.04 with Gunicorn, Nginx, systemd, static files, secure environment variables, HTTPS settings, and end-to-end production checks. Deploying Django with Gunicorn and Nginx on Ubuntu 24.04 gives each layer one clear responsibility: Django handles application logic, Gunicorn runs the WSGI application, systemd manages the Gunicorn process, and Nginx handles public HTTP/HTTPS traffic and static files. Raff users can use this pattern on a Linux VM without exposing Django's development server or a raw Gunicorn port to the internet. Django's production checklist explicitly says `manage.py runserver` is not designed for production and recommends a production WSGI or ASGI server instead. Gunicorn's deployment documentation recommends placing Gunicorn behind a proxy such as Nginx. The worker-count formula often quoted for Gunicorn is only a starting point; the correct count depends on CPU, memory, database connections, request behavior, and measured load. This tutorial creates a small Django app, keeps `SECRET_KEY` outside source control, runs Gunicorn as a non-root systemd service over a Unix socket, serves collected static files with Nginx, keeps the application port private, and finishes with HTTPS and Django's deployment checks. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root sudo user - A domain such as `example.com` pointing to the VM - TCP ports 80 and 443 available for Nginx - No requirement to expose Gunicorn directly to the public internet ## Step 1 — Install Python and Nginx and Create a Django Service User Update package metadata and install the packages used by this deployment: ```bash sudo apt update sudo apt install -y python3-venv nginx curl ``` Create a dedicated non-login user for the Django application: ```bash sudo useradd --system \ --home /srv/mysite \ --create-home \ --shell /usr/sbin/nologin \ djangoapp ``` Create the application directory and give the service user ownership: ```bash sudo mkdir -p /srv/mysite/app sudo chown -R djangoapp:djangoapp /srv/mysite ``` Confirm Python and Nginx are available: ```bash python3 --version nginx -v systemctl is-active nginx ``` Do not depend on an exact Python patch version in automation; Ubuntu security updates can change it within the supported 3.12 series. **Verify:** Python should run, Nginx should report a version, and `systemctl is-active nginx` should return `active`. ## Step 2 — Create a Virtual Environment and Install Django and Gunicorn Create a virtual environment owned by the application user: ```bash sudo -u djangoapp python3 -m venv /srv/mysite/venv ``` Upgrade pip inside the virtual environment, not the system Python: ```bash sudo -u djangoapp /srv/mysite/venv/bin/python -m pip install --upgrade pip ``` For this demo, install Django and Gunicorn: ```bash sudo -u djangoapp /srv/mysite/venv/bin/python -m pip install django gunicorn ``` For an existing application, install its reviewed dependency file instead of blindly replacing versions: ```bash sudo -u djangoapp /srv/mysite/venv/bin/python -m pip install -r /srv/mysite/app/requirements.txt ``` Create a demo project: ```bash cd /srv/mysite/app sudo -u djangoapp /srv/mysite/venv/bin/django-admin startproject config . ``` Add a small health endpoint to `config/urls.py`: ```python from django.contrib import admin from django.http import JsonResponse from django.urls import path def health(_request): return JsonResponse({"status": "ok"}) urlpatterns = [ path("admin/", admin.site.urls), path("health/", health), ] ``` Confirm the packages and WSGI module import correctly: ```bash sudo -u djangoapp /srv/mysite/venv/bin/python -c 'import django, gunicorn, config.wsgi; print(django.get_version())' ``` **Verify:** Django should print a version and the command should exit without an import error. ## Step 3 — Store the Django Secret Outside the Project Django's deployment checklist recommends keeping `SECRET_KEY` secret and out of source control. Create a root-managed environment file that the service user can read: ```bash sudo install -m 640 -o root -g djangoapp /dev/null /etc/mysite.env ``` Generate a high-entropy secret without printing it to your terminal history: ```bash sudo sh -c 'printf "DJANGO_SECRET_KEY=%s\n" "$(python3 -c "import secrets; print(secrets.token_urlsafe(50))")" > /etc/mysite.env' sudo chown root:djangoapp /etc/mysite.env sudo chmod 640 /etc/mysite.env ``` Confirm the service account can read the file without displaying the secret: ```bash sudo -u djangoapp test -r /etc/mysite.env && echo readable ``` Do not commit `/etc/mysite.env` to Git or copy its value into the systemd unit. **Verify:** The command should print `readable`, and `stat -c '%U %G %a' /etc/mysite.env` should show `root djangoapp 640`. ## Step 4 — Configure Django for Production Edit `/srv/mysite/app/config/settings.py` and add `import os` near the top if it is not already present. Use production settings like these: ```python import os SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] DEBUG = False ALLOWED_HOSTS = ["example.com", "www.example.com"] STATIC_URL = "static/" STATIC_ROOT = BASE_DIR / "staticfiles" ``` Do not use `ALLOWED_HOSTS = ["*"]` as a shortcut. Django recommends validating the expected hostnames in production. For an existing project, also review database credentials, email settings, caches, uploaded media, logging, and any environment-specific settings. Database passwords should be protected like `SECRET_KEY` rather than committed to the repository. Load the environment and run Django's basic system check: ```bash sudo -u djangoapp bash -c ' set -a . /etc/mysite.env set +a cd /srv/mysite/app ../venv/bin/python manage.py check ' ``` **Verify:** `manage.py check` should finish without configuration errors and `DEBUG` should be `False` in the production settings. ## Step 5 — Run Migrations and Collect Django Static Files Apply migrations and collect static assets under `STATIC_ROOT`: ```bash sudo -u djangoapp bash -c ' set -a . /etc/mysite.env set +a cd /srv/mysite/app ../venv/bin/python manage.py migrate ../venv/bin/python manage.py collectstatic --noinput ' ``` Django's production documentation expects static files to be collected and then served by a web server or another static-file service rather than by the development server. Check that the directory exists and contains files: ```bash sudo -u djangoapp find /srv/mysite/app/staticfiles -maxdepth 2 -type f | head ``` For a real application, back up the database before production migrations and use your application's tested release procedure instead of treating every migration as risk-free. **Verify:** Migrations should complete successfully and `staticfiles/` should contain collected assets. ## Step 6 — Test Django with Gunicorn on Localhost Before creating a service, test Gunicorn locally. Bind only to loopback so the raw WSGI server is not exposed publicly: ```bash sudo -u djangoapp bash -c ' set -a . /etc/mysite.env set +a cd /srv/mysite/app ../venv/bin/gunicorn \ --bind 127.0.0.1:8000 \ --workers 2 \ config.wsgi:application ' ``` In a second SSH session, send the expected host header: ```bash curl -H 'Host: example.com' http://127.0.0.1:8000/health/ ``` Expected output: ```json {"status": "ok"} ``` Django's `runserver` is a development server; the reason to move to Gunicorn is not that `runserver` is always single-threaded, but that Django explicitly says it is not designed for production. Stop the foreground Gunicorn test with `Ctrl+C` after verification. **Verify:** Gunicorn should return the health response on `127.0.0.1:8000`, and no public firewall rule should exist for port 8000. ## Step 7 — Run Gunicorn as a systemd Service over a Unix Socket Create `/etc/systemd/system/mysite-gunicorn.service`: ```ini [Unit] Description=Gunicorn for Django mysite After=network.target [Service] Type=notify NotifyAccess=main User=djangoapp Group=www-data WorkingDirectory=/srv/mysite/app EnvironmentFile=/etc/mysite.env RuntimeDirectory=mysite RuntimeDirectoryMode=0750 UMask=0007 ExecStart=/srv/mysite/venv/bin/gunicorn \ --workers 2 \ --access-logfile - \ --error-logfile - \ --bind unix:/run/mysite/gunicorn.sock \ config.wsgi:application ExecReload=/bin/kill -s HUP $MAINPID KillMode=mixed TimeoutStopSec=30 Restart=on-failure RestartSec=5 PrivateTmp=true NoNewPrivileges=true [Install] WantedBy=multi-user.target ``` Reload systemd and start the service: ```bash sudo systemctl daemon-reload sudo systemctl enable --now mysite-gunicorn ``` Check the service and socket: ```bash systemctl is-active mysite-gunicorn sudo ls -l /run/mysite/gunicorn.sock ``` Test the socket as the Nginx user: ```bash sudo -u www-data curl \ --unix-socket /run/mysite/gunicorn.sock \ -H 'Host: example.com' \ http://localhost/health/ ``` Gunicorn's current deployment documentation supports systemd-managed services and Unix sockets. `Type=notify` lets Gunicorn report readiness to systemd. **Verify:** The service should be `active`, the socket should exist under `/run/mysite/`, and the `www-data` curl command should return `{"status": "ok"}`. ## Step 8 — Configure Nginx for Django and Gunicorn Create `/etc/nginx/sites-available/mysite`: ```nginx server { listen 80; listen [::]:80; server_name example.com www.example.com; client_max_body_size 10m; location /static/ { alias /srv/mysite/app/staticfiles/; access_log off; expires 7d; add_header Cache-Control "public"; } location / { proxy_pass http://unix:/run/mysite/gunicorn.sock; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; } } ``` This tutorial does not add WebSocket upgrade headers because standard Django through Gunicorn's WSGI worker is an HTTP WSGI deployment. If your application requires WebSockets or other ASGI behavior, use an ASGI deployment rather than copying WSGI settings blindly. Enable the site and remove the Ubuntu default only if it is not serving anything else: ```bash sudo ln -sfn /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t sudo systemctl reload nginx ``` On a dedicated single-site VM, you can also configure a separate default server that rejects unknown hostnames instead of forwarding them to Django. **Verify:** `sudo nginx -t` should succeed and Nginx should reload without errors. ## Step 9 — Set Static-File Permissions and Keep Gunicorn Private Nginx needs read and traverse permission for the collected static directory, but it does not need write access to your project: ```bash sudo chmod 755 /srv/mysite /srv/mysite/app sudo find /srv/mysite/app/staticfiles -type d -exec chmod 755 {} + sudo find /srv/mysite/app/staticfiles -type f -exec chmod 644 {} + ``` If UFW is active, allow SSH before making firewall changes, then allow Nginx: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw status numbered ``` Do not add a public rule for port 8000. The persistent Gunicorn service uses a Unix socket and Nginx is the public edge. If your project has user-uploaded media, treat uploads as untrusted data and configure a separate media path carefully. Do not let Nginx execute uploaded content. **Verify:** UFW should allow the intended SSH and web ports, and there should be no public Gunicorn port. :::cta Deploy Your Server Launch an Ubuntu VM for a Django, Gunicorn, and Nginx application stack. ::: ## Step 10 — Verify Django, Gunicorn, Nginx, and Static Files End to End Test the application through Nginx: ```bash curl -H 'Host: example.com' http://127.0.0.1/health/ curl http://example.com/health/ ``` Expected application response: ```json {"status": "ok"} ``` Confirm an admin static file is served by Nginx: ```bash curl -I http://example.com/static/admin/css/base.css ``` Check the two services: ```bash systemctl is-active mysite-gunicorn nginx ``` Inspect recent logs if a request fails: ```bash sudo journalctl -u mysite-gunicorn -n 50 --no-pager sudo tail -n 50 /var/log/nginx/error.log ``` **Verify:** The public health endpoint should succeed, the static file should return a successful HTTP response, and both services should be active. ## Step 11 — Tune Gunicorn Workers from Measurements, Not a Fixed Formula Gunicorn documents `(2 × CPU cores) + 1` as a starting point, not a universal production rule. Too many workers can waste memory, increase database connections, and reduce throughput. This tutorial starts with two workers on the existing 2 vCPU test profile. Measure before changing it: ```bash ps -o pid,ppid,rss,%cpu,cmd -C gunicorn free -h uptime ``` Also watch: - request latency and error rate; - worker memory after normal traffic; - database connection usage; - CPU saturation; - timeout and restart events. If you change `--workers`, reload the unit definition and restart during a controlled deployment: ```bash sudo systemctl daemon-reload sudo systemctl restart mysite-gunicorn ``` For application-code deployments that are safe to reload, the unit also supports Gunicorn's HUP reload path: ```bash sudo systemctl reload mysite-gunicorn ``` Do not use a long `--timeout` to hide slow views. Fix slow database queries, external calls, or background jobs according to the workload. **Verify:** Worker count should fit available memory and database capacity without repeated OOM events, timeouts, or restarts. ## Step 12 — Add HTTPS and Enable Django's HTTPS Security Settings Before serving logins, admin sessions, password resets, or other sensitive traffic, enable site-wide HTTPS. Complete [Install Certbot for Nginx on Ubuntu 24.04 with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04) for certificate issuance and renewal testing. Because Nginx is the trusted proxy and this configuration explicitly sets `X-Forwarded-Proto`, add these settings after HTTPS is working: ```python SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True ``` Treat HSTS separately. After HTTPS and renewal are stable, start with a short test value before increasing it: ```python SECURE_HSTS_SECONDS = 300 ``` Do not enable `SECURE_PROXY_SSL_HEADER` when requests can bypass your trusted proxy or when an untrusted client can control the forwarded-protocol header. Run Django's deployment checks against the production environment: ```bash sudo -u djangoapp bash -c ' set -a . /etc/mysite.env set +a cd /srv/mysite/app ../venv/bin/python manage.py check --deploy ' ``` Review every warning rather than assuming one generic configuration is correct for every application. **Verify:** HTTPS should work, HTTP should redirect to HTTPS, secure cookies should be enabled, and `check --deploy` warnings should be understood and resolved where applicable. ## Step 13 — Test Reboot Persistence and the Final Production Path Reboot during a safe test window: ```bash sudo reboot ``` After reconnecting, check services: ```bash systemctl is-active mysite-gunicorn nginx ``` Run the public checks: ```bash curl -I https://example.com/ curl https://example.com/health/ curl -I https://example.com/static/admin/css/base.css ``` Confirm the Gunicorn socket exists again: ```bash sudo ls -l /run/mysite/gunicorn.sock ``` The intended request path is: ```text Browser → Nginx on 80/443 → Unix socket /run/mysite/gunicorn.sock → Gunicorn workers → Django WSGI application ``` **Verify:** Nginx and Gunicorn should start automatically, HTTPS should respond, static files should load, and the health endpoint should return `{"status": "ok"}` after reboot. ## Step 14 — Operate, Update, and Clean Up Safely Follow Gunicorn logs with journald: ```bash sudo journalctl -u mysite-gunicorn -f ``` Validate Nginx before every reload: ```bash sudo nginx -t && sudo systemctl reload nginx ``` Before dependency upgrades, review release notes and test the new environment. Do not run a blanket production `pip install --upgrade` without a tested dependency strategy. To stop the application without deleting data: ```bash sudo systemctl disable --now mysite-gunicorn ``` Disable the Nginx site if this hostname is being decommissioned: ```bash sudo rm -f /etc/nginx/sites-enabled/mysite sudo nginx -t sudo systemctl reload nginx ``` Only after backups and decommissioning are confirmed should you remove `/srv/mysite`, `/etc/mysite.env`, or the systemd unit. If the application uses a production database or uploaded media, back those up separately before removal. **Verify:** A stopped deployment should no longer serve the Django application, while unrelated Nginx sites and services should continue to work. ## Conclusion You deployed Django with Gunicorn and Nginx on Ubuntu 24.04 using a non-root service account, a Python virtual environment, a protected environment file, a systemd-managed Unix socket, collected static files, Nginx reverse proxying, HTTPS-aware Django settings, deployment checks, and reboot verification. The important production decisions are not a magic worker count or a synthetic requests-per-second number. Keep secrets out of source control, keep Gunicorn private, let Nginx own the public edge, tune workers from real CPU/memory/database behavior, and run `manage.py check --deploy` against your actual production settings. For related setup work, see [Install pip on Ubuntu 24.04](/learn/tutorials/install-python-pip-ubuntu-24-04), [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04), and [Install Certbot for Nginx on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). ## Sources - [Django 6.0 — How to use Django with Gunicorn](https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/gunicorn/) - [Django 6.0 — Deployment checklist](https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/) - [Django 6.0 — Deploying static files](https://docs.djangoproject.com/en/6.0/howto/static-files/deployment/) - [Gunicorn — Deploying Gunicorn](https://gunicorn.org/deploy/) - [Gunicorn — Design and worker scaling](https://gunicorn.org/design/) - Sources verified: 2026-09-04 --- ### How to Install pip on Ubuntu 24.04 and Use Python venv URL: https://rafftechnologies.com/learn/tutorials/install-python-pip-ubuntu-24-04 Description: Install pip on Ubuntu 24.04, create a Python venv, fix externally-managed-environment errors, use requirements files, and install pipx safely. Ubuntu 24.04 uses Python 3.12 by default, but application dependencies should not be installed into the operating system's Python environment with a normal global `pip install`. Ubuntu follows the externally managed environment model defined by Python packaging standards, so the safe default is to install `python3-pip` and `python3-venv` with APT, create a project-specific virtual environment, and run pip inside that environment. On a Raff Ubuntu VM, this keeps your project packages separate from files managed by the operating system. It also makes deployments easier to reproduce: each application can have its own `.venv`, dependency file, and package versions without changing Python packages required by system tools. This tutorial shows how to install pip on Ubuntu 24.04, create and verify a Python virtual environment, install packages safely, work with requirements files, use pipx for standalone Python command-line applications, troubleshoot `externally-managed-environment`, and clean up the test environment. It uses `python -m pip` inside the virtual environment so the pip command is tied to the Python interpreter you actually intend to use. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root user that has sudo privileges - No public application port or firewall change is required for this tutorial ## Step 1 — Verify the Ubuntu 24.04 Python Version Check the default Python 3 interpreter: ```bash python3 --version ``` Ubuntu 24.04 defaults to Python 3.12. The exact patch version can change through Ubuntu updates, so do not depend on a hard-coded `3.12.x` patch number. Check which executable is being used: ```bash command -v python3 python3 -c 'import sys; print(sys.executable)' ``` On a standard Ubuntu installation, the system interpreter is normally under `/usr/bin/`. **Verify:** `python3 --version` should report Python 3.12.x and `sys.executable` should point to the intended system Python before you create a virtual environment. ## Step 2 — Install pip and venv with APT Refresh package metadata and install the Ubuntu packages for pip and virtual environments: ```bash sudo apt update sudo apt install -y python3-pip python3-venv ``` Check pip through the Python interpreter rather than relying only on a standalone `pip3` command: ```bash python3 -m pip --version ``` Also verify that the `venv` module is available: ```bash python3 -m venv --help >/dev/null && echo 'venv available' ``` Using APT here matters because Ubuntu manages the system Python installation. Avoid using `get-pip.py` to replace the distro-managed pip on a normal Ubuntu server. **Verify:** `python3 -m pip --version` should succeed and the venv check should print `venv available`. ## Step 3 — Understand the externally-managed-environment Error Ubuntu 24.04 marks its system Python as externally managed. Python packaging tools use this marker to avoid modifying packages owned by the operating system. Locate the marker without changing the system: ```bash python3 - <<'PY' import os import sysconfig path = os.path.join(sysconfig.get_path('stdlib'), 'EXTERNALLY-MANAGED') print(path) print('exists:', os.path.exists(path)) PY ``` On Ubuntu 24.04, a normal system-level command such as: ```bash python3 -m pip install requests ``` is expected to be rejected outside a virtual environment with an `externally-managed-environment` message. pip provides `--break-system-packages` as an explicit override, but that bypasses the protection. Do not use it as the normal application-dependency workflow. Use a virtual environment instead. **Verify:** The marker check should report that the externally managed marker exists on the distro-managed Python installation. ## Step 4 — Create a Python Virtual Environment on Ubuntu Create a project directory and a virtual environment named `.venv`: ```bash mkdir -p ~/my-python-project cd ~/my-python-project python3 -m venv .venv ``` Python's standard `venv` module creates an isolated Python environment for the project. Unless `--without-pip` is specified, venv bootstraps pip into the environment. Starting with Python 3.12, setuptools is no longer installed as a core venv dependency by default. Install it only when your project or build process actually requires it. Inspect the environment: ```bash ls -la .venv .venv/bin/python --version .venv/bin/python -m pip --version ``` Add the environment directory to Git ignore rules if this is a version-controlled project: ```bash printf '.venv/\n' >> .gitignore ``` **Verify:** `.venv/bin/python` and `.venv/bin/python -m pip` should both run successfully, and `.venv/` should be excluded from version control. ## Step 5 — Activate the venv and Verify Which Python and pip You Are Using Activate the environment in Bash: ```bash source .venv/bin/activate ``` Check the active executables: ```bash which python python --version python -m pip --version ``` The paths should now point inside `~/my-python-project/.venv/`. Using `python -m pip` is useful because it makes the relationship between the interpreter and pip explicit. It avoids accidentally invoking a pip executable from another Python installation on systems with multiple interpreters. You do not have to activate a venv to use it. Automation and systemd units can call its interpreter directly: ```bash ~/my-python-project/.venv/bin/python -m pip --version ``` **Verify:** `which python` and the pip output should both reference the `.venv` directory. ## Step 6 — Install and Verify a Python Package with pip With the virtual environment active, install a small test dependency: ```bash python -m pip install requests ``` Inspect the installed package: ```bash python -m pip show requests ``` Verify that Python can import it: ```bash python - <<'PY' import requests print('requests version:', requests.__version__) PY ``` Check the package location: ```bash python -c 'import requests; print(requests.__file__)' ``` The path should be inside `.venv`, not the system Python directories. This tutorial intentionally does not start a Flask development server or open a public firewall port. Installing pip and verifying a package does not require exposing an application to the internet. **Verify:** `requests` should import successfully and its file path should be inside your project's `.venv`. :::cta Deploy Your Server Launch a Raff Ubuntu VM and use isolated Python environments for development and application deployment. ::: ## Step 7 — Record and Reinstall Dependencies with a Requirements File For a simple pip-based project, you can record the current environment: ```bash python -m pip freeze > requirements.txt ``` Inspect the file: ```bash cat requirements.txt ``` A requirements file is one common way to reproduce an environment, but it is not the only dependency-management format in Python. Some projects use `pyproject.toml`, lock files, or another dependency tool. Commit the dependency files your project actually uses rather than treating `requirements.txt` as mandatory for every Python project. Test that pip can parse the file: ```bash python -m pip install -r requirements.txt ``` For deployment, review dependency changes before upgrading packages. Avoid a blind `pip install --upgrade` across every production dependency without testing the result. **Verify:** `requirements.txt` should contain the installed dependency set and `python -m pip install -r requirements.txt` should complete without changing the system Python. ## Step 8 — Use pipx for Standalone Python Command-Line Applications A virtual environment is appropriate for libraries used by a project. For standalone Python command-line applications that you want available from your shell, pipx is usually a better fit because it creates a separate environment for each application. Install pipx from Ubuntu's package manager: ```bash sudo apt update sudo apt install -y pipx ``` Add the pipx application directory to your user PATH: ```bash pipx ensurepath ``` You may need to open a new shell before the PATH change is visible. Check pipx: ```bash pipx --version pipx list ``` For example, a CLI package can be installed into its own managed environment with: ```bash pipx install httpie ``` Remove the example when you are finished: ```bash pipx uninstall httpie ``` Do not use pipx for libraries that your application imports. Those belong in the application's venv. **Verify:** `pipx --version` should succeed, and `pipx list` should show only the standalone applications you intentionally installed. ## Step 9 — Troubleshoot pip and venv on Ubuntu 24.04 ### `externally-managed-environment` If pip shows this error, confirm that you are outside a virtual environment: ```bash python3 -c 'import sys; print(sys.prefix); print(sys.base_prefix)' ``` If the two paths are equal, create or activate a venv: ```bash python3 -m venv .venv source .venv/bin/activate python -m pip install ``` Do not reach for `sudo pip install` or `--break-system-packages` as the default fix. ### `No module named venv` or venv creation fails Install the Ubuntu venv package: ```bash sudo apt update sudo apt install -y python3-venv ``` Then retry: ```bash python3 -m venv .venv ``` ### `pip: command not found` Use the interpreter-bound form first: ```bash python3 -m pip --version ``` If pip is missing from the Ubuntu system Python, install the package: ```bash sudo apt install -y python3-pip ``` Inside a venv, use: ```bash python -m pip --version ``` ### A package fails to build from source pip prefers a compatible wheel when one exists. If no wheel is available, a source build may require a compiler or development headers. Read the package's build documentation and install only the system dependencies it actually requires instead of installing a large build-tool bundle preemptively. ### The wrong Python receives the package Compare the interpreter and package location: ```bash which python python -c 'import sys; print(sys.executable)' python -m pip --version ``` All three should refer to the same virtual environment when it is active. **Verify:** After troubleshooting, `python -m pip --version` and an import test should both resolve inside the intended `.venv`. ## Step 10 — Run the Final End-to-End Verification From the project directory with the environment active, run: ```bash python --version python -m pip --version python -c 'import requests; print(requests.__version__)' python -c 'import requests; print(requests.__file__)' python -m pip check ``` `pip check` verifies whether installed packages have compatible declared dependencies. Confirm that the environment is isolated from the system interpreter: ```bash python - <<'PY' import sys print('prefix:', sys.prefix) print('base_prefix:', sys.base_prefix) print('isolated:', sys.prefix != sys.base_prefix) PY ``` Expected result: ```text isolated: True ``` You now have the core Ubuntu 24.04 Python workflow: APT manages the system Python packages, venv isolates application dependencies, and pip installs packages inside that venv. **Verify:** The import should succeed, `pip check` should report no broken requirements, and `isolated` should be `True`. ## Step 11 — Deactivate or Clean Up the Test Environment Leave the active virtual environment: ```bash deactivate ``` Confirm that your shell has returned to the system interpreter: ```bash command -v python3 python3 --version ``` If this was only a disposable test project, remove the entire project directory rather than trying to uninstall each virtual-environment package individually: ```bash rm -rf ~/my-python-project ``` Only run that command if the directory contains no source code or files you need to keep. If you want to rebuild a real project's venv, keep the source and dependency files, remove only `.venv`, and recreate it: ```bash rm -rf .venv python3 -m venv .venv source .venv/bin/activate python -m pip install -r requirements.txt ``` Virtual environments are designed to be disposable and recreated rather than copied between machines. **Verify:** The test `.venv` should be gone when cleanup is intended, while the Ubuntu system Python should continue to work normally. ## Conclusion You installed pip on Ubuntu 24.04 with `python3-pip`, created a Python 3.12 virtual environment with `venv`, installed packages without modifying the externally managed system Python, verified package isolation, recorded dependencies, and used pipx for standalone command-line applications. The key rule is simple: let APT manage the operating system's Python environment and let project-specific virtual environments manage application dependencies. If you see `externally-managed-environment`, treat it as a signal to check whether you should be using a venv rather than as an error to bypass automatically. For production Python deployments, continue with [Deploy Django with Gunicorn and Nginx](/learn/tutorials/deploy-django-nginx-gunicorn-ubuntu-24-04), [Deploy FastAPI with Nginx and systemd](/learn/tutorials/deploy-fastapi-ubuntu-24-04), or [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). ## Sources - [Ubuntu 24.04 LTS release notes](https://documentation.ubuntu.com/release-notes/24.04/) - [Python Packaging User Guide — Externally Managed Environments](https://packaging.python.org/en/latest/specifications/externally-managed-environments/) - [Python 3.12 — Virtual Environments and Packages](https://docs.python.org/3.12/tutorial/venv.html) - [Python Packaging User Guide — Installing packages with pip and venv](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/) - [pipx — Install pipx](https://pipx.pypa.io/latest/how-to/install-pipx.html) - Sources verified: 2026-09-04 --- ### How to Automate Rsync Backups with Cron on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/automate-backups-cron-rsync-ubuntu-24-04 Description: Automate rsync backups on Ubuntu 24.04 with cron, safe --delete dry runs, locking, retention, integrity checks, restore testing, and troubleshooting. Automating rsync backups with cron on Ubuntu 24.04 is useful for application files, configuration directories, and other file-based data that can be copied consistently. On a Raff Linux VM, a safe workflow is to test rsync manually, preview destructive options with `--dry-run`, create versioned restore archives, prevent overlapping runs, schedule the job with cron, and verify that a restore actually works. This tutorial deliberately separates three concepts that are often mixed together: an **rsync mirror** keeps a destination synchronized with the current source, a **versioned archive** gives you an older restore point, and an **off-server copy** protects against loss of the VM itself. A mirror alone is not enough for every recovery scenario, especially when `--delete` is enabled, because deletions at the source can be propagated to the destination. You will build a small backup workflow for `/srv/sample-app`, use rsync for the current mirror, create timestamped compressed archives for retention, verify checksums, schedule both backup and health-check jobs with cron, and perform a real restore test. The example is appropriate for file-based application data. Do not copy a live database data directory with rsync and assume it is transactionally consistent; use the database's supported dump, snapshot, or backup method first. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root sudo user - Enough free disk space for the test backup and retained archives - No public firewall port is required for the local workflow ## Step 1 — Install rsync, cron, and Backup Utilities Install the tools used by the workflow: ```bash sudo apt update sudo apt install -y rsync cron tar gzip coreutils util-linux sudo systemctl enable --now cron ``` Check the installed tools and cron service: ```bash rsync --version | head -n 1 tar --version | head -n 1 flock --version | head -n 1 systemctl is-active cron ``` Do not depend on exact package patch versions in automation; Ubuntu updates can change them while keeping command behavior compatible. **Verify:** `rsync`, `tar`, and `flock` should report versions, and `systemctl is-active cron` should return `active`. ## Step 2 — Create Safe Test Data for the Rsync Backup Create a small application directory so every backup and restore step can be verified without touching production data: ```bash sudo mkdir -p /srv/sample-app/config sudo tee /srv/sample-app/app.txt > /dev/null <<'EOF' Raff rsync backup tutorial test file EOF sudo tee /srv/sample-app/config/settings.env > /dev/null <<'EOF' APP_NAME=raff-rsync-demo APP_ENV=production EOF sudo chown -R root:root /srv/sample-app sudo find /srv/sample-app -type d -exec chmod 750 {} + sudo find /srv/sample-app -type f -exec chmod 640 {} + ``` List the source tree: ```bash sudo find /srv/sample-app -maxdepth 3 -type f -print sudo cat /srv/sample-app/app.txt ``` For a real application, identify what can be copied while the application is running. Configuration files and immutable assets are usually straightforward; live database files, queues, and frequently changing application state may require an application-aware backup step. **Verify:** Both test files should exist and `app.txt` should contain `Raff rsync backup tutorial test file`. ## Step 3 — Create Backup, Log, and Restore Directories Create separate locations for the current rsync mirror, versioned archives, logs, and restore testing: ```bash sudo mkdir -p \ /var/backups/raff-rsync/mirror/sample-app \ /var/backups/raff-rsync/archives \ /var/backups/raff-rsync/logs \ /var/backups/raff-rsync/restore-test sudo chown -R root:root /var/backups/raff-rsync sudo chmod 750 /var/backups/raff-rsync sudo chmod 750 /var/backups/raff-rsync/{mirror,archives,logs,restore-test} ``` Inspect the structure: ```bash sudo find /var/backups/raff-rsync -maxdepth 2 -type d -print ``` Keeping backup data outside the source tree avoids recursive copies where a backup begins copying its own previous output. **Verify:** The `mirror`, `archives`, `logs`, and `restore-test` directories should exist under `/var/backups/raff-rsync`. ## Step 4 — Test the Rsync Backup Command with --dry-run The source path's trailing slash matters. This command copies the **contents** of `/srv/sample-app/` into the destination directory: ```bash sudo rsync -a --itemize-changes --dry-run \ /srv/sample-app/ \ /var/backups/raff-rsync/mirror/sample-app/ ``` The rsync `-a` option is archive mode: it recursively copies files and preserves common metadata such as permissions and timestamps. It does not automatically include every metadata class such as ACLs, extended attributes, or hard links. If those matter to your application, review and test options such as `-A`, `-X`, or `-H` for your destination filesystem. Now preview the behavior that will eventually keep the mirror exact: ```bash sudo rsync -a --delete-delay --itemize-changes --dry-run \ /srv/sample-app/ \ /var/backups/raff-rsync/mirror/sample-app/ ``` `--delete` and its variants remove destination files that no longer exist at the source. Rsync's own documentation recommends using `--dry-run` first because deletion options can be dangerous when source or destination paths are wrong. Do not enable deletion until you have verified both paths and the dry-run output. **Verify:** The dry run should show planned copies without changing the destination. Confirm that the source is `/srv/sample-app/` and the destination is `/var/backups/raff-rsync/mirror/sample-app/` before continuing. ## Step 5 — Create a Locked Rsync Backup Script Create `/usr/local/sbin/raff-rsync-backup.sh`: ```bash sudo tee /usr/local/sbin/raff-rsync-backup.sh > /dev/null <<'EOF' #!/usr/bin/env bash set -Eeuo pipefail umask 077 BACKUP_ROOT="/var/backups/raff-rsync" SOURCE_DIR="/srv/sample-app" MIRROR_DIR="${BACKUP_ROOT}/mirror/sample-app" ARCHIVE_DIR="${BACKUP_ROOT}/archives" LOG_DIR="${BACKUP_ROOT}/logs" LOG_FILE="${LOG_DIR}/backup.log" RETENTION_DAYS=7 STAMP="$(date -u +%Y%m%dT%H%M%SZ)" ARCHIVE_FILE="${ARCHIVE_DIR}/sample-app-${STAMP}.tar.gz" ARCHIVE_TMP="${ARCHIVE_FILE}.part" mkdir -p "$MIRROR_DIR" "$ARCHIVE_DIR" "$LOG_DIR" exec 9>/run/raff-rsync-backup.lock if ! flock -n 9; then printf '%s SKIP backup already running\n' "$(date -Is)" >> "$LOG_FILE" exit 75 fi trap 'rc=$?; printf "%s ERROR exit=%s line=%s\n" "$(date -Is)" "$rc" "$LINENO" >> "$LOG_FILE"; rm -f "$ARCHIVE_TMP"; exit "$rc"' ERR if [ ! -d "$SOURCE_DIR" ]; then printf '%s ERROR source missing: %s\n' "$(date -Is)" "$SOURCE_DIR" >> "$LOG_FILE" exit 1 fi printf '%s START source=%s\n' "$(date -Is)" "$SOURCE_DIR" >> "$LOG_FILE" rsync -a --delete-delay --itemize-changes \ "$SOURCE_DIR"/ \ "$MIRROR_DIR"/ >> "$LOG_FILE" 2>&1 tar -C "$(dirname "$SOURCE_DIR")" \ -czf "$ARCHIVE_TMP" \ "$(basename "$SOURCE_DIR")" gzip -t "$ARCHIVE_TMP" mv "$ARCHIVE_TMP" "$ARCHIVE_FILE" sha256sum "$ARCHIVE_FILE" > "${ARCHIVE_FILE}.sha256" find "$ARCHIVE_DIR" -maxdepth 1 -type f \ \( -name 'sample-app-*.tar.gz' -o -name 'sample-app-*.tar.gz.sha256' \) \ -mmin "+$((RETENTION_DAYS * 1440))" -delete printf '%s OK archive=%s\n' "$(date -Is)" "$ARCHIVE_FILE" >> "$LOG_FILE" EOF sudo chown root:root /usr/local/sbin/raff-rsync-backup.sh sudo chmod 750 /usr/local/sbin/raff-rsync-backup.sh ``` The script adds several safeguards missing from many basic rsync cron examples: - `set -Eeuo pipefail` stops on command and pipeline failures; - `flock` prevents a second backup from starting while the first is still running; - the archive is written to a `.part` file before being renamed into place; - `gzip -t` checks the compressed archive before it is accepted; - a SHA-256 file is written for later integrity verification; - retention uses minutes so the seven-day threshold is explicit; - logs contain START, OK, SKIP, or ERROR states. Check shell syntax before executing it: ```bash sudo bash -n /usr/local/sbin/raff-rsync-backup.sh ``` **Verify:** `bash -n` should exit without output or syntax errors, and the script should be owned by root with mode `750`. ## Step 6 — Run the First Rsync Backup Manually Never make cron the first execution of a new backup script. Run it manually: ```bash sudo /usr/local/sbin/raff-rsync-backup.sh ``` Check the log: ```bash sudo tail -n 20 /var/backups/raff-rsync/logs/backup.log ``` List the current mirror and versioned archives: ```bash sudo find /var/backups/raff-rsync/mirror/sample-app -maxdepth 3 -type f -print sudo ls -lh /var/backups/raff-rsync/archives/ ``` You should have both a current rsync mirror and a timestamped `.tar.gz` archive with a matching `.sha256` file. **Verify:** The log should end with an `OK archive=...` entry, the mirror should contain the two source files, and the archive directory should contain one `.tar.gz` plus its checksum file. ## Step 7 — Verify Backup Integrity and Restore a File Find the newest archive: ```bash LATEST_ARCHIVE="$(sudo find /var/backups/raff-rsync/archives \ -maxdepth 1 -type f -name 'sample-app-*.tar.gz' \ -printf '%T@ %p\n' | sort -nr | head -n 1 | cut -d' ' -f2-)" echo "$LATEST_ARCHIVE" ``` Verify its checksum: ```bash sudo sha256sum -c "${LATEST_ARCHIVE}.sha256" ``` Check that tar can read the full archive index: ```bash sudo tar -tzf "$LATEST_ARCHIVE" >/dev/null ``` Restore into a separate directory rather than overwriting the source: ```bash sudo rm -rf /var/backups/raff-rsync/restore-test/* sudo tar -xzf "$LATEST_ARCHIVE" \ -C /var/backups/raff-rsync/restore-test sudo cat /var/backups/raff-rsync/restore-test/sample-app/app.txt ``` Expected content: ```text Raff rsync backup tutorial test file ``` A successful copy is not enough evidence that recovery works. A restore test is the stronger check. **Verify:** `sha256sum -c` should report `OK`, `tar -tzf` should succeed, and the restored `app.txt` should contain the original text. :::cta Protect Your Server Pair file-level backups with an additional recovery layer when your production recovery plan requires protection beyond the same VM. ::: ## Step 8 — Create a Backup Health Check Create `/usr/local/sbin/raff-rsync-backup-check.sh`: ```bash sudo tee /usr/local/sbin/raff-rsync-backup-check.sh > /dev/null <<'EOF' #!/usr/bin/env bash set -Eeuo pipefail BACKUP_ROOT="/var/backups/raff-rsync" ARCHIVE_DIR="${BACKUP_ROOT}/archives" MIRROR_DIR="${BACKUP_ROOT}/mirror/sample-app" MAX_AGE_MINUTES=1440 LATEST_ARCHIVE="$(find "$ARCHIVE_DIR" \ -maxdepth 1 -type f -name 'sample-app-*.tar.gz' \ -mmin -"$MAX_AGE_MINUTES" \ -printf '%T@ %p\n' | sort -nr | head -n 1 | cut -d' ' -f2-)" if [ -z "$LATEST_ARCHIVE" ]; then echo "FAIL no archive newer than ${MAX_AGE_MINUTES} minutes" exit 1 fi sha256sum -c "${LATEST_ARCHIVE}.sha256" >/dev/null tar -tzf "$LATEST_ARCHIVE" >/dev/null test -f "$MIRROR_DIR/app.txt" echo "OK backup healthy: $LATEST_ARCHIVE" EOF sudo chown root:root /usr/local/sbin/raff-rsync-backup-check.sh sudo chmod 750 /usr/local/sbin/raff-rsync-backup-check.sh ``` Test it manually: ```bash sudo /usr/local/sbin/raff-rsync-backup-check.sh ``` The check confirms recency, checksum validity, archive readability, and the presence of the expected file in the rsync mirror. It does not replace a periodic restore test of the real application. **Verify:** The command should print `OK backup healthy:` followed by the newest archive path. ## Step 9 — Schedule the Rsync Backup with Cron Create a system cron file that runs the backup daily at 02:15 and the health check at 03:00: ```bash sudo tee /etc/cron.d/raff-rsync-backup > /dev/null <<'EOF' SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 15 2 * * * root /usr/local/sbin/raff-rsync-backup.sh 0 3 * * * root /usr/local/sbin/raff-rsync-backup-check.sh >> /var/backups/raff-rsync/logs/health.log 2>&1 EOF sudo chown root:root /etc/cron.d/raff-rsync-backup sudo chmod 644 /etc/cron.d/raff-rsync-backup ``` Files in `/etc/cron.d/` use the system-crontab format, which includes the user field after the five schedule fields. Ubuntu cron monitors these files for changes, so editing the file does not normally require restarting the cron daemon. Check the installed schedule: ```bash sudo cat /etc/cron.d/raff-rsync-backup sudo ls -l /etc/cron.d/raff-rsync-backup systemctl is-active cron ``` **Verify:** The cron file should be owned by root, not group- or world-writable, contain both jobs, and the cron service should be active. ## Step 10 — Verify Cron Timezone, Environment, and Logs Cron jobs run according to the server's configured timezone. Check it before assuming `02:15` means a particular local time: ```bash timedatectl show -p Timezone --value date ``` If the schedule must align with a business timezone, either configure the server timezone intentionally or calculate the cron schedule from the server timezone. Do not assume an interactive SSH shell and cron have the same environment. This tutorial defines an explicit `PATH` in `/etc/cron.d/raff-rsync-backup` and uses absolute script paths so the job does not depend on shell profile files. After the scheduled time passes, inspect logs: ```bash sudo tail -n 50 /var/backups/raff-rsync/logs/backup.log sudo tail -n 50 /var/backups/raff-rsync/logs/health.log sudo journalctl -u cron --since '24 hours ago' --no-pager ``` Cron can mail job output when a suitable mail system is configured, but minimal cloud servers often do not have one. Do not make silent cron mail your only backup-monitoring mechanism; retain logs and connect failures to your normal monitoring or alerting system in production. **Verify:** Confirm the timezone is the one you expect, the backup log contains an `OK` for the scheduled run, and the health log contains a successful check. ## Step 11 — Keep Rsync Mirrors Separate from Versioned and Off-Server Backups An rsync mirror is useful because later runs can transfer only what changed, but a mirror follows the current source state. If a file disappears from the source and a delete option is enabled, the destination copy can disappear too. That is why this tutorial also creates timestamped archives. For a production recovery plan, add an independent copy outside the VM as well. Options include: - a second Linux host reached through SSH and rsync; - object storage using a tool designed for S3-compatible storage, such as the [Raff Object Storage rclone workflow](/learn/tutorials/sync-files-raff-object-storage-rclone); - infrastructure-level protection through [Raff Data Protection](/products/data-protection), depending on your recovery requirements. If you use rsync over SSH, use key-based authentication suitable for automation, verify the remote host key, give the backup account only the access it needs, and test the exact command interactively before scheduling it. For databases, back up through the database's supported mechanism first. Do not rsync a live PostgreSQL or MySQL data directory and call the result a verified database backup. For PostgreSQL, use a database-aware dump or backup workflow before copying the resulting backup artifact off-server. **Verify:** Document where the independent copy lives and confirm that losing the source VM would not also destroy every retained recovery copy. ## Step 12 — Troubleshoot Rsync and Cron Backup Failures ### The rsync cron job works manually but not from cron Check the cron service, explicit PATH, file ownership, and recent cron logs: ```bash systemctl is-active cron sudo cat /etc/cron.d/raff-rsync-backup sudo ls -l /etc/cron.d/raff-rsync-backup sudo journalctl -u cron --since '2 hours ago' --no-pager ``` Cron does not run your interactive shell profile, so commands that depend on aliases, shell initialization, or an interactive SSH agent often fail when scheduled. ### Rsync wants to delete unexpected files Stop and run a dry run: ```bash sudo rsync -a --delete-delay --itemize-changes --dry-run \ /srv/sample-app/ \ /var/backups/raff-rsync/mirror/sample-app/ ``` If the output is not exactly what you expect, correct the source/destination paths before running the real command. ### The backup is skipped with exit code 75 Another run holds the lock. Check whether a backup process is legitimately still active: ```bash ps -ef | grep '[r]aff-rsync-backup.sh' sudo tail -n 20 /var/backups/raff-rsync/logs/backup.log ``` Do not remove a lock simply because a backup takes longer than usual; first determine whether the existing process is healthy or stuck. ### The checksum fails Keep the suspect archive for investigation and create a new backup rather than trusting it: ```bash sudo /usr/local/sbin/raff-rsync-backup.sh sudo /usr/local/sbin/raff-rsync-backup-check.sh ``` A checksum verifies that the archived bytes match the checksum recorded after creation. It does not prove that a changing application was captured at a transactionally consistent moment. ### The disk is filling with backups Inspect archive sizes and free space: ```bash sudo du -sh /var/backups/raff-rsync/* df -h /var/backups/raff-rsync ``` Adjust retention from measured storage usage and recovery requirements. Do not shorten retention blindly if it would remove the only recovery point you need. **Verify:** After correcting the problem, run both scripts manually and confirm the backup log ends with `OK` and the health check passes. ## Step 13 — Run the Final End-to-End Backup and Restore Test Make a controlled change to the source: ```bash echo 'second version' | sudo tee -a /srv/sample-app/app.txt >/dev/null ``` Run a fresh backup and health check: ```bash sudo /usr/local/sbin/raff-rsync-backup.sh sudo /usr/local/sbin/raff-rsync-backup-check.sh ``` Confirm the rsync mirror contains the change: ```bash sudo tail -n 2 /var/backups/raff-rsync/mirror/sample-app/app.txt ``` Restore the newest archive into the test directory: ```bash LATEST_ARCHIVE="$(sudo find /var/backups/raff-rsync/archives \ -maxdepth 1 -type f -name 'sample-app-*.tar.gz' \ -printf '%T@ %p\n' | sort -nr | head -n 1 | cut -d' ' -f2-)" sudo rm -rf /var/backups/raff-rsync/restore-test/* sudo tar -xzf "$LATEST_ARCHIVE" \ -C /var/backups/raff-rsync/restore-test sudo tail -n 2 /var/backups/raff-rsync/restore-test/sample-app/app.txt ``` Finally, confirm the cron schedule and services: ```bash systemctl is-active cron sudo cat /etc/cron.d/raff-rsync-backup sudo tail -n 10 /var/backups/raff-rsync/logs/backup.log ``` The workflow is complete only when the source change reaches the rsync mirror, a new archive is created, the checksum and health check pass, and the changed file can be restored from the archive. **Verify:** Both the mirror and restored archive should include `second version`, the health check should report `OK`, and cron should remain active with both scheduled jobs installed. ## Step 14 — Clean Up the Test Backup Workflow Safely Use this step only if you want to remove the tutorial's test data and schedule. First disable future runs: ```bash sudo rm -f /etc/cron.d/raff-rsync-backup ``` Confirm no backup script is currently running: ```bash ps -ef | grep '[r]aff-rsync-backup.sh' || true ``` Review what will be deleted: ```bash sudo du -sh /var/backups/raff-rsync sudo find /srv/sample-app -maxdepth 3 -type f -print ``` If these are only tutorial files and you have no archive you need to retain, remove them: ```bash sudo rm -f /usr/local/sbin/raff-rsync-backup.sh sudo rm -f /usr/local/sbin/raff-rsync-backup-check.sh sudo rm -rf /var/backups/raff-rsync sudo rm -rf /srv/sample-app ``` Do not adapt this cleanup command to a production path without separately confirming backups and retention requirements. **Verify:** `/etc/cron.d/raff-rsync-backup`, the two tutorial scripts, `/var/backups/raff-rsync`, and `/srv/sample-app` should be absent only when you intentionally completed cleanup. ## Conclusion You automated rsync backups with cron on Ubuntu 24.04, previewed deletion behavior with `--dry-run`, protected the job from overlapping runs, kept a current rsync mirror, created versioned compressed archives, verified checksums, tested a restore, checked cron timezone and logs, and documented the need for an independent off-server copy. The most important distinction is that **synchronization is not automatically the same as a complete backup strategy**. Rsync is excellent for efficient file copying and mirrors, but recovery planning also needs retained versions, restore testing, and a failure domain separate from the source server. For a broader recovery design, see [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies). For off-server object storage, continue with [Sync Files to Raff Object Storage with rclone](/learn/tutorials/sync-files-raff-object-storage-rclone). For database workloads, use a database-aware backup workflow before copying backup artifacts. ## Sources - [rsync(1) official manpage](https://download.samba.org/pub/rsync/rsync.1) - [Ubuntu 24.04 cron(8) manpage](https://manpages.ubuntu.com/manpages/noble/man8/cron.8.html) - [Ubuntu crontab(5) manpage](https://manpages.ubuntu.com/manpages/noble/man5/crontab.5.html) - [GNU tar manual](https://www.gnu.org/software/tar/manual/) - Sources verified: 2026-09-04 --- ### How to Self-Host Next.js on Ubuntu 24.04 with PM2 and Nginx URL: https://rafftechnologies.com/learn/tutorials/deploy-nextjs-ubuntu-24-04-pm2-nginx Description: Self-host Next.js on Ubuntu 24.04 with Node.js 24 LTS, PM2, Nginx, HTTPS, loopback-only app ports, reboot persistence, and production checks. Self-hosting Next.js on Ubuntu 24.04 requires three layers: the Next.js production server, a process manager that keeps it running, and a reverse proxy that handles public HTTP/HTTPS traffic. In this tutorial, you will run a production Next.js application with **Node.js 24 LTS**, keep it alive with **PM2**, bind the application only to `127.0.0.1:3000`, place **Nginx** in front of it, and enable HTTPS with Certbot. This architecture follows the current Next.js self-hosting model. Next.js explicitly recommends placing a reverse proxy such as Nginx in front of the application instead of exposing `next start` directly to the internet. The reverse proxy can handle connection limits, malformed requests, payload limits, TLS, and other edge concerns while the Next.js server handles rendering and application logic. Next.js also manages its own immutable asset caching, so this guide does not duplicate or override framework-generated `Cache-Control` headers. As of September 2026, Node.js 24 is an LTS release and Next.js 16 is the current Active LTS major line. You should still deploy the Next.js version pinned by your application lockfile rather than upgrading a production application blindly during server setup. The original workflow was tested on a Raff Ubuntu 24.04 VM with 1 vCPU and 2 GB RAM. The Node.js release status, current Next.js self-hosting behavior, `next start` options, PM2 startup behavior, and multi-instance caveats were re-verified on September 4, 2026. Prerequisites: * A [Raff Linux VM](/products/linux-vm) running Ubuntu 24.04 * SSH access with a non-root user that has sudo privileges * A Next.js application stored in a Git repository * A `package-lock.json` file if you plan to use `npm ci` * A domain whose DNS can point to the VM * Ports `80/tcp` and `443/tcp` available for Nginx ## Step 1 — Prepare Ubuntu, DNS, and the firewall Update Ubuntu and install the base packages used in this deployment: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y git curl ca-certificates nginx ufw ``` If Ubuntu reports that a reboot is required, reboot before continuing: ```bash sudo reboot ``` Point your domain's `A` record to the VM's public IPv4 address. Add an `AAAA` record only when IPv6 is configured and reachable on the same server. Check DNS from the VM: ```bash dig +short A your-domain.com ``` If `dig` is not installed: ```bash sudo apt install -y dnsutils ``` Before enabling UFW, allow your existing SSH access path: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw --force enable ``` If SSH uses a custom port, allow that port instead of assuming port `22`. **Verify:** ```bash sudo ufw status numbered systemctl is-active nginx dig +short A your-domain.com ``` UFW should allow SSH plus Nginx HTTP/HTTPS traffic, Nginx should be active, and the domain should resolve to the VM's public address. ## Step 2 — Install Node.js 24 LTS with NVM Node.js 24 is an LTS release in September 2026. Install it with the current NVM installer shown on the Node.js download page: ```bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash ``` Load NVM into the current shell: ```bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" ``` Install Node.js 24 and make it the default for new shell sessions: ```bash nvm install 24 nvm alias default 24 nvm use 24 ``` Node.js currently lists v24 as LTS and recommends using an Active LTS or Maintenance LTS release for production applications: [Node.js release schedule](https://nodejs.org/en/about/previous-releases). **Verify:** ```bash node --version npm --version nvm current ``` The Node.js version should begin with `v24.` and `nvm current` should point to the same branch. ## Step 3 — Clone the Next.js application and install locked dependencies Create the application directory: ```bash sudo mkdir -p /var/www/nextjs sudo chown "$USER":"$USER" /var/www/nextjs cd /var/www/nextjs ``` Clone your repository into it: ```bash git clone https://github.com/your-username/your-nextjs-repo.git . ``` Install the exact dependency versions recorded in `package-lock.json`: ```bash npm ci ``` Inspect the installed Next.js version: ```bash npm ls next ``` Next.js currently recommends using a supported Active or Maintenance LTS release. As of September 4, 2026, the current docs are on Next.js 16.3.x, and recent security releases have updated both the 16.x Active LTS and 15.x Maintenance LTS lines. Do not run an unplanned major framework upgrade as part of a server migration; update and test the application separately when necessary. **Verify:** ```bash test -f package.json && echo "package.json found" test -f package-lock.json && echo "package-lock.json found" npm ls next ``` The dependency tree should resolve without a missing Next.js package or lockfile error. ## Step 4 — Configure production environment variables safely Next.js supports both build-time and runtime environment variables. Variables prefixed with `NEXT_PUBLIC_` are exposed to the browser and are inlined into client JavaScript during `next build`, so never put secrets in a `NEXT_PUBLIC_` variable. Create a production-local environment file when your application requires server-side configuration: ```bash cd /var/www/nextjs nano .env.production.local ``` Example: ```dotenv DATABASE_URL=your_server_side_database_url APP_SECRET=your_server_side_secret NEXT_PUBLIC_APP_URL=https://your-domain.com ``` Restrict the file: ```bash chmod 600 .env.production.local ``` Make sure local environment files are excluded from Git: ```bash grep -E '^\.env|\.env\*' .gitignore || true ``` Add an appropriate ignore rule if the repository does not already contain one. Next.js documents that server environment values can be evaluated at runtime for dynamic rendering, while `NEXT_PUBLIC_` variables are embedded into the browser bundle during the build: [Next.js self-hosting environment variables](https://nextjs.org/docs/app/guides/self-hosting#environment-variables). **Verify:** ```bash stat -c '%a %n' .env.production.local 2>/dev/null || true git status --short ``` If the file exists, its mode should be `600`, and it should not appear as a file that Git intends to commit. ## Step 5 — Build the Next.js production application Build the application with the environment variables required by your project already in place: ```bash cd /var/www/nextjs npm run build ``` A successful build creates the `.next` directory. The exact route output varies by Next.js version and application architecture. Do not publish a universal build-time or RAM benchmark. Build memory depends on dependency count, route count, source maps, image processing, TypeScript, bundler behavior, and the application's own code. If the build runs out of memory, measure actual usage before resizing the VM or adding swap. Check the installed application and framework information when troubleshooting a build: ```bash npx next info ``` **Verify:** ```bash test -d .next && echo ".next build directory exists" npm run build --if-present >/dev/null && echo "build command completed" ``` A successful production build should finish without a fatal compiler or dependency error and leave the `.next` output present. ## Step 6 — Test `next start` on localhost only Next.js `next start` defaults to port `3000` and hostname `0.0.0.0`. For this architecture, do not expose the application server directly. Bind it to loopback so only software on the VM can reach it. Start the production server manually: ```bash cd /var/www/nextjs npm run start -- --hostname 127.0.0.1 --port 3000 ``` In a second SSH session, verify the listener: ```bash sudo ss -lntp | grep ':3000' ``` It should show `127.0.0.1:3000`, not `0.0.0.0:3000`. Test the application locally: ```bash curl -I http://127.0.0.1:3000 ``` The current Next.js CLI documents `--hostname` and `--port` for `next start`, with `0.0.0.0` as the default hostname. Explicitly using `127.0.0.1` keeps the application behind Nginx. Stop the manual process with `Ctrl+C` after the test. **Verify:** `curl` should receive an HTTP response from the Next.js application, and port `3000` should listen only on `127.0.0.1`. ## Step 7 — Run Next.js with PM2 Install PM2 under the same Node.js/NVM user that will own the application process: ```bash npm install -g pm2 ``` Create a PM2 ecosystem file: ```bash nano /var/www/nextjs/ecosystem.config.cjs ``` Use one process as the safe default: ```javascript module.exports = { apps: [ { name: 'nextjs-app', cwd: '/var/www/nextjs', script: 'npm', args: [ 'start', '--', '--hostname', '127.0.0.1', '--port', '3000' ], instances: 1, exec_mode: 'fork', watch: false, env: { NODE_ENV: 'production' } } ] } ``` Start it: ```bash cd /var/www/nextjs pm2 start ecosystem.config.cjs ``` Inspect the process and logs: ```bash pm2 status pm2 logs nextjs-app --lines 50 --nostream ``` Starting with one instance avoids introducing multi-instance cache and revalidation consistency problems before you have designed for them. PM2 cluster mode can run Node.js applications across multiple CPUs, but modern Next.js applications may also have per-instance in-memory cache state and cache-tag invalidation requirements. Next.js specifically documents additional cache coordination for multiple self-hosted instances. For a standalone PM2 explanation, see [How to Install PM2 and Deploy Node.js on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04). **Verify:** ```bash pm2 status curl -I http://127.0.0.1:3000 sudo ss -lntp | grep ':3000' ``` `nextjs-app` should be `online`, the local request should succeed, and port `3000` should remain loopback-only. ## Step 8 — Configure PM2 to restore the application after reboot Generate the startup configuration as your application user: ```bash pm2 startup ``` PM2 prints a `sudo env PATH=... pm2 startup systemd ...` command customized for your username, home directory, NVM path, and Node.js version. Copy and run the exact command PM2 prints rather than using a hard-coded example from another server. Save the current process list: ```bash pm2 save ``` PM2's startup documentation requires both the generated startup integration and a saved process list for restoration after reboot. It also notes that when you change the installed Node.js version, you should regenerate the startup script so its PATH points to the current Node.js binary: [PM2 startup scripts](https://pm2.keymetrics.io/docs/usage/startup/). Find the generated service: ```bash systemctl list-unit-files | grep '^pm2-' ``` **Verify:** The PM2 systemd service for your user should be enabled, and `pm2 save` should complete successfully. ## Step 9 — Configure Nginx as the public reverse proxy Next.js recommends a reverse proxy such as Nginx in front of a self-hosted `next start` server. Create the Nginx site: ```bash sudo nano /etc/nginx/sites-available/nextjs ``` Add: ```nginx server { listen 80; listen [::]:80; server_name your-domain.com www.your-domain.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_read_timeout 60s; proxy_connect_timeout 10s; } } ``` `proxy_buffering off` preserves streaming behavior for App Router features such as Suspense and Partial Prerendering. The current Next.js self-hosting guide notes that buffering must be disabled somewhere in the Nginx path when streaming is required. Do not create a separate Nginx cache rule for `/_next/static/` just to force a one-year cache lifetime. Next.js already sends immutable caching headers for hashed immutable assets, and its self-hosting documentation says these headers cannot be overridden by the application. Enable the site: ```bash sudo ln -sf /etc/nginx/sites-available/nextjs \ /etc/nginx/sites-enabled/nextjs sudo rm -f /etc/nginx/sites-enabled/default ``` Test before reloading: ```bash sudo nginx -t sudo systemctl reload nginx ``` **Verify:** ```bash curl -I http://127.0.0.1 -H 'Host: your-domain.com' sudo nginx -t ``` Nginx should return the Next.js response and the configuration test should succeed. ## Step 10 — Enable HTTPS with Certbot Install Certbot and its Nginx plugin: ```bash sudo apt install -y certbot python3-certbot-nginx ``` Request the certificate only after the public DNS records point to this VM and port `80` is reachable: ```bash sudo certbot --nginx --redirect \ -d your-domain.com \ -d www.your-domain.com ``` If you do not use the `www` hostname, omit it from both DNS and the Certbot command. Inspect the installed certificate and test renewal: ```bash sudo certbot certificates sudo certbot renew --dry-run ``` For deeper certificate troubleshooting, follow [How to Secure Nginx with Let's Encrypt on Ubuntu 24.04](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). **Verify:** ```bash curl -I http://your-domain.com curl -I https://your-domain.com ``` HTTP should redirect to HTTPS and the HTTPS request should complete with a valid certificate. :::cta Deploy Your Server Launch an Ubuntu 24.04 Linux VM and use this self-hosted Next.js deployment pattern with PM2, Nginx, and HTTPS. ::: ## Step 11 — Verify reboot persistence and process recovery Before rebooting, save the PM2 process list again after any final process changes: ```bash pm2 save ``` Reboot the VM: ```bash sudo reboot ``` After reconnecting over SSH, reload NVM if your shell has not done so automatically and inspect the application: ```bash pm2 status curl -I http://127.0.0.1:3000 curl -I https://your-domain.com ``` Also inspect the PM2 systemd unit if the process did not return: ```bash systemctl list-units --type=service | grep pm2 ``` Do not use a forced `kill -9` test as the normal deployment workflow. PM2 already restarts processes that crash or exit, while production updates should allow Node.js and Next.js to shut down gracefully when possible. **Verify:** The PM2 process should return as `online` after reboot, localhost port `3000` should respond, and the public HTTPS endpoint should work without manually starting the app. ## Step 12 — Run the final end-to-end production checks Verify the complete request path: ```bash printf 'PM2:\n' pm2 status printf '\nLocal Next.js:\n' curl -I http://127.0.0.1:3000 printf '\nListening socket:\n' sudo ss -lntp | grep ':3000' printf '\nNginx config:\n' sudo nginx -t printf '\nHTTP redirect:\n' curl -I http://your-domain.com printf '\nHTTPS response:\n' curl -I https://your-domain.com printf '\nFirewall:\n' sudo ufw status numbered ``` Inspect the response headers of an actual hashed Next.js static asset in your browser's Network panel or with `curl`. Immutable framework assets should retain the caching behavior generated by Next.js rather than a manually invented Nginx policy. The deployment is complete when: * PM2 reports `nextjs-app` as online * Next.js listens only on `127.0.0.1:3000` * Nginx passes its syntax test * HTTP redirects to HTTPS * HTTPS serves the application successfully * port `3000` is not intentionally opened in UFW * the application returns after a VM reboot **Verify:** All checks above should pass without exposing the Next.js application server directly to the public network. ## Step 13 — Update the Next.js application safely A simple single-instance deployment update looks like this: ```bash cd /var/www/nextjs git pull --ff-only npm ci npm run build pm2 restart nextjs-app pm2 save ``` This sequence intentionally uses `restart` for the single-process baseline. It does not claim zero downtime. PM2's `reload` feature is designed for cluster-mode rolling reloads, but PM2 documents that reload can fall back to a classic restart if graceful reload does not complete. Next.js also documents version-skew and cache-coordination concerns for rolling or multi-instance deployments. If uninterrupted deployments are a hard requirement, design that architecture explicitly instead of assuming that changing `instances` from `1` to `2` makes every Next.js application safe for rolling deployment. Before a framework upgrade, check the installed release and the Next.js support/security policy: ```bash npm ls next npm outdated next || true ``` Test major-version changes in a staging environment before promoting them to production. **Verify:** ```bash pm2 status curl -I http://127.0.0.1:3000 curl -I https://your-domain.com ``` The updated process should be online and both local and public checks should return the expected application response. ## Step 14 — Roll back or remove the tutorial deployment If an application update is bad, prefer deploying a known-good Git revision and rebuilding instead of deleting the whole server: ```bash cd /var/www/nextjs git log --oneline -n 10 ``` Check out the known-good revision according to your normal release process, then run: ```bash npm ci npm run build pm2 restart nextjs-app ``` To remove the test deployment entirely, stop and delete only this PM2 process: ```bash pm2 delete nextjs-app pm2 save ``` Remove the Nginx site: ```bash sudo rm -f /etc/nginx/sites-enabled/nextjs sudo rm -f /etc/nginx/sites-available/nextjs sudo nginx -t sudo systemctl reload nginx ``` Delete the application directory only when its source, uploads, generated files, and environment configuration are no longer needed: ```bash sudo rm -rf /var/www/nextjs ``` Review certificates before deleting any TLS material: ```bash sudo certbot certificates ``` Then delete only the certificate belonging to the retired hostname when appropriate: ```bash sudo certbot delete --cert-name your-domain.com ``` **Verify:** `pm2 status` should no longer list `nextjs-app`, the Nginx site should be absent, and no retired application should remain listening on port `3000`. ## Troubleshooting ### `npm run build` fails Check the Node.js version, installed Next.js version, dependency state, and application-specific build output: ```bash node --version npm --version npm ls next npx next info ``` Use the application's actual error rather than assuming every failed build is caused by low RAM. ### PM2 starts but Next.js immediately exits Inspect the logs: ```bash pm2 logs nextjs-app --lines 100 --nostream ``` Common causes include a missing `.next` build, missing environment variables, a dependency install failure, or port `3000` already being used. Check the port: ```bash sudo ss -lntp | grep ':3000' ``` ### Port 3000 is listening on `0.0.0.0` Confirm that PM2 is using the ecosystem file from this tutorial: ```bash pm2 describe nextjs-app ``` Restart it from the application directory: ```bash cd /var/www/nextjs pm2 delete nextjs-app pm2 start ecosystem.config.cjs pm2 save ``` Verify that `127.0.0.1:3000` is the only intended listener. ### Nginx returns `502 Bad Gateway` Verify Next.js first: ```bash pm2 status curl -I http://127.0.0.1:3000 pm2 logs nextjs-app --lines 50 --nostream ``` Then inspect Nginx: ```bash sudo nginx -t sudo tail -n 50 /var/log/nginx/error.log ``` A `502` usually means Nginx cannot reach the upstream application or the upstream process is failing. ### Streaming responses appear delayed The Next.js App Router supports streaming when self-hosted, but Nginx buffering can delay chunks. Confirm the active Nginx configuration contains: ```nginx proxy_buffering off; ``` Then test and reload: ```bash sudo nginx -t sudo systemctl reload nginx ``` ### The app does not return after reboot Check the generated PM2 service and logs: ```bash systemctl list-unit-files | grep '^pm2-' systemctl --failed ``` If Node.js was upgraded through NVM after the startup service was generated, regenerate PM2's startup integration as documented by PM2: ```bash pm2 unstartup pm2 startup pm2 save ``` Run the exact `sudo` command printed by PM2 during both startup/unstartup operations when requested. ### Multiple PM2 instances serve inconsistent data Next.js keeps caching state per self-hosted instance by default. App Router cache tags and revalidation need coordination when multiple instances are used. Return to one instance while you design a shared cache/tag strategy: ```bash pm2 delete nextjs-app ``` Set the ecosystem file back to: ```javascript instances: 1, exec_mode: 'fork' ``` Then restart: ```bash pm2 start ecosystem.config.cjs pm2 save ``` ## Conclusion You now have a self-hosted Next.js application on Ubuntu 24.04 with Node.js 24 LTS, a loopback-only Next.js production server, PM2 process supervision, Nginx reverse proxying, HTTPS, reboot persistence, and explicit end-to-end verification. The most important production details are not the number of PM2 workers or an arbitrary memory limit. Keep `next start` private behind Nginx, deploy a supported Next.js release, provide secrets through server-only environment variables, preserve Next.js's own cache headers, and treat multi-instance deployments as an architectural change that requires cache and version coordination. Next.js's current self-hosting documentation recommends a reverse proxy and explains caching, streaming, environment variables, and multi-instance behavior: [Next.js Self-Hosting](https://nextjs.org/docs/app/guides/self-hosting). For the process layer, continue with [Install PM2 on Ubuntu 24.04](/learn/tutorials/deploy-nodejs-pm2-ubuntu-24-04). For the web edge, review [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04) and [Secure Nginx with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). --- ### How to Deploy FastAPI on Ubuntu 24.04 with Uvicorn and Nginx URL: https://rafftechnologies.com/learn/tutorials/deploy-fastapi-ubuntu-24-04 Description: Deploy FastAPI on Ubuntu 24.04 with Uvicorn, systemd, Nginx, trusted proxy headers, HTTPS, worker scaling, troubleshooting, and safe cleanup. Deploying FastAPI on Ubuntu 24.04 is a three-layer setup: **FastAPI** provides the ASGI application, **Uvicorn** serves it, and **Nginx** sits in front as the public reverse proxy. On a single Ubuntu VM, systemd can supervise the Uvicorn process, restart it after failures, and start it again after a reboot. This tutorial uses a deliberately simple production baseline: one FastAPI/Uvicorn process bound only to `127.0.0.1:8000`, a dedicated system user, a Python virtual environment, systemd for process lifecycle, Nginx for the public edge, and Certbot for HTTPS. It also explains when Uvicorn workers help and why older FastAPI guides that require `gunicorn -k uvicorn.workers.UvicornWorker` should be updated: Uvicorn's built-in `uvicorn.workers` module is deprecated, while modern FastAPI and Uvicorn can manage multiple workers directly with `--workers`. Raff Technologies appears here as the Ubuntu VM platform used by the original tutorial. The original workflow was tested on Ubuntu 24.04 LTS on a Raff 1 vCPU / 2 GB RAM VM; the FastAPI/Uvicorn worker guidance, proxy-header behavior, and Gunicorn deprecation notes were re-verified against current official documentation on September 4, 2026. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root user that has sudo privileges - A domain pointed to the VM if you want HTTPS - Ports `80/tcp` and `443/tcp` available for Nginx - No public access to port `8000` is required ## Step 1 — Update Ubuntu and install Python, Nginx, and firewall tools Update package metadata and install the required system packages: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y python3 python3-venv python3-pip nginx ufw curl ``` Ubuntu 24.04 uses Python 3.12 as its default Python 3 branch. The exact patch version can change through Ubuntu security and maintenance updates. Before enabling UFW, make sure your SSH access path is allowed: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw --force enable ``` If SSH uses a custom port, allow that port before enabling the firewall. **Verify:** ```bash python3 --version systemctl is-active nginx sudo ufw status numbered ``` Python should report 3.12.x, Nginx should be active, and UFW should allow SSH plus Nginx HTTP/HTTPS traffic. ## Step 2 — Create a dedicated FastAPI service user and application directory Create a system account that cannot log in interactively: ```bash sudo useradd --system --no-create-home --shell /usr/sbin/nologin fastapi ``` Create the application directory: ```bash sudo mkdir -p /srv/fastapi-app sudo chown -R fastapi:fastapi /srv/fastapi-app sudo chmod 750 /srv/fastapi-app ``` A dedicated service user limits the blast radius of an application compromise compared with running the API as root or under a general administrator account. **Verify:** ```bash getent passwd fastapi stat -c '%U:%G %a %n' /srv/fastapi-app ``` The `fastapi` account should use a non-login shell and `/srv/fastapi-app` should be owned by `fastapi:fastapi`. ## Step 3 — Create a Python virtual environment and install FastAPI Create an isolated Python environment for the application: ```bash sudo -u fastapi python3 -m venv /srv/fastapi-app/.venv ``` Install FastAPI with its standard server dependencies inside that venv: ```bash sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m pip install --upgrade pip sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m pip install 'fastapi[standard]' ``` FastAPI's current documentation notes that its standard installation includes Uvicorn plus recommended serving dependencies. Keeping these packages inside the venv avoids modifying Ubuntu's externally managed system Python. For more detail on Ubuntu 24.04 Python isolation, see [How to Install pip on Ubuntu 24.04 and Use Python venv](/learn/tutorials/install-python-pip-ubuntu-24-04). **Verify:** ```bash sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m pip show fastapi uvicorn sudo -u fastapi /srv/fastapi-app/.venv/bin/python -c 'import fastapi, uvicorn; print(fastapi.__version__, uvicorn.__version__)' ``` Both packages should import successfully from `/srv/fastapi-app/.venv`. ## Step 4 — Create a minimal FastAPI application and health endpoint Create `/srv/fastapi-app/main.py`: ```bash sudo tee /srv/fastapi-app/main.py > /dev/null <<'PY' from fastapi import FastAPI app = FastAPI(title="Example API") @app.get("/") async def root(): return {"status": "ok"} @app.get("/health") async def health(): return {"status": "healthy"} PY ``` Set ownership and permissions: ```bash sudo chown fastapi:fastapi /srv/fastapi-app/main.py sudo chmod 640 /srv/fastapi-app/main.py ``` A simple `/health` endpoint gives systemd, Nginx, monitoring, and your deployment process a stable path to test. **Verify:** ```bash sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m py_compile /srv/fastapi-app/main.py ``` The command should exit without a Python syntax error. ## Step 5 — Test FastAPI with Uvicorn on localhost Run the application manually before creating a service: ```bash cd /srv/fastapi-app sudo -u fastapi ./.venv/bin/uvicorn main:app \ --host 127.0.0.1 \ --port 8000 ``` In a second SSH session, check the listener: ```bash sudo ss -lntp | grep ':8000' ``` Then test the API: ```bash curl -sS http://127.0.0.1:8000/health ``` Expected response: ```json {"status":"healthy"} ``` Keep the application bound to `127.0.0.1`. Nginx will be the public entry point; port `8000` does not need to be exposed through UFW or any external firewall. Stop the manual Uvicorn process with `Ctrl+C` after testing. **Verify:** Uvicorn should respond locally on `127.0.0.1:8000`, and `ss` should not show `0.0.0.0:8000`. ## Step 6 — Create a protected environment file for application secrets Create a configuration directory outside the application source tree: ```bash sudo install -d -m 750 -o root -g fastapi /etc/fastapi ``` Create the environment file: ```bash sudo tee /etc/fastapi/fastapi.env > /dev/null <<'EOF' APP_ENV=production APP_SECRET=replace-with-a-real-secret EOF ``` Restrict it so root can modify it and the FastAPI service group can read it: ```bash sudo chown root:fastapi /etc/fastapi/fastapi.env sudo chmod 640 /etc/fastapi/fastapi.env ``` Do not put secrets into source control, Nginx configuration, or publicly visible environment-variable prefixes. Your application can read these values from the process environment with `os.environ`, Pydantic Settings, or your preferred settings layer. **Verify:** ```bash stat -c '%U:%G %a %n' /etc/fastapi/fastapi.env ``` The file should be owned by `root:fastapi` with mode `640`. ## Step 7 — Create the FastAPI systemd service Create `/etc/systemd/system/fastapi.service`: ```bash sudo tee /etc/systemd/system/fastapi.service > /dev/null <<'EOF' [Unit] Description=FastAPI application After=network.target [Service] Type=simple User=fastapi Group=fastapi WorkingDirectory=/srv/fastapi-app EnvironmentFile=/etc/fastapi/fastapi.env ExecStart=/srv/fastapi-app/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000 --proxy-headers --forwarded-allow-ips=127.0.0.1 Restart=on-failure RestartSec=5 NoNewPrivileges=true PrivateTmp=true ProtectHome=true ProtectSystem=strict ProtectKernelTunables=true ProtectControlGroups=true RestrictSUIDSGID=true [Install] WantedBy=multi-user.target EOF ``` The forwarded-header settings matter because Nginx terminates public HTTP/HTTPS and forwards requests to Uvicorn. FastAPI's proxy documentation warns that forwarded headers should be trusted only from known proxy addresses. Here, the application listens only on loopback and trusts forwarded headers only from `127.0.0.1`, where Nginx connects. If your real application must write uploaded files, generated documents, SQLite databases, or other local state, explicitly grant a writable path rather than weakening the whole systemd sandbox. Reload systemd and start the service: ```bash sudo systemctl daemon-reload sudo systemctl enable --now fastapi ``` **Verify:** ```bash sudo systemctl is-active fastapi sudo systemctl is-enabled fastapi curl -sS http://127.0.0.1:8000/health ``` The service should be active, enabled, and return the health JSON locally. ## Step 8 — Inspect FastAPI logs and service failures with journalctl Check recent service logs: ```bash sudo journalctl -u fastapi -n 50 --no-pager ``` Follow logs during troubleshooting: ```bash sudo journalctl -u fastapi -f ``` Inspect the exact command and service properties systemd loaded: ```bash sudo systemctl cat fastapi sudo systemctl show fastapi -p MainPID -p ExecMainStatus -p NRestarts ``` Do not rely only on `systemctl status`; journal logs usually contain the Python import error, missing environment variable, permission failure, or bind error that caused startup to fail. **Verify:** The journal should show a successful Uvicorn startup without a repeated crash/restart loop. ## Step 9 — Configure Nginx as a reverse proxy for FastAPI Create the Nginx site: ```bash sudo tee /etc/nginx/sites-available/fastapi > /dev/null <<'EOF' server { listen 80; listen [::]:80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 10s; proxy_read_timeout 60s; } } EOF ``` The `X-Forwarded-*` headers preserve the original client/protocol information. Uvicorn will accept them only from the trusted loopback proxy configured in the systemd command. Do not add WebSocket `Upgrade` headers unless your application actually has WebSocket endpoints. Standard FastAPI HTTP APIs do not need them. Enable the site and remove the default site if it is unused: ```bash sudo ln -sf /etc/nginx/sites-available/fastapi /etc/nginx/sites-enabled/fastapi sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t sudo systemctl reload nginx ``` For the base web-server setup, see [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). **Verify:** ```bash curl -sS http://127.0.0.1 -H 'Host: your-domain.com' | head sudo nginx -t ``` Nginx should proxy to FastAPI successfully and the syntax test should pass. ## Step 10 — Decide whether `/docs` and `/openapi.json` should be public FastAPI generates Swagger UI at `/docs` and the OpenAPI schema at `/openapi.json` by default. That is convenient for development and public APIs, but internal or private APIs may not want those endpoints reachable from the internet. If the documentation should remain public, no extra Nginx location is required; the main proxy already forwards those paths. If the documentation should be private, control it intentionally. Options include disabling docs in your FastAPI application, applying application authentication, or restricting the paths at the proxy layer. For example, to deny the two paths publicly in Nginx: ```nginx location = /docs { return 404; } location = /openapi.json { return 404; } ``` Do not assume hiding documentation is a substitute for API authentication and authorization. **Verify:** Test `/docs` and `/openapi.json` from the public side and confirm they match your intended exposure policy. ## Step 11 — Enable HTTPS with Certbot Make sure the domain resolves to this VM and port `80` is publicly reachable, then install Certbot: ```bash sudo apt install -y certbot python3-certbot-nginx ``` Request the certificate and redirect HTTP to HTTPS: ```bash sudo certbot --nginx --redirect -d your-domain.com ``` Check the certificate and simulate renewal: ```bash sudo certbot certificates sudo certbot renew --dry-run ``` For full DNS, port-80, renewal, and ACME troubleshooting, use [How to Install Certbot for Nginx on Ubuntu 24.04 with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). **Verify:** ```bash curl -I http://your-domain.com/health curl -sS https://your-domain.com/health ``` HTTP should redirect to HTTPS and the HTTPS endpoint should return the expected health response. :::cta Deploy Your Server Launch a Raff Ubuntu VM and deploy FastAPI behind a private Uvicorn listener, systemd, Nginx, and HTTPS. ::: ## Step 12 — Scale FastAPI with Uvicorn workers only when measurements justify it Modern FastAPI and Uvicorn can start multiple worker processes directly. Gunicorn is not required just to use more CPU cores. For example, a two-worker Uvicorn command is: ```bash /srv/fastapi-app/.venv/bin/uvicorn main:app \ --host 127.0.0.1 \ --port 8000 \ --workers 2 \ --proxy-headers \ --forwarded-allow-ips=127.0.0.1 ``` FastAPI's current deployment documentation demonstrates both `fastapi ... --workers` and `uvicorn ... --workers` for process replication. Do not use a universal formula such as “two workers per CPU” or “always four workers.” Each worker is a separate process with its own application memory and database connections. Benchmark your application, watch memory, observe latency and connection-pool usage, then select a worker count that fits the VM and workload. If you change the systemd `ExecStart` to include workers, reload and restart: ```bash sudo systemctl daemon-reload sudo systemctl restart fastapi ``` **Verify:** ```bash ps -ef | grep '[u]vicorn' sudo systemctl is-active fastapi curl -sS https://your-domain.com/health ``` The expected number of Uvicorn worker processes should be visible and the public health endpoint should remain healthy. ## Step 13 — Understand FastAPI, Uvicorn, and Gunicorn in 2026 Uvicorn is the ASGI server in this tutorial. systemd manages whether that server process is running. Nginx handles the public network edge. Older FastAPI deployment articles often use: ```bash gunicorn -k uvicorn.workers.UvicornWorker main:app ``` Do not copy that exact worker path into a new deployment. Uvicorn's current documentation marks the `uvicorn.workers` module as deprecated and says it will be removed in a future release. If your organization specifically wants Gunicorn's process-management features, Uvicorn now points to the separate `uvicorn-worker` package and worker path: ```bash python -m pip install gunicorn uvicorn-worker gunicorn main:app -w 4 -k uvicorn_worker.UvicornWorker ``` That remains an optional architecture choice, not a requirement for FastAPI. For a straightforward Ubuntu VM under systemd, running Uvicorn directly is simpler and FastAPI itself documents native Uvicorn worker support. **Verify:** If you use Gunicorn, confirm your configuration does not reference the deprecated `uvicorn.workers.UvicornWorker` import path. ## Step 14 — Run final end-to-end checks and test reboot persistence Check the full stack before rebooting: ```bash printf 'FastAPI service:\n' sudo systemctl is-active fastapi printf '\nLocal Uvicorn:\n' curl -sS http://127.0.0.1:8000/health printf '\nListener:\n' sudo ss -lntp | grep ':8000' printf '\nNginx:\n' sudo nginx -t printf '\nHTTPS:\n' curl -sS https://your-domain.com/health printf '\nFirewall:\n' sudo ufw status numbered ``` Then reboot: ```bash sudo reboot ``` After reconnecting: ```bash sudo systemctl is-active fastapi nginx curl -sS http://127.0.0.1:8000/health curl -sS https://your-domain.com/health ``` The API should return without manually starting Uvicorn. **Verify:** FastAPI and Nginx should be active after reboot, port `8000` should remain loopback-only, and the public HTTPS health endpoint should succeed. ## Step 15 — Update or remove the FastAPI deployment safely For an application update, first update code and dependencies according to your repository workflow. With a requirements file, a simple deployment pattern could be: ```bash sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m pip install -r /srv/fastapi-app/requirements.txt sudo -u fastapi /srv/fastapi-app/.venv/bin/python -m compileall -q /srv/fastapi-app sudo systemctl restart fastapi ``` Check logs immediately after restart: ```bash sudo journalctl -u fastapi -n 50 --no-pager curl -sS https://your-domain.com/health ``` If the release fails, restore the previously tested code/dependency state and restart the service. Do not upgrade every dependency blindly on the production server without a tested lock or release process. To remove the tutorial deployment entirely, first stop future starts: ```bash sudo systemctl disable --now fastapi sudo rm -f /etc/systemd/system/fastapi.service sudo systemctl daemon-reload ``` Remove the Nginx site: ```bash sudo rm -f /etc/nginx/sites-enabled/fastapi sudo rm -f /etc/nginx/sites-available/fastapi sudo nginx -t sudo systemctl reload nginx ``` Review certificate names before deleting TLS material: ```bash sudo certbot certificates ``` Delete the application files and service account only when you have confirmed there is no application data or secret you need to retain: ```bash sudo rm -rf /srv/fastapi-app sudo rm -rf /etc/fastapi sudo userdel fastapi ``` **Verify:** The service should no longer exist or start on boot, Nginx should pass its syntax test, and no process should be listening on `127.0.0.1:8000` for the removed application. ## Troubleshooting ### `externally-managed-environment` appears during pip install You are probably installing into Ubuntu's system Python instead of the application venv. Use: ```bash /srv/fastapi-app/.venv/bin/python -m pip install ``` Do not use `sudo pip install` as the normal fix. ### `fastapi.service` enters a restart loop Inspect the journal: ```bash sudo journalctl -u fastapi -n 100 --no-pager ``` Then test the exact Uvicorn command manually as the service user. ### Nginx returns `502 Bad Gateway` Test Uvicorn directly: ```bash curl -v http://127.0.0.1:8000/health sudo systemctl status fastapi --no-pager sudo journalctl -u fastapi -n 50 --no-pager ``` If localhost works, inspect Nginx: ```bash sudo nginx -t sudo tail -n 50 /var/log/nginx/error.log ``` ### HTTPS redirects point to `http://` or localhost Confirm that Nginx sets `X-Forwarded-Proto` and that Uvicorn trusts forwarded headers only from the loopback proxy: ```bash sudo systemctl cat fastapi sudo nginx -T | grep -E 'X-Forwarded-(Proto|For|Host)' ``` The systemd command in this tutorial uses `--proxy-headers --forwarded-allow-ips=127.0.0.1`. ### WebSockets fail through Nginx Only add WebSocket forwarding when the application actually uses WebSockets. A typical Nginx WebSocket location needs `Upgrade` and `Connection` handling in addition to HTTP/1.1 proxying. Keep those headers scoped to WebSocket traffic instead of adding them universally to a basic HTTP API. ### More workers make performance worse Reduce the worker count and measure again. Workers duplicate process memory, application startup work, database pools, and other per-process resources. Worker count is an application-capacity decision, not a CPU-count rule. ## Conclusion You deployed FastAPI on Ubuntu 24.04 with an isolated Python environment, a dedicated service account, Uvicorn bound to localhost, systemd process supervision, trusted proxy headers, Nginx reverse proxying, HTTPS, reboot persistence, and an explicit cleanup path. The key 2026 deployment change is that Gunicorn is no longer required simply to run multiple FastAPI/Uvicorn workers. FastAPI and Uvicorn support `--workers` directly. If you do choose Gunicorn, avoid the deprecated `uvicorn.workers.UvicornWorker` path and use the current separate worker package instead. For the Python environment layer, see [Install pip and Python venv on Ubuntu 24.04](/learn/tutorials/install-python-pip-ubuntu-24-04). For Nginx and TLS, continue with [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04) and [Install Certbot for Nginx](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). ## Sources - [FastAPI — Run a Server Manually](https://fastapi.tiangolo.com/deployment/manually/) - [FastAPI — Server Workers](https://fastapi.tiangolo.com/deployment/server-workers/) - [FastAPI — Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/) - [Uvicorn — Deployment](https://www.uvicorn.org/deployment/) - Sources verified: 2026-09-04 --- ### How to Connect Two Raff VMs with a Private VPC Network URL: https://rafftechnologies.com/learn/tutorials/connect-two-raff-vms-private-network Description: Connect two Raff VMs over a private VPC on Ubuntu 24.04. Verify private routing, firewall rules, service access, throughput tests, and safe cleanup. Connecting two Raff VMs over a private VPC lets the servers communicate on private IPv4 addresses instead of exposing every service on public interfaces. A typical use case is a public application VM talking to a database, cache, worker, or internal API over the VPC while only the public edge accepts internet traffic. This tutorial uses two Ubuntu 24.04 VMs in one Raff VPC. You will create or select a private CIDR, attach both VMs, identify the private interfaces without assuming they are named `eth1`, verify the Linux route that carries private traffic, allow only a temporary test flow through your firewalls, measure connectivity with `iperf3`, and then apply the same pattern to an application-to-database connection. Raff's current VPC product page documents isolated layer-2 VPCs, managed NAT/DNS/DHCP, stateful security groups, RFC 1918 CIDRs from `/16` through `/28`, and unmetered private traffic on a 25 Gbps internal network. Treat that 25 Gbps figure as the network-fabric specification, not a guaranteed per-VM `iperf3` result: actual throughput depends on the VM, guest networking, protocol, CPU, and test method. Private-network isolation also does **not** mean application traffic is cryptographically encrypted, so continue using TLS or another secure protocol when your threat model requires encryption in transit. Prerequisites: - Two Raff VMs running Ubuntu 24.04 with SSH access - A non-root sudo user on both VMs - Access to Raff VPC/networking settings in the dashboard - A planned RFC 1918 CIDR that does not conflict with networks you may later connect through VPN or peering - UFW or another host firewall configured deliberately on both VMs The examples use `10.20.0.10` for **VM-A** and `10.20.0.11` for **VM-B**. Replace them with the private addresses assigned to your VMs. ## Step 1 — Choose a private CIDR before creating the VPC Raff VPC currently accepts private IPv4 CIDRs from `/16` through `/28` and can suggest a `/24` automatically. Use an RFC 1918 range and consider future networks before choosing it. Common private address space includes: ```text 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ``` For this tutorial, use an example network such as: ```text 10.20.0.0/24 ``` Do not automatically reuse the same CIDR as your office LAN, client VPN pool, another cloud VPC, or a network you expect to peer later. Overlap can make future routing and VPN design harder. **Verify:** Record the CIDR you will use and confirm it does not overlap with any network that must later route to this VPC. ## Step 2 — Create the Raff VPC Open the VPC/networking section of the Raff dashboard and create a new VPC. Give it a descriptive name such as: ```text prod-app-vpc ``` Choose the CIDR from Step 1 or accept an appropriate auto-suggested range. Raff's current VPC model includes the managed gateway, DNS, and DHCP with the VPC, so attached VM interfaces can receive private addressing from the network. The exact dashboard labels can evolve, but the workflow is the same: create a VPC, choose or accept the CIDR, then wait until the VPC reports that it is ready before attaching workloads. **Verify:** The Raff dashboard should show the VPC as ready and display the expected CIDR, for example `10.20.0.0/24`. ## Step 3 — Attach VM-A and VM-B to the same VPC Attach both VMs to the VPC from the Raff dashboard. The two VMs must belong to the same private network for the direct private-IP test in this tutorial. Record the assigned private addresses. For example: ```text VM-A: 10.20.0.10 VM-B: 10.20.0.11 ``` Do not assume the private Linux interface will be named `eth1`. Modern Ubuntu guests may use predictable names such as `ens4`, `ens7`, or another device name depending on how the NIC is presented. If the dashboard exposes security groups for the VM or VPC, do not create a broad `allow any from the entire VPC` rule just for convenience. In later steps, permit only the temporary test flow or the actual service flow you need. **Verify:** Both VM detail views should show attachment to the same VPC and a private IPv4 address from the VPC CIDR. ## Step 4 — Identify the private interface and address on Ubuntu SSH to VM-A and list interfaces in compact form: ```bash ip -br addr ``` Then list IPv4 routes: ```bash ip -4 route ``` Repeat on VM-B. You are looking for the interface that owns each VM's VPC address. Example output might resemble: ```text ens3 UP 203.0.113.10/24 ens7 UP 10.20.0.10/24 ``` On VM-B, the private interface may similarly own `10.20.0.11/24`. Do **not** create a Netplan file simply because an old tutorial expected `eth1`. First verify the actual device, dashboard attachment, DHCP state, and existing Netplan configuration. Writing a guessed interface name or route into Netplan can break remote networking. Useful diagnostics are: ```bash networkctl list sudo netplan status --all ``` **Verify:** Each VM should show one interface with its expected private VPC address, regardless of the interface's device name. ## Step 5 — Verify that Linux routes peer traffic through the private NIC From VM-A, ask the kernel how it would reach VM-B: ```bash ip route get 10.20.0.11 ``` Expected structure: ```text 10.20.0.11 dev src 10.20.0.10 ``` From VM-B, check the reverse path: ```bash ip route get 10.20.0.10 ``` This test is more useful than assuming that any successful request used the VPC. It tells you which interface and source IP Linux selected for that destination. You can also inspect the neighbor table after traffic has been attempted: ```bash ip neigh show ``` **Verify:** `ip route get` on each VM should select the private interface and the VM's private source IP for the peer's private address. ## Step 6 — Allow only the temporary private-network test flow For a deterministic connectivity test, use `iperf3` on TCP port `5201`. Install it on both VMs: ```bash sudo apt update sudo apt install -y iperf3 ``` On VM-B, allow only VM-A's private IP to reach the test port through UFW: ```bash sudo ufw allow from 10.20.0.10 to any port 5201 proto tcp ``` If a Raff security group also filters private traffic, add an equivalent temporary inbound rule for TCP `5201` from `10.20.0.10/32` to VM-B. Keep the source specific rather than opening the port to the internet or the entire VPC without a reason. Check the host rule: ```bash sudo ufw status numbered ``` If UFW is currently inactive, do not enable it blindly on a remote server. Follow the [Ubuntu 24.04 UFW tutorial](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) so SSH access is allowed before the firewall is enabled. **Verify:** VM-B should have a rule allowing TCP `5201` only from VM-A's private IP, and any Raff security-group rule should match the same intended source and destination. ## Step 7 — Test private connectivity with ping and iperf3 A ping can provide a quick reachability signal when ICMP is allowed: ```bash ping -c 4 10.20.0.11 ``` Do not treat a failed ping as proof that the VPC is broken; ICMP may be blocked while TCP traffic is allowed. For the application-layer test, start `iperf3` on VM-B and bind it specifically to the private address: ```bash iperf3 -s -B 10.20.0.11 ``` From VM-A, connect to VM-B's private address: ```bash iperf3 -c 10.20.0.11 ``` The output reports measured throughput for this specific test. Do not compare it with a fixed expected number from an old benchmark. A result is affected by VM CPU, guest networking, TCP behavior, concurrent load, and the test duration. While the test is active, you can confirm the connection endpoints on VM-B: ```bash ss -tnp | grep ':5201' ``` Stop the `iperf3` server with `Ctrl+C` when finished. **Verify:** `iperf3` should complete over `10.20.0.11`, and the connection should use the private source/destination addresses rather than the VMs' public IPs. ## Step 8 — Replace broad VPC access with service-specific rules The production goal is not “all private VMs trust each other.” The goal is to allow the exact application relationship you need. For example, if VM-A is an application server and VM-B runs PostgreSQL, allow only VM-A's private address to reach PostgreSQL on VM-B: ```bash sudo ufw allow from 10.20.0.10 to any port 5432 proto tcp ``` If MySQL is the backend instead: ```bash sudo ufw allow from 10.20.0.10 to any port 3306 proto tcp ``` Mirror that least-privilege rule in the Raff security group when a security group protects the VM. Then configure the application to use the database's **private** address, for example: ```dotenv DB_HOST=10.20.0.11 DB_PORT=5432 ``` The database service itself should also bind only to the interfaces it actually needs. Do not make a database publicly reachable merely because its firewall currently blocks the port. For PostgreSQL configuration and authentication, follow [Install PostgreSQL on Ubuntu 24.04](/learn/tutorials/install-postgresql-ubuntu-24-04) rather than copying database settings from a networking tutorial. **Verify:** The application VM should be able to reach the required service port over VM-B's private IP, while unrelated VPC sources should not gain access simply because they share the subnet. ## Step 9 — Keep private-network isolation separate from encryption Raff's current VPC documentation describes per-VPC layer-2 isolation and private addressing that is separated from other tenants and the public internet. That is a network isolation boundary. It is not a replacement for protocol-level security. Private IP traffic is not automatically equivalent to a WireGuard tunnel or TLS session. For credentials, database sessions, administration, or sensitive service-to-service traffic, use the encryption and authentication controls appropriate to the protocol and threat model. Examples include: - PostgreSQL or MySQL TLS for database connections; - HTTPS or mTLS for internal APIs where required; - SSH for administrative access; - WireGuard/IPsec when you need an encrypted tunnel between networks or endpoints. For client-to-server private access, see [Set Up WireGuard VPN on Ubuntu 24.04](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04). **Verify:** Document which private flows rely only on VPC isolation and which also require application-layer or tunnel encryption. :::cta Create a Private Network Use Raff VPC to connect application, database, worker, and internal-service VMs over private IPs. ::: ## Step 10 — Run the final end-to-end VPC verification On VM-A, verify the route and private connection again: ```bash ip route get 10.20.0.11 ``` If your production service is PostgreSQL, test the private TCP port without authenticating to the database: ```bash nc -vz 10.20.0.11 5432 ``` Install `netcat-openbsd` first if `nc` is unavailable: ```bash sudo apt install -y netcat-openbsd ``` On VM-B, inspect listening sockets and confirm the service is not unintentionally bound to every public interface: ```bash sudo ss -lntp ``` Then review both firewall layers: ```bash sudo ufw status numbered ``` In the Raff dashboard, review the security group attached to VM-B and confirm it contains only the private flows you intend. The final architecture should resemble: ```text Internet | v VM-A public edge 10.20.0.10 | | private VPC v VM-B database/internal service 10.20.0.11 ``` **Verify:** The peer route should use the private NIC, the required service should work over the private IP, port `5201` should no longer be needed after testing, and public exposure should be limited to intentionally public services. ## Step 11 — Troubleshoot private VPC connectivity systematically ### The private IP does not appear in Ubuntu Check the dashboard attachment first, then inspect the guest: ```bash ip -br addr networkctl list sudo netplan status --all ``` Do not assume the NIC is `eth1`, and do not write a new Netplan file until you understand the existing network configuration. If the VPC attachment is present in Raff but the guest never receives DHCP configuration, gather these outputs before changing networking or contacting support. ### `ip route get` chooses the public interface Confirm both private IPs belong to the same VPC CIDR and inspect the full route table: ```bash ip -4 route ``` A conflicting or more-specific route from VPN software, custom Netplan, or another NIC can override the expected path. ### Ping fails but the route is correct ICMP may be filtered. Test the actual allowed TCP service instead: ```bash nc -vz 10.20.0.11 5201 ``` or run the `iperf3` test from Step 7. ### `iperf3` reports connection refused On VM-B, confirm the server is listening on the private address: ```bash ss -lntp | grep ':5201' ``` Then review UFW and the Raff security group: ```bash sudo ufw status numbered ``` ### The service works on the public IP but not the private IP The application may be bound only to its public address or localhost. Inspect listeners with: ```bash sudo ss -lntp ``` Configure that service to bind to the intended private address according to its own documentation, then restart and verify it. **Verify:** After fixing the identified layer, rerun `ip route get`, then the actual TCP test. Do not consider the issue solved based only on the presence of a private IP. ## Step 12 — Remove temporary test access and tools After `iperf3` testing, remove the temporary UFW rule from VM-B. First find its rule number: ```bash sudo ufw status numbered ``` Then delete only the TCP `5201` rule that you created for VM-A: ```bash sudo ufw delete ``` Remove the equivalent temporary Raff security-group rule if you created one. If `iperf3` was installed only for this test and is no longer needed: ```bash sudo apt remove -y iperf3 ``` Do **not** detach a production VPC or delete its CIDR merely to clean up the tutorial. Detaching the private NIC can break database, cache, internal API, monitoring, backup, or administrative paths that now depend on the private address. Only when this was a disposable lab and no dependencies remain should you detach the VMs and remove the VPC from the Raff dashboard. **Verify:** TCP `5201` should no longer be allowed or listening, while the production service-specific private rules you intentionally created should remain in place. ## Conclusion You connected two Raff VMs through a private VPC, identified their actual Ubuntu network interfaces, verified the kernel route that carries private traffic, tested TCP connectivity without exposing a test port publicly, and replaced broad subnet trust with service-specific firewall rules. The important production pattern is simple: use the VPC for private reachability, security groups and host firewalls for least-privilege access, and protocol-level encryption where the data requires it. Do not infer network performance from an old `iperf3` screenshot or treat a private IP as a substitute for authentication and TLS. For broader architecture decisions, continue with [VPC Architecture for Multi-VM Applications](/learn/guides/understanding-private-cloud-networks) and [Public vs Private Networking](/learn/guides/private-networking-public-vs-private-traffic). The current Raff VPC product details are available at [Raff VPC](/products/vpc). ## Sources - [Raff VPC](/products/vpc) - [VPC Architecture for Multi-VM Applications](/learn/guides/understanding-private-cloud-networks) - [RFC 1918 — Address Allocation for Private Internets](https://datatracker.ietf.org/doc/html/rfc1918) - Product and networking guidance verified: 2026-09-04 --- ### How to Set Up an SFTP-Only User on Ubuntu 24.04 with Chroot URL: https://rafftechnologies.com/learn/tutorials/set-up-sftp-only-user-ubuntu-24-04 Description: Set up an SFTP-only user on Ubuntu 24.04 with OpenSSH chroot, internal-sftp, safe directory permissions, forwarding restrictions, and verification. An SFTP-only account on Ubuntu 24.04 lets a user transfer files over SSH without giving that account an interactive shell or unrestricted access to the server filesystem. The safest baseline is to use OpenSSH's built-in `internal-sftp`, place the user inside a root-owned chroot, give them a writable subdirectory inside that jail, and disable every SSH forwarding feature that the account does not need. This tutorial uses a group-based OpenSSH configuration so you can add more restricted users later without duplicating per-user `Match` blocks. It also fixes several common mistakes in older SFTP guides: assuming a writable chroot root is allowed, editing only the main `sshd_config`, leaving a `Match` block open inside `sshd_config.d`, restarting the wrong daemon blindly, and checking syntax without verifying the effective configuration that actually applies to the restricted user. Ubuntu's current OpenSSH documentation recommends modular files in `/etc/ssh/sshd_config.d/`, running `sshd -t` before a restart, and restarting `ssh.service` after normal server configuration changes. OpenSSH also requires every component of `ChrootDirectory` to be root-owned and not writable by other users or groups. `internal-sftp` is useful here because it runs inside `sshd` and does not require copying a shell, libraries, or device nodes into the jail. Raff Technologies is the Ubuntu VM platform used by the original tutorial. The original setup was tested on Ubuntu 24.04 LTS on a Raff 2 vCPU / 4 GB RAM VM; the OpenSSH configuration and Ubuntu service guidance were re-verified on September 4, 2026. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root sudo user - A second SSH session available while you change `sshd` settings - Port `22/tcp` or your existing SSH port allowed by the firewall - A test username that is not your current administrator account The examples use the restricted account `sftpclient` and group `sftponly`. ## Step 1 — Verify OpenSSH and keep your current admin session open Check that the OpenSSH server package is installed: ```bash dpkg -s openssh-server | grep -E '^(Status|Version):' ``` If it is not installed: ```bash sudo apt update sudo apt install -y openssh-server ``` Check the service: ```bash sudo systemctl is-active ssh.service ``` Check the server binary version: ```bash /usr/sbin/sshd -V 2>&1 | head -1 ``` Before changing anything, keep your current working SSH session open and, if possible, open a second administrator session. Do not test new SFTP rules by modifying the account you are currently using to administer the VM. Ubuntu's current OpenSSH server documentation warns that a bad SSH configuration can lock you out and recommends validating the configuration before restarting the service. **Verify:** `openssh-server` should be installed, `ssh.service` should be active, and you should still have a working administrator session that is not the SFTP test account. ## Step 2 — Back up the SSH configuration before editing it Create a timestamped backup of the main configuration and the current snippet directory: ```bash sudo cp -a /etc/ssh/sshd_config \ "/etc/ssh/sshd_config.backup.$(date +%Y%m%d-%H%M%S)" sudo cp -a /etc/ssh/sshd_config.d \ "/etc/ssh/sshd_config.d.backup.$(date +%Y%m%d-%H%M%S)" ``` Ubuntu includes this line near the top of its default server configuration: ```text Include /etc/ssh/sshd_config.d/*.conf ``` That means drop-in files are the preferred place for a small custom policy such as an SFTP-only group. Ubuntu also documents that OpenSSH generally uses the first value it obtains for most directives, which makes snippet ordering and Match scope worth checking rather than assuming. **Verify:** ```bash ls -ld /etc/ssh/sshd_config.backup.* /etc/ssh/sshd_config.d.backup.* | tail ``` A backup of both the main file and snippet directory should exist before you continue. ## Step 3 — Create the SFTP-only group and user Create the group: ```bash sudo groupadd --force sftponly ``` Create the restricted test user if it does not already exist: ```bash sudo useradd -m -s /bin/bash -G sftponly sftpclient ``` Set a password for the initial test: ```bash sudo passwd sftpclient ``` This tutorial does **not** rely on `/usr/sbin/nologin` to enforce SFTP-only behavior. The OpenSSH `Match Group` block will force `internal-sftp`, disable forwarding, and disable TTY allocation. This avoids mixing shell-policy behavior with SFTP subsystem testing and makes the actual SSH restriction explicit and testable. If the account already exists, add it to the group without removing its other memberships: ```bash sudo usermod -aG sftponly sftpclient ``` **Verify:** ```bash id sftpclient getent passwd sftpclient ``` The output should show membership in `sftponly`. Do not continue if you accidentally added your current administrator account to this group. ## Step 4 — Create a root-owned chroot with a writable upload directory OpenSSH checks `ChrootDirectory` ownership unconditionally. Every component of the chroot path must be root-owned and must not be writable by another user or group. Use the user's home directory as the jail root: ```bash sudo chown root:root /home/sftpclient sudo chmod 755 /home/sftpclient ``` Create a writable directory inside the jail: ```bash sudo mkdir -p /home/sftpclient/uploads sudo chown sftpclient:sftpclient /home/sftpclient/uploads sudo chmod 750 /home/sftpclient/uploads ``` The resulting model is: ```text /home/sftpclient root:root 755 <- chroot root /home/sftpclient/uploads sftpclient:* 750 <- writable area ``` Do not make `/home/sftpclient` user-writable and do not use `chmod 777`. OpenSSH's Ubuntu 24.04 man page states that all path components used for `ChrootDirectory` must be root-owned and not writable by any other user or group. **Verify:** ```bash namei -l /home/sftpclient stat -c '%U:%G %a %n' /home/sftpclient /home/sftpclient/uploads ``` The chroot root should be `root:root` and not group/other writable; the `uploads` directory should be writable by `sftpclient`. ## Step 5 — Create an isolated OpenSSH Match Group policy Create a dedicated snippet: ```bash sudo tee /etc/ssh/sshd_config.d/60-sftp-only.conf > /dev/null <<'EOF' Match Group sftponly ChrootDirectory %h ForceCommand internal-sftp -d /uploads DisableForwarding yes PermitTTY no PermitUserRC no Match all EOF ``` The important directives are: - `ChrootDirectory %h` — makes the user's real home directory the jail root; - `ForceCommand internal-sftp -d /uploads` — forces the in-process SFTP server and starts the user in the writable `/uploads` directory inside the jail; - `DisableForwarding yes` — disables TCP, agent, X11, and StreamLocal forwarding in one directive; - `PermitTTY no` — prevents TTY allocation; - `PermitUserRC no` — prevents execution of user SSH rc files; - `Match all` — ends the restricted Match scope before parsing continues. That final `Match all` is especially important in a drop-in file. Ubuntu loads `/etc/ssh/sshd_config.d/*.conf` from the main configuration, and a `Match` context continues until another `Match` directive or end of the full configuration stream. Ending the snippet with `Match all` prevents later global settings from accidentally remaining inside the `sftponly` Match context. You do not need to replace Ubuntu's global `Subsystem sftp ...` line for this design. `ForceCommand internal-sftp` directly forces the in-process SFTP server for matching users. **Verify:** ```bash sudo cat /etc/ssh/sshd_config.d/60-sftp-only.conf ``` The file should contain exactly one `Match Group sftponly` block followed by `Match all`. ## Step 6 — Validate both syntax and the effective Match configuration First run OpenSSH's syntax test: ```bash sudo sshd -t ``` No output means the syntax and host-key checks passed. Then inspect the effective configuration for `sftpclient`. `sshd -T` prints the resulting configuration, while `-C` applies Match rules for a simulated connection: ```bash sudo sshd -T \ -C user=sftpclient,host=localhost,addr=127.0.0.1,laddr=127.0.0.1,lport=22 \ | grep -E '^(chrootdirectory|forcecommand|disableforwarding|permittty|permituserrc) ' ``` Expected values include: ```text chrootdirectory %h forcecommand internal-sftp -d /uploads disableforwarding yes permittty no permituserrc no ``` This check is stronger than syntax validation alone because it proves that the `Match Group` policy actually applies to the account you intend to restrict. **Verify:** `sshd -t` should produce no error and `sshd -T -C ...` should show the SFTP-only settings above for `sftpclient`. ## Step 7 — Restart OpenSSH safely and verify administrator access first Ubuntu's current OpenSSH server documentation recommends applying normal `sshd` configuration changes with: ```bash sudo systemctl restart ssh.service ``` Do that only after `sshd -t` succeeds: ```bash sudo systemctl restart ssh.service ``` Immediately verify the service: ```bash sudo systemctl is-active ssh.service ``` Before closing your original SSH window, open a **new administrator SSH session** and make sure it works. Ubuntu 24.04 can use socket activation in some OpenSSH configurations, which matters particularly when changing listener settings such as `Port` or `ListenAddress`. This tutorial does not change those listener directives. For the Match policy used here, follow Ubuntu's documented `ssh.service` restart path and validate the actual result with a fresh connection. **Verify:** `ssh.service` should be active and a new administrator SSH connection should succeed before you test `sftpclient`. ## Step 8 — Test SFTP login, landing directory, upload, and download From another machine or another local terminal, connect with SFTP: ```bash sftp sftpclient@SERVER_IP ``` After authentication, confirm the working directory: ```text sftp> pwd ``` Because the Match policy uses `internal-sftp -d /uploads`, the user should start in: ```text Remote working directory: /uploads ``` Create a local test file before connecting, or use an existing harmless file. From the SFTP prompt: ```text sftp> put test-upload.txt sftp> ls -la sftp> get test-upload.txt test-download.txt ``` Confirm that the user cannot leave the jail: ```text sftp> cd / sftp> ls ``` The `/` visible to this user is the chroot root, not the real server filesystem root. Paths such as the server's real `/etc` are outside the jail. **Verify:** The user should land in `/uploads`, be able to upload/download there, and remain confined to the chroot filesystem. ## Step 9 — Verify shell commands, TTYs, and forwarding are blocked SFTP success is only half the test. Confirm that the same account cannot obtain a shell command channel: ```bash ssh sftpclient@SERVER_IP 'id' ``` Because `ForceCommand internal-sftp` replaces the requested command, this should not execute `id` as a shell command. Try an interactive SSH session: ```bash ssh sftpclient@SERVER_IP ``` The account should not receive a normal shell prompt. The `DisableForwarding yes` rule also blocks the account from being used for SSH forwarding. For example, a local forwarding request should fail rather than create a tunnel: ```bash ssh -N -L 15432:127.0.0.1:5432 sftpclient@SERVER_IP ``` Do not leave this command running if your client behaves unexpectedly; stop it with `Ctrl+C`. OpenSSH documents that `ForceCommand` alone does not disable other forwarding channels, which is why this tutorial also sets `DisableForwarding yes`. **Verify:** `sftpclient` should transfer files through SFTP but should not receive a shell, execute arbitrary SSH commands, allocate a TTY, or create SSH forwarding channels. ## Step 10 — Restrict network access when the SFTP client has a stable source IP SFTP uses SSH transport, so the network port is the server's SSH port — normally TCP `22` unless you deliberately changed it. If this SFTP account is used only from a known office, VPN, CI runner, or partner IP, firewall restriction adds a useful independent control. For example, with UFW and a stable client address `198.51.100.20`: ```bash sudo ufw allow from 198.51.100.20 to any port 22 proto tcp ``` Do **not** remove your broader administrator SSH rule until you have confirmed how all legitimate administrators connect. A firewall change can lock you out independently of the SFTP configuration. If your VM also uses a cloud-side security group, apply the same source-IP principle there when appropriate. For a complete firewall workflow, use [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). **Verify:** Review the firewall with `sudo ufw status numbered` and confirm it still permits every required administrator path as well as the intended SFTP client source. ## Step 11 — Monitor SFTP authentication and errors with journalctl Ubuntu's current server documentation uses the `ssh.service` journal for OpenSSH troubleshooting. Follow logs while you test: ```bash sudo journalctl -fu ssh.service ``` Or inspect recent entries: ```bash sudo journalctl -u ssh.service -n 100 --no-pager ``` Useful problems to look for include: - `bad ownership or modes for chroot directory` — a path component is not root-owned or is writable by another user/group; - authentication failures — password/key or account-policy problem; - `Connection closed` immediately after authentication — often a chroot, directory, or Match-policy problem; - missing `/uploads` — the forced start directory does not exist inside the jail. Do not depend on hard-coded `/var/log/auth.log` availability for every Ubuntu logging setup; the systemd journal is the most portable first check on current Ubuntu Server. **Verify:** A successful SFTP connection should appear in the SSH journal without a chroot ownership error or repeated authentication failure. ## Step 12 — Add another SFTP-only user without editing sshd_config again Create another user and add it to the same group: ```bash sudo useradd -m -s /bin/bash -G sftponly client2 sudo passwd client2 ``` Make the new home directory a valid chroot root: ```bash sudo chown root:root /home/client2 sudo chmod 755 /home/client2 ``` Create the writable directory: ```bash sudo mkdir -p /home/client2/uploads sudo chown client2:client2 /home/client2/uploads sudo chmod 750 /home/client2/uploads ``` No OpenSSH configuration edit is necessary because the group Match rule already exists. No service restart is required merely because a new user joined the group. Check that the effective Match configuration applies to the second user as well: ```bash sudo sshd -T \ -C user=client2,host=localhost,addr=127.0.0.1,laddr=127.0.0.1,lport=22 \ | grep -E '^(chrootdirectory|forcecommand|disableforwarding) ' ``` **Verify:** `client2` should inherit the same chroot, forced SFTP command, and forwarding restrictions without another `sshd_config` change. ## Step 13 — Run the final end-to-end SFTP security check Run the final checklist before using the account for real file transfers. On the server: ```bash sudo sshd -t sudo systemctl is-active ssh.service stat -c '%U:%G %a %n' /home/sftpclient /home/sftpclient/uploads sudo sshd -T \ -C user=sftpclient,host=localhost,addr=127.0.0.1,laddr=127.0.0.1,lport=22 \ | grep -E '^(chrootdirectory|forcecommand|disableforwarding|permittty|permituserrc) ' ``` From the client: ```bash sftp sftpclient@SERVER_IP ``` Inside SFTP: ```text pwd put test-upload.txt ls -la ``` In another client terminal: ```bash ssh sftpclient@SERVER_IP 'uname -a' ``` The SFTP operation should work, while the arbitrary SSH command should not run as a shell command. :::cta Deploy Your SFTP Server Launch a Raff Ubuntu VM and use OpenSSH chroot rules to provide restricted SFTP-only file access. ::: **Verify:** The final state is correct only when file transfer works, the user is confined to the jail, the chroot root is not user-writable, arbitrary SSH commands do not execute, forwarding is disabled, and normal administrator SSH access still works. ## Step 14 — Roll back or remove the SFTP-only setup safely To remove only the Match policy, first move the snippet out of the active `.conf` path: ```bash sudo mv /etc/ssh/sshd_config.d/60-sftp-only.conf \ /etc/ssh/60-sftp-only.conf.disabled ``` Validate before restarting: ```bash sudo sshd -t ``` Then apply the change: ```bash sudo systemctl restart ssh.service ``` If the restricted account is no longer needed, remove it only after confirming that uploaded files have been archived or transferred elsewhere: ```bash sudo userdel sftpclient ``` Do not use `userdel -r` until you have deliberately decided to delete `/home/sftpclient` and its uploaded files. If this was a disposable lab and the data is safe to delete: ```bash sudo rm -rf /home/sftpclient ``` Remove the group only when no remaining account depends on it: ```bash getent group sftponly sudo groupdel sftponly ``` **Verify:** `sudo sshd -t` should still pass, administrator SSH should work after the restart, and only the users/data you intentionally removed should be gone. ## Troubleshooting ### `fatal: bad ownership or modes for chroot directory` Inspect every component of the jail path: ```bash namei -l /home/sftpclient ``` `/`, `/home`, and `/home/sftpclient` must satisfy OpenSSH's chroot ownership rules. The jail root should be root-owned and not writable by other users/groups. Only directories inside the jail, such as `/uploads`, should be user-writable. ### SFTP authenticates and then disconnects immediately Run: ```bash sudo journalctl -u ssh.service -n 100 --no-pager ``` Then confirm the forced start directory exists: ```bash ls -ld /home/sftpclient/uploads ``` Also re-check the effective policy: ```bash sudo sshd -T \ -C user=sftpclient,host=localhost,addr=127.0.0.1,laddr=127.0.0.1,lport=22 \ | grep -E '^(chrootdirectory|forcecommand|disableforwarding) ' ``` ### The user can connect by SFTP but cannot upload to `/` That is expected. The chroot root must not be writable by the restricted user. Upload into `/uploads`, which is intentionally owned by `sftpclient`. ### The SFTP user unexpectedly gets a shell Check group membership: ```bash id sftpclient ``` Then check the effective OpenSSH policy with `sshd -T -C`. If the account is not in `sftponly` or the Match rule is not being applied, fix that before allowing the account to remain active. ### `sshd -t` fails after editing the snippet Do not restart OpenSSH. Read the exact syntax error, fix the file, and rerun: ```bash sudo sshd -t ``` Only restart `ssh.service` when the syntax test succeeds. ### SFTP works but SSH port forwarding also works The Match rule is either not applying or `DisableForwarding yes` is missing. Check the effective configuration with `sshd -T -C` and confirm: ```text disableforwarding yes ``` ## Conclusion You now have an SFTP-only OpenSSH account on Ubuntu 24.04 with a root-owned chroot, a writable upload directory, forced `internal-sftp`, forwarding disabled, no TTY allocation, explicit Match-scope termination, effective-configuration testing, service logs, end-to-end validation, and a rollback path. The two details that prevent most SFTP chroot failures are straightforward: keep the chroot root owned by root and non-writable by the restricted user, and verify the **effective** OpenSSH Match configuration instead of assuming a syntactically valid file is applying the rules you intended. For key-based administrator access, see [Configure SSH Keys on Ubuntu](/learn/tutorials/configure-ssh-keys-ubuntu). For host firewall policy, use [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). For broader host protection, continue with [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Ubuntu Server — OpenSSH server](https://ubuntu.com/server/docs/how-to/security/openssh-server/) - [Ubuntu 24.04 sshd_config(5)](https://manpages.ubuntu.com/manpages/noble/man5/sshd_config.5.html) - [Ubuntu 24.04 sshd(8)](https://manpages.ubuntu.com/manpages/noble/man8/sshd.8.html) - [Ubuntu 24.04 sftp(1)](https://manpages.ubuntu.com/manpages/noble/man1/sftp.1.html) - OpenSSH guidance verified: 2026-09-04 --- ### How to Set Up a Caddy Reverse Proxy on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy Description: Set up Caddy as a reverse proxy on Ubuntu 24.04 with automatic HTTPS, localhost-only upstreams, safe firewall rules, WebSockets, logs, and rollback. A Caddy reverse proxy on Ubuntu 24.04 can put a public HTTPS domain in front of an application that listens only on localhost. The production pattern is simple: keep your application on a private listener such as `127.0.0.1:8080`, let Caddy accept traffic on ports 80 and 443, and point a Caddyfile `reverse_proxy` directive at the local upstream. Caddy handles several details that older reverse-proxy tutorials often configure manually. For qualifying public hostnames, automatic HTTPS obtains and renews certificates and redirects HTTP to HTTPS. The `reverse_proxy` handler also manages the standard `X-Forwarded-For`, `X-Forwarded-Proto`, and `X-Forwarded-Host` headers by default, and WebSocket upgrades work without adding Nginx-style `Connection` or `Upgrade` header rules. This tutorial installs Caddy from its official Debian/Ubuntu repository, creates a localhost-only demo backend, validates DNS and firewall state without risking SSH lockout, configures the reverse proxy, verifies HTTPS and WebSockets behavior, enables structured access logging, tests a second upstream pattern, and includes a safe rollback path. Raff Technologies is the VM platform used by the original tutorial. The original setup was tested on Ubuntu 24.04 LTS on a Raff 1 vCPU / 2 GB RAM VM; Caddy's current installation, reverse-proxy, automatic HTTPS, and systemd guidance were re-verified on September 4, 2026. Prerequisites: - A Raff Linux VM running Ubuntu 24.04 - SSH access with a non-root sudo user - A domain or subdomain whose DNS can point to the VM - Ports 80 and 443 available for Caddy - A backend application that can listen on localhost or a private network address The examples use `app.example.com` and a demo backend on `127.0.0.1:8080`. Replace them with your real hostname and application port. ## Step 1 — Check DNS, existing listeners, and SSH access before changing the firewall Confirm Ubuntu: ```bash cat /etc/os-release ``` Check whether another web server already owns ports 80 or 443: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` Check the domain's IPv4 and IPv6 DNS records: ```bash dig +short A app.example.com dig +short AAAA app.example.com ``` If `dig` is unavailable: ```bash sudo apt update sudo apt install -y dnsutils ``` An `A` record should point to the VM's public IPv4 address. If an `AAAA` record exists, it must also point to working IPv6 service on this server; stale IPv6 DNS can break validation or client access even when IPv4 is correct. If Nginx, Apache, or another reverse proxy is already serving production traffic on ports 80/443, do not stop it blindly. Plan the migration or move Caddy to a different server before continuing. Also keep your current SSH session open while making network changes. **Verify:** Ubuntu should report 24.04, the intended hostname should resolve to this VM, and you should know which process currently owns ports 80 and 443 before installing Caddy. ## Step 2 — Install Caddy from the official Debian/Ubuntu repository Install the repository prerequisites: ```bash sudo apt update sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl ``` Add Caddy's official stable signing key: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \ sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg ``` Add the official stable repository: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \ sudo tee /etc/apt/sources.list.d/caddy-stable.list ``` Make the APT files readable and install Caddy: ```bash sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install -y caddy ``` Caddy's official package automatically installs and starts `caddy.service` for Caddyfile-based configurations. Official installation instructions: [Caddy — Install](https://caddyserver.com/docs/install). **Verify:** ```bash caddy version systemctl is-active caddy systemctl is-enabled caddy ``` The version command should return a Caddy v2 release, and the service should be active and enabled unless another process is preventing it from binding to the required ports. ## Step 3 — Create a localhost-only demo backend Install Python for a temporary test backend: ```bash sudo apt install -y python3 ``` Create a small document root: ```bash sudo install -d -o root -g root -m 755 /srv/caddy-proxy-demo ``` Create a test page: ```bash cat <<'EOF' | sudo tee /srv/caddy-proxy-demo/index.html > /dev/null Caddy Reverse Proxy Test

Caddy reverse proxy is working

EOF ``` Start the demo server in the foreground from a second SSH session or terminal: ```bash python3 -m http.server 8080 \ --bind 127.0.0.1 \ --directory /srv/caddy-proxy-demo ``` Python's built-in HTTP server is only a disposable test upstream. Do not use it as the production application server. **Verify:** From the VM, run `curl -fsS http://127.0.0.1:8080 | grep 'Caddy reverse proxy is working'`. The command should return the heading. ## Step 4 — Confirm the backend is not exposed publicly Check the listener: ```bash sudo ss -lntp | grep ':8080' ``` The local address should be: ```text 127.0.0.1:8080 ``` not: ```text 0.0.0.0:8080 ``` Do not add a UFW or cloud firewall rule for port 8080 when Caddy and the application run on the same VM. The entire point of this topology is that the public client reaches Caddy, while Caddy reaches the application through loopback. A real Node.js, FastAPI, Django, Go, or other application should follow the same principle unless it intentionally lives on another private host. **Verify:** Port 8080 should listen only on `127.0.0.1`, and there should be no public firewall rule exposing TCP 8080. ## Step 5 — Back up the Caddyfile and configure the reverse proxy Back up the packaged configuration: ```bash sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak ``` Replace the active configuration with the reverse-proxy site: ```bash sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF' app.example.com { reverse_proxy 127.0.0.1:8080 } EOF ``` That is enough for the basic proxy. Caddy's current `reverse_proxy` documentation says incoming headers are passed through by default, while Caddy sets or augments `X-Forwarded-For` and sets `X-Forwarded-Proto` and `X-Forwarded-Host` itself. Do not add boilerplate such as: ```text header_up X-Forwarded-For ... header_up X-Forwarded-Proto ... header_up Host ... ``` unless your application has a specific, documented requirement that differs from Caddy's defaults. **Verify:** `sudo cat /etc/caddy/Caddyfile` should show your real hostname and the intended localhost upstream. ## Step 6 — Format and validate the Caddyfile before reloading Format the configuration: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile ``` Validate it: ```bash sudo caddy validate --config /etc/caddy/Caddyfile ``` `caddy validate` does more than parse syntax; Caddy documents that it loads and provisions modules as if starting the configuration, without actually starting it. That makes it a useful check before changing the running service. Do not reload a configuration that fails validation. **Verify:** `caddy validate` should complete successfully without a configuration or provisioning error. ## Step 7 — Allow HTTP and HTTPS without enabling UFW blindly Check UFW first: ```bash sudo ufw status verbose ``` If UFW is already **active** and your SSH access is already safely allowed, add web traffic: ```bash sudo ufw allow 80/tcp sudo ufw allow 443/tcp ``` If UFW is **inactive**, do not run `ufw enable` merely because this tutorial uses Caddy. Enabling a firewall on a remote server without first validating your SSH rule can lock you out. Configure SSH deliberately first using [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), then enable it if host-level firewalling is part of your plan. If a Raff-side security group or another cloud firewall protects the VM, allow public TCP 80 and 443 there as well. For normal public automatic HTTPS, Caddy's documentation expects ports 80 and 443 to be externally reachable. Port 80 is also used for automatic HTTP-to-HTTPS redirects and can be used for ACME HTTP challenge validation; port 443 serves HTTPS and can be used for TLS-ALPN validation. **Verify:** If UFW is active, `sudo ufw status numbered` should preserve your working SSH access and allow TCP 80/443. The external firewall should also permit the intended public web traffic. ## Step 8 — Reload Caddy and verify automatic HTTPS Apply the validated configuration with a graceful reload: ```bash sudo systemctl reload caddy ``` Caddy recommends reloading rather than stopping the service for Caddyfile configuration changes. Check recent logs: ```bash sudo journalctl -u caddy -n 100 --no-pager ``` Test HTTPS: ```bash curl -I https://app.example.com ``` Test the HTTP redirect: ```bash curl -I http://app.example.com ``` For a qualifying public hostname with correct DNS and external reachability, Caddy automatically manages a publicly trusted certificate and normally redirects HTTP to HTTPS. **Verify:** HTTPS should reach the demo backend successfully, HTTP should redirect to HTTPS, and the Caddy journal should not show repeating certificate, DNS, bind, or upstream errors. ## Step 9 — Verify the full client → Caddy → backend path Check the backend directly from the VM: ```bash curl -fsS http://127.0.0.1:8080 | \ grep 'Caddy reverse proxy is working' ``` Then check the same content through public HTTPS: ```bash curl -fsS https://app.example.com | \ grep 'Caddy reverse proxy is working' ``` Inspect the listeners: ```bash sudo ss -lntp | grep -E ':(80|443|8080)\b' ``` The expected topology is: ```text Internet | | TCP 80 / 443 v Caddy | | 127.0.0.1:8080 v Application ``` :::cta Deploy Your Reverse Proxy Launch a Raff Ubuntu VM and put your application behind a Caddy reverse proxy with automatic HTTPS. ::: **Verify:** Caddy should own the public web ports, the application should remain on localhost, and the content returned through HTTPS should match the local upstream response. ## Step 10 — Use Caddy's built-in WebSocket proxying instead of manual upgrade headers Caddy's reverse proxy supports WebSockets directly. When the client sends an HTTP upgrade request, Caddy performs the upgrade and turns the connection into a bidirectional tunnel. For a WebSocket-capable application on port 3000, the normal configuration is still just: ```caddyfile ws.example.com { reverse_proxy 127.0.0.1:3000 } ``` You do not need Nginx-style boilerplate such as manually setting `Connection: upgrade` and `Upgrade: websocket` for the standard case. One operational detail matters: Caddy documents that active WebSocket connections are closed by default when the configuration is reloaded. Applications normally reconnect, but long-lived connection workloads can consider `stream_close_delay` or `stream_timeout` after measuring their actual behavior. **Verify:** For your real WebSocket application, connect through the HTTPS/WSS hostname and confirm messages flow in both directions without adding manual upgrade headers. ## Step 11 — Handle reverse-proxy headers and upstream trust deliberately When Caddy is directly internet-facing, its default forwarded-header behavior is usually the correct baseline. Caddy ignores client-supplied values for its managed `X-Forwarded-*` headers by default to reduce spoofing risk, then sets the forwarding information it knows itself. If another reverse proxy or CDN sits in front of Caddy, client IP handling changes. In that architecture, configure Caddy's `trusted_proxies` only for the actual proxy/CDN address ranges rather than trusting arbitrary incoming forwarded headers. Do not copy a broad `trusted_proxies private_ranges` or `0.0.0.0/0` rule without understanding which machine is the immediate peer. Your application also needs to be configured to trust proxy headers only from the Caddy hop when its framework requires explicit proxy trust. **Verify:** Document whether Caddy is the first public proxy. If another proxy exists in front, verify that only the known proxy address ranges are trusted for client-IP parsing. ## Step 12 — Proxy to HTTPS upstreams without disabling certificate verification If Caddy and the backend are on the same VM, loopback HTTP is often the simplest transport: ```caddyfile app.example.com { reverse_proxy 127.0.0.1:8080 } ``` If the upstream itself requires HTTPS and has a valid certificate, specify the HTTPS URL: ```caddyfile app.example.com { reverse_proxy https://backend.example.internal } ``` Current Caddy versions automatically handle the upstream `Host` value needed for normal HTTPS upstream certificate verification. Do **not** solve a private-certificate error by adding: ```text tls_insecure_skip_verify ``` Caddy's documentation explicitly states that this disables TLS handshake verification and is vulnerable to man-in-the-middle attacks. For an internal CA or self-signed upstream, establish trust with an appropriate `tls_trust_pool` and configure the correct TLS server name when necessary. **Verify:** If you use an HTTPS upstream, Caddy should connect without `tls_insecure_skip_verify`, and the backend certificate should validate against a trusted CA or explicitly configured trust pool. ## Step 13 — Add access logging and a second reverse-proxy site Caddy's site-level `log` directive enables HTTP access logging. Update the Caddyfile: ```caddyfile app.example.com { log reverse_proxy 127.0.0.1:8080 } api.example.com { log reverse_proxy 127.0.0.1:9000 } ``` Only add the second site when `api.example.com` actually points to this VM and a backend is listening on the configured address. Format, validate, and reload: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo caddy validate --config /etc/caddy/Caddyfile sudo systemctl reload caddy ``` With the packaged systemd service, Caddy's output is available through the systemd journal: ```bash sudo journalctl -u caddy -n 100 --no-pager ``` Do not confuse access logs with application logs. Caddy can tell you that a request reached the proxy and what response it produced, while your upstream application still needs its own logs for application errors and business logic. **Verify:** The Caddyfile should validate after adding `log`, requests to the configured site should appear in Caddy's logs, and every hostname should map only to an upstream that actually exists. ## Step 14 — Run the final verification and roll back safely if needed Run the complete check: ```bash sudo caddy validate --config /etc/caddy/Caddyfile systemctl is-active caddy systemctl is-enabled caddy sudo ss -lntp | grep -E ':(80|443|8080)\b' curl -I http://app.example.com curl -I https://app.example.com curl -fsS https://app.example.com | \ grep 'Caddy reverse proxy is working' sudo journalctl -u caddy -p warning -n 50 --no-pager ``` The final state is healthy when Caddy is active and enabled, ports 80/443 terminate at Caddy, the backend remains private, HTTP redirects to HTTPS, the HTTPS response reaches the application, and there are no unresolved repeating errors. To roll back the Caddyfile, first validate the saved backup: ```bash sudo caddy validate --config /etc/caddy/Caddyfile.bak ``` Then restore it and reload: ```bash sudo cp /etc/caddy/Caddyfile.bak /etc/caddy/Caddyfile sudo systemctl reload caddy ``` Stop the temporary Python backend with `Ctrl+C` in the terminal where it is running, then remove the demo directory if it is no longer needed: ```bash sudo rm -rf /srv/caddy-proxy-demo ``` Do not remove ports 80/443 from the firewall if another production web service still needs them, and do not delete `/var/lib/caddy` casually because it contains Caddy-managed application state including certificate data. **Verify:** After rollback, `sudo caddy validate --config /etc/caddy/Caddyfile` should pass, Caddy should serve the intended previous configuration, and the temporary port 8080 listener should be gone. ## Troubleshooting ### Caddy returns `502 Bad Gateway` Test the upstream first: ```bash curl -v http://127.0.0.1:8080 sudo ss -lntp | grep ':8080' ``` If the local request fails, fix the application before changing Caddy. If the application works locally, inspect Caddy's journal: ```bash sudo journalctl -u caddy -n 120 --no-pager ``` ### HTTPS certificate issuance fails Check both address families: ```bash dig +short A app.example.com dig +short AAAA app.example.com ``` Then confirm ports 80/443 are reachable and owned by Caddy: ```bash sudo ss -lntp | grep -E ':(80|443)\b' sudo ufw status numbered ``` A stale `AAAA` record, blocked port, another web server, or DNS pointed at the wrong VM can all prevent normal public validation. ### Caddy fails after a configuration edit Validate before doing anything else: ```bash sudo caddy validate --config /etc/caddy/Caddyfile ``` Then inspect: ```bash sudo journalctl -u caddy -n 100 --no-pager ``` Do not repeatedly restart the service while the configuration is invalid. ### The backend sees the wrong client IP First decide whether a CDN/load balancer sits in front of Caddy. If Caddy is the first public proxy, do not add broad trusted-proxy rules. If another proxy is present, configure only its actual CIDRs with Caddy's `trusted_proxies` settings and configure your application framework's proxy trust accordingly. ### WebSockets disconnect when Caddy reloads Caddy supports WebSockets automatically, but current documentation notes that open WebSocket streams are normally closed when a config is unloaded during reload. If this is a problem for your workload, evaluate `stream_close_delay` or `stream_timeout` and test reconnect behavior before changing production settings. ### An HTTPS upstream works only with `tls_insecure_skip_verify` That means certificate trust or server-name verification is not configured correctly. Do not keep the insecure option in production. Install or reference the correct CA through `tls_trust_pool`, use the hostname that matches the backend certificate, or use trusted private HTTP when that is appropriate for the network and threat model. ## Conclusion You now have Caddy running as a reverse proxy on Ubuntu 24.04 with a localhost-only backend, automatic HTTPS, safe firewall handling, validated Caddyfile reloads, default forwarded-header behavior, native WebSocket support, access logging, upstream TLS guidance, end-to-end checks, and rollback instructions. The production baseline is intentionally small: `reverse_proxy 127.0.0.1:PORT` is often all the Caddyfile needs. Add manual headers, transport settings, health checks, or trusted proxies only when your actual topology requires them. Keeping the application off the public interface and validating every configuration before reload removes much of the unnecessary risk found in older reverse-proxy examples. For a static Caddy site instead of a proxy, see [Install Caddy Web Server on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04). For an Nginx-based edge, use [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04) and [Secure Nginx with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). ## Sources - [Caddy — Install](https://caddyserver.com/docs/install) - [Caddy — Reverse proxy quick-start](https://caddyserver.com/docs/quick-starts/reverse-proxy) - [Caddy — reverse_proxy directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) - [Caddy — Automatic HTTPS](https://caddyserver.com/docs/automatic-https) - [Caddy — Keep Caddy Running](https://caddyserver.com/docs/running) - Caddy guidance verified: 2026-09-04 --- ### How to Self-Host Plausible Analytics on Ubuntu 24.04 with Docker URL: https://rafftechnologies.com/learn/tutorials/self-host-plausible-analytics-ubuntu-24-04 Description: Self-host Plausible Analytics CE on Ubuntu 24.04 with Docker Compose, automatic HTTPS, protected secrets, health checks, backups, and safe upgrades. Plausible Community Edition (CE) can be self-hosted on Ubuntu 24.04 with Docker Compose, PostgreSQL, ClickHouse, persistent Docker volumes, and built-in HTTPS. For the current official quickstart, you do **not** need to install Nginx, Caddy, or Certbot just to get a trusted public TLS endpoint: Plausible CE can listen on ports 80 and 443 and manage Let's Encrypt certificates itself. This tutorial follows the current Plausible CE v3.2.1 deployment layout verified on September 4, 2026. It uses the repository's `compose.yml`, stores required settings in `.env`, adds public port mappings through `compose.override.yml`, keeps the upstream Compose file untouched for easier upgrades, and uses the dashboard-generated tracking snippet rather than the older hard-coded `/js/script.js` pattern. Plausible's official quickstart recommends at least 2 GB of RAM and a CPU with SSE 4.2 on x86 or NEON support on ARM because ClickHouse is part of the stack. Raff Technologies is the VM platform used by the original tutorial. The original workflow was tested on Ubuntu 24.04 LTS on a Raff 1 vCPU / 2 GB RAM VM (Tier 2). This revision re-verifies the upstream Plausible CE workflow and documentation; it does not claim a new end-to-end benchmark or capacity test. When you self-host Plausible, you are responsible for upgrades, backups, availability, monitoring, and recovery. Prerequisites: - Ubuntu 24.04 with at least 2 GB RAM recommended by Plausible CE - A CPU with SSE 4.2 support on x86 or NEON support on ARM - Docker Engine with the Docker Compose plugin - SSH access with sudo privileges - A domain such as `analytics.example.com` pointing to the VM - Public TCP ports 80 and 443 available for HTTPS ## Step 1 — Verify Ubuntu, Docker, CPU support, memory, DNS, and web ports Confirm the operating system: ```bash cat /etc/os-release ``` Check Docker and Compose: ```bash docker --version docker compose version ``` If Docker is not installed, use [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) before continuing. Check memory: ```bash free -h ``` Check CPU flags on an x86 VM: ```bash lscpu | grep -i '^Flags' | grep -o 'sse4_2' || true ``` On ARM64 systems, inspect the feature line instead: ```bash lscpu | grep -i '^Flags\|^Features' ``` Plausible's current CE quickstart requires a CPU that supports SSE 4.2 or NEON because ClickHouse depends on those instruction sets. Check DNS in both address families: ```bash dig +short A analytics.example.com dig +short AAAA analytics.example.com ``` Check whether another service already owns ports 80 or 443: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` A stale `AAAA` record can cause confusing HTTPS behavior even when the IPv4 `A` record is correct, so remove or correct IPv6 DNS if this server is not serving the hostname over IPv6. **Verify:** Ubuntu should report 24.04, Docker Compose should work, the VM should meet the Plausible CE memory/CPU requirements, DNS should resolve to this server, and ports 80/443 should be available for the deployment. ## Step 2 — Install the small host utilities used by this tutorial Install Git, OpenSSL, DNS tools, and curl: ```bash sudo apt update sudo apt install -y git openssl dnsutils curl ca-certificates ``` Do not reinstall Docker from a second package source if it is already working. Mixing Ubuntu's Docker packages with Docker's official repository packages can make future upgrades harder to reason about. Confirm Git and OpenSSL are available: ```bash git --version openssl version ``` **Verify:** `git --version` and `openssl version` should both return installed versions without errors. ## Step 3 — Clone a pinned Plausible Community Edition release Create a dedicated installation path owned by your administrative user: ```bash sudo install -d -o "$USER" -g "$USER" /opt/plausible-ce ``` Clone the current CE release used by this revision: ```bash git clone -b v3.2.1 --single-branch \ https://github.com/plausible/community-edition \ /opt/plausible-ce ``` Enter the project: ```bash cd /opt/plausible-ce ``` Inspect the files: ```bash ls -la git describe --tags --exact-match ``` The current repository layout includes `compose.yml`; older tutorials that expect `docker-compose.yml` or `plausible-conf.env` are describing an older CE setup. Pinning an exact release makes upgrades intentional rather than silently changing your application stack whenever a floating image tag moves. **Verify:** `/opt/plausible-ce/compose.yml` should exist and `git describe --tags --exact-match` should report `v3.2.1` for this revision. ## Step 4 — Create a protected Plausible environment file Move into the project directory: ```bash cd /opt/plausible-ce ``` Set a restrictive file-creation mask and generate the secret without printing it to the terminal: ```bash umask 077 SECRET_KEY_BASE="$(openssl rand -base64 48 | tr -d '\n')" ``` Create `.env`: ```bash cat > .env <` of your website. Do not copy the old generic pattern from outdated tutorials: ```text /js/script.js ``` Plausible introduced a newer site-specific tracking script model in October 2025. The current snippet is generated for the site and can reflect enabled tracking options. Using the dashboard-generated snippet avoids hard-coding a path that may not match the current tracker configuration. After adding the snippet, deploy the website change and load the site in a browser. Official current tracking guidance: [Add the Plausible tracking script](https://plausible.io/docs/plausible-script). **Verify:** View the website's rendered HTML or browser developer tools and confirm the exact Plausible snippet from the site's installation screen is present in the page ``. ## Step 10 — Verify analytics end to end from a real browser visit Open the tracked website in a normal browser session and navigate between a few pages. In browser developer tools, open **Network** and filter for your Plausible hostname. Confirm that the tracker script loads and that an analytics event request is sent when a pageview occurs. Then return to the Plausible dashboard and use its installation check or realtime view to confirm the visit is being received. This is a better production verification than posting a fabricated event with a forged `X-Forwarded-For` header or querying an internal ClickHouse table name. Internal schemas and tracker payloads can change between CE releases; the public tracker and dashboard are the interfaces your real site depends on. If the request is blocked, check browser extensions, Content Security Policy, the generated snippet, the site's domain setting, and the Plausible `BASE_URL` before changing database configuration. :::cta Deploy Your Analytics Server Launch a Raff Ubuntu VM and run Plausible Community Edition with Docker Compose and automatic HTTPS. ::: **Verify:** A real browser pageview should produce a request to your Plausible instance and appear in the site's Plausible dashboard or installation check. ## Step 11 — Use an external Caddy reverse proxy only when your topology needs one Starting with Plausible CE 2.1.2, an external reverse proxy is optional because Plausible can manage HTTPS itself. Keep the built-in HTTPS setup from the previous steps unless you already operate Caddy/Nginx as a shared edge or have another architectural reason to proxy Plausible. If you choose Caddy, change `.env` so Plausible listens on its internal HTTP port instead of managing public TLS: ```dotenv BASE_URL=https://analytics.example.com HTTP_PORT=8000 ``` Remove `HTTPS_PORT=443` from `.env`, then replace the direct-public override with a loopback mapping: ```yaml services: plausible: ports: - "127.0.0.1:8000:8000" ``` A minimal Caddy site is: ```caddyfile analytics.example.com { reverse_proxy 127.0.0.1:8000 } ``` Then validate and recreate Plausible before configuring/reloading Caddy: ```bash cd /opt/plausible-ce docker compose config -q docker compose up -d curl -I http://127.0.0.1:8000 ``` For the full Caddy edge workflow, use [How to Set Up a Caddy Reverse Proxy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy). Do not run the direct 80/443 Plausible mode and an external reverse proxy on the same public ports at the same time. **Verify:** Choose exactly one public-edge model: either Plausible owns 80/443 with built-in TLS, or the app listens on `127.0.0.1:8000` and your external proxy owns the public web ports. ## Step 12 — Back up PostgreSQL, ClickHouse, Plausible data, and configuration Self-hosted Plausible stores different classes of state in multiple persistent volumes. PostgreSQL stores account/site configuration, ClickHouse stores analytics data, and the Plausible service has its own persistent application-data volume. A PostgreSQL dump alone is therefore **not** a complete Plausible backup. Create a protected backup directory: ```bash cd /opt/plausible-ce STAMP="$(date +%F-%H%M%S)" BACKUP_DIR="/opt/plausible-ce/backups/$STAMP" mkdir -p "$BACKUP_DIR" chmod 700 /opt/plausible-ce/backups "$BACKUP_DIR" ``` Create a logical PostgreSQL dump while the stack is running: ```bash docker compose exec -T plausible_db \ pg_dump -U postgres plausible_db \ | gzip > "$BACKUP_DIR/plausible-postgres.sql.gz" ``` Capture the exact Docker volume names before stopping the services: ```bash DB_VOL="$(docker inspect "$(docker compose ps -q plausible_db)" --format '{{range .Mounts}}{{if eq .Destination "/var/lib/postgresql/data"}}{{.Name}}{{end}}{{end}}')" EVENT_VOL="$(docker inspect "$(docker compose ps -q plausible_events_db)" --format '{{range .Mounts}}{{if eq .Destination "/var/lib/clickhouse"}}{{.Name}}{{end}}{{end}}')" EVENT_LOG_VOL="$(docker inspect "$(docker compose ps -q plausible_events_db)" --format '{{range .Mounts}}{{if eq .Destination "/var/log/clickhouse-server"}}{{.Name}}{{end}}{{end}}')" APP_VOL="$(docker inspect "$(docker compose ps -q plausible)" --format '{{range .Mounts}}{{if eq .Destination "/var/lib/plausible"}}{{.Name}}{{end}}{{end}}')" ``` Stop the stack for a consistent volume-level archive: ```bash docker compose stop ``` Archive each named volume read-only: ```bash docker run --rm -v "$DB_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/db-data.tar.gz -C /source . docker run --rm -v "$EVENT_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/event-data.tar.gz -C /source . docker run --rm -v "$EVENT_LOG_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/event-logs.tar.gz -C /source . docker run --rm -v "$APP_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/plausible-data.tar.gz -C /source . ``` Back up the deployment configuration and restart: ```bash cp .env compose.override.yml "$BACKUP_DIR/" chmod 600 "$BACKUP_DIR/.env" docker compose start ``` Check the archives: ```bash gzip -t "$BACKUP_DIR/plausible-postgres.sql.gz" ls -lh "$BACKUP_DIR" ``` Keep at least one verified copy away from the VM. Raff [Data Protection](/products/data-protection) can provide an additional infrastructure-level recovery layer, and [Object Storage](/products/object-storage) can be used as an off-server destination for backup archives when your backup workflow supports it. **Verify:** The backup set should contain the PostgreSQL dump, archives for all persistent CE volumes, `.env`, and `compose.override.yml`; the stack should return to its previous running state after `docker compose start`. ## Step 13 — Upgrade Plausible CE with an exact version and a rollback plan Check the installed version first: ```bash cd /opt/plausible-ce git describe --tags --exact-match docker compose images ``` Before upgrading: 1. Create and verify a fresh backup. 2. Read the Plausible CE release notes and version-specific upgrade instructions. 3. Choose an exact target tag rather than following `latest` blindly. Fetch release tags: ```bash git fetch --tags origin ``` When you have deliberately chosen a newer target, replace the placeholder below with that exact release: ```bash TARGET=vX.Y.Z git fetch origin tag "$TARGET" git checkout "$TARGET" docker compose pull docker compose up -d ``` Then verify: ```bash git describe --tags --exact-match docker compose ps docker compose logs --tail=100 plausible curl -I https://analytics.example.com ``` Plausible recommends version pinning, with patch-version pinning providing the most control. Major releases can require additional migration steps, so an old image tag is not automatically a safe rollback after database migrations. Follow the target release notes rather than assuming every upgrade is reversible by changing an image tag. **Verify:** The intended exact release should be checked out, the databases should recover to healthy state, Plausible should run without migration loops, and the public HTTPS dashboard should still respond. ## Step 14 — Run the final checks and clean up safely when needed For the built-in HTTPS topology used by the main tutorial, run: ```bash cd /opt/plausible-ce docker compose config -q git describe --tags --exact-match docker compose ps stat -c '%a %n' .env curl -I http://analytics.example.com curl -I https://analytics.example.com ls -lh backups/ 2>/dev/null || true ``` Also confirm in the browser that: - the dashboard loads over trusted HTTPS; - the administrator can sign in; - the tracked site's current dashboard-generated snippet is installed; - a real page visit appears in Plausible; - no PostgreSQL or ClickHouse port is publicly exposed. To stop Plausible without deleting persistent data: ```bash docker compose down ``` A normal `docker compose down` keeps named volumes. To restart: ```bash docker compose up -d ``` Do **not** use this destructive command unless you intentionally want to remove the databases and analytics history and have already verified your backups: ```bash docker compose down -v ``` Remove `/opt/plausible-ce` only after you have decided that its configuration and local backup copies are no longer needed. **Verify:** After a normal `down`, the Plausible named volumes should remain. After restarting, the existing account, site configuration, and analytics history should still be present. ## Troubleshooting ### Automatic HTTPS does not obtain a certificate Check both DNS families and port ownership: ```bash dig +short A analytics.example.com dig +short AAAA analytics.example.com sudo ss -lntp | grep -E ':(80|443)\b' || true cd /opt/plausible-ce docker compose logs --tail=150 plausible ``` The hostname must resolve to the server and ports 80/443 must reach the Plausible container. Remove stale IPv6 DNS if the server is not actually reachable over that IPv6 address. ### Plausible or a database repeatedly restarts Check the full state and service-specific logs: ```bash cd /opt/plausible-ce docker compose ps docker compose logs --tail=150 plausible docker compose logs --tail=150 plausible_db docker compose logs --tail=150 plausible_events_db ``` Also confirm the VM has at least the 2 GB RAM recommended by the current CE quickstart: ```bash free -h docker stats --no-stream ``` Treat resource output as a measurement of your instance, not as a universal pageview-capacity estimate. ### The dashboard loads but tracking data does not arrive Use the current snippet copied from the site's installation settings. Then check the website's browser Network panel for the tracker script and event request. Common causes include: - an old or manually edited tracking snippet; - a restrictive Content Security Policy; - browser privacy/ad-blocking extensions; - the wrong site domain in Plausible; - a wrong `BASE_URL` after moving the analytics instance. Do not start by editing ClickHouse tables or fabricating events against an assumed internal schema. ### The external reverse proxy returns 502 If you intentionally selected the optional proxy topology, verify the loopback upstream first: ```bash curl -I http://127.0.0.1:8000 sudo ss -lntp | grep ':8000' ``` The override should map `127.0.0.1:8000:8000`, and `.env` should contain `HTTP_PORT=8000` without the direct `HTTPS_PORT=443` setup. ### WebSocket features fail behind Nginx Plausible's current community Nginx example includes an explicit `/live/websocket` WebSocket location with HTTP/1.1 upgrade headers. Do not describe the live connection as ordinary buffered HTTP or assume a generic proxy block handles every Nginx WebSocket case. Caddy's `reverse_proxy` handles WebSocket upgrades automatically. ### An upgrade fails after migrations start Stop making repeated image/tag changes. Read the release-specific upgrade notes, preserve the failing state and logs, and restore from your pre-upgrade backup when the documented recovery path requires it. Database migrations can make a simple image downgrade unsafe. ## Conclusion You now have Plausible Community Edition running on Ubuntu 24.04 with its current Docker Compose layout, a pinned CE release, protected secrets, built-in automatic HTTPS, current site-specific tracking, persistent PostgreSQL and ClickHouse data, a complete backup plan, and a controlled upgrade path. Plausible is designed for privacy-focused, cookieless aggregate web analytics, but your site's legal obligations depend on your jurisdiction, configuration, and any other trackers or personal-data processing you use. Self-hosting also moves the operational responsibility to you: keep CE updated, monitor storage and memory, protect the server, and test restores rather than assuming a VM snapshot or PostgreSQL dump alone covers the entire analytics stack. For adjacent workflows, use [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Caddy Reverse Proxy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy), and Raff [Data Protection](/products/data-protection). ## Sources - [Plausible Community Edition — v3.2.1 Quick Start](https://github.com/plausible/community-edition/tree/v3.2.1) - [Plausible CE — Configuration](https://github.com/plausible/community-edition/wiki/Configuration) - [Plausible CE — Reverse Proxy](https://github.com/plausible/community-edition/wiki/reverse-proxy) - [Plausible CE — Upgrade](https://github.com/plausible/community-edition/wiki/upgrade) - [Plausible Docs — Add the tracking script](https://plausible.io/docs/plausible-script) - [Plausible Docs — Update your tracking script](https://plausible.io/docs/script-update-guide) - Plausible CE guidance re-verified: 2026-09-04 --- ### How to Install Open WebUI with Ollama on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-open-webui-ollama-ubuntu-24-04 Description: Install Open WebUI with Ollama on Ubuntu 24.04 using private Docker Compose networking, Caddy HTTPS, pinned versions, backups, and safe updates. Open WebUI with Ollama can run safely on one Ubuntu 24.04 server without exposing the Ollama API to the internet. The cleaner production pattern is to run **Open WebUI and Ollama as separate Docker Compose services on the same private Docker network**, publish only Open WebUI to `127.0.0.1:3000`, and let Caddy provide the public HTTPS endpoint. In this design, Open WebUI reaches Ollama at `http://ollama:11434` inside Docker; host port `11434` is never published. This tutorial uses Open WebUI **v0.11.1** and Ollama **0.33.3**, the current stable releases verified on September 4, 2026. Open WebUI's own production guidance recommends pinning a specific release instead of using the rolling `:main` or `:latest` image. A persistent `WEBUI_SECRET_KEY` is also set so container recreation does not invalidate sessions or encrypted integration data. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment is Ubuntu 24.04.4 LTS on a Raff 8 vCPU / 16 GB RAM / 320 GB NVMe VM running CPU-only inference with `llama3.2:3b`. This revision updates the deployment architecture against current upstream documentation; it does not claim a new benchmark or a fresh end-to-end hardware test. Prerequisites: - An Ubuntu 24.04 VM with SSH and sudo access - Docker Engine with Docker Compose v2 - A domain such as `ai.example.com` pointed to the VM - Ports 80 and 443 available for Caddy - Enough RAM and storage for the Ollama model you choose ## Step 1 — Verify Ubuntu, Docker, DNS, memory, and free disk space Check the operating system: ```bash cat /etc/os-release ``` Verify Docker and Compose: ```bash docker --version docker compose version ``` If Docker is not installed, use [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) before continuing. Check memory and storage: ```bash free -h df -h / ``` Check DNS in both address families: ```bash dig +short A ai.example.com dig +short AAAA ai.example.com ``` Check whether an existing service already owns the public web ports: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` Model files can consume multiple gigabytes, and memory requirements vary substantially by model size, quantization, context length, concurrency, and whether inference runs on CPU or GPU. Do not size the VM from a universal "requests per second" or model-count claim. **Verify:** Ubuntu should report 24.04, Docker Compose should run, the domain should resolve to this VM, and you should have enough RAM/disk for the model you intend to pull. ## Step 2 — Create the Open WebUI and Ollama project directory Create a dedicated deployment directory: ```bash sudo install -d -o "$USER" -g "$USER" /opt/open-webui cd /opt/open-webui ``` Create a backup directory now so the path exists before the application contains important data: ```bash mkdir -p backups chmod 700 backups ``` Confirm ownership: ```bash ls -ld /opt/open-webui /opt/open-webui/backups ``` **Verify:** `/opt/open-webui` and `/opt/open-webui/backups` should exist and be writable by your administrative user. ## Step 3 — Create pinned version and secret settings Open WebUI's current production guidance recommends versioned image tags rather than rolling `:main`/`:latest` tags. Ollama also publishes versioned Docker images. Generate a persistent Open WebUI secret without printing it to the terminal: ```bash cd /opt/open-webui umask 077 WEBUI_SECRET_KEY="$(openssl rand -hex 32)" ``` Create `.env`: ```bash cat > .env < /dev/null <<'EOF' ai.example.com { reverse_proxy 127.0.0.1:3000 } EOF ``` Replace `ai.example.com` with the domain stored in `/opt/open-webui/.env`. Caddy's `reverse_proxy` supports WebSocket upgrades automatically, so you do not need to copy Nginx-style manual `Upgrade` and `Connection` header boilerplate. Format and validate the Caddyfile: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo caddy validate --config /etc/caddy/Caddyfile ``` Reload Caddy: ```bash sudo systemctl reload caddy ``` Test both schemes: ```bash curl -I http://ai.example.com curl -I https://ai.example.com ``` **Verify:** HTTP should redirect to HTTPS, the HTTPS request should reach Open WebUI with a trusted certificate, and `127.0.0.1:3000` should remain the only host-side Open WebUI backend listener. ## Step 11 — Create the first Open WebUI administrator account Open: ```text https://ai.example.com ``` Create the first account. Current Open WebUI hardening guidance states that signup is open only until the first account is registered; that first user becomes the administrator and signup is then automatically disabled by default. Use a unique administrator password and avoid sharing the administrator account for normal multi-user access. ![Open WebUI dashboard after first login on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/open_webui_ollama_ubuntu_24_04_02_admin_dashboard_webp_8a5ddbf49c.png) The interface has changed across Open WebUI releases, so labels in an older screenshot may differ slightly from v0.11.1 even though the account workflow remains the same. **Verify:** You should be able to sign in over HTTPS, open the Admin area, and confirm the first account has administrator privileges. ## Step 12 — Verify the Ollama connection and chat with the model Open the Open WebUI administrator connection settings. In current releases, Ollama connections are managed under the administrator settings area. The backend connection for this Compose deployment is: ```text http://ollama:11434 ``` Open WebUI's current Docker guidance uses internal URLs that the backend container can actually reach; when two services share a Compose network, the service name is preferable to exposing Ollama on the host. ![Open WebUI Ollama connection settings showing a working local endpoint](https://raff-images.s3.raffusercloud.com/open_webui_ollama_ubuntu_24_04_03_ollama_connection_webp_04f2cd42bd.png) Return to chat and select: ```text llama3.2:3b ``` ![Open WebUI model selector with llama3.2 selected](https://raff-images.s3.raffusercloud.com/open_webui_ollama_ubuntu_24_04_04_model_selected_webp_5fd206c8be.png) Send a simple test prompt: ```text Reply with exactly: Open WebUI and Ollama are connected. ``` ![Open WebUI response from an Ollama model on a Raff Ubuntu 24.04 VM](https://raff-images.s3.raffusercloud.com/open_webui_ollama_ubuntu_24_04_05_successful_response_webp_01a3613167.png) :::cta Deploy Your AI Server Launch a Raff Ubuntu VM and use this private Docker Compose pattern for Open WebUI and Ollama. ::: **Verify:** The model should appear in the selector, the prompt should produce a response, and the browser should remain on the HTTPS Open WebUI domain throughout the request. ## Step 13 — Back up Open WebUI data, Ollama models, secrets, and proxy configuration Open WebUI stores users, chats, settings, uploads, and its local database under `/app/backend/data`. Ollama stores downloaded models under `/root/.ollama`. Both locations are persistent named volumes in this deployment. Create a timestamped backup directory: ```bash cd /opt/open-webui STAMP="$(date +%F-%H%M%S)" BACKUP_DIR="/opt/open-webui/backups/$STAMP" mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" ``` Capture the exact volume names while the containers are running: ```bash WEBUI_VOL="$(docker inspect open-webui --format '{{range .Mounts}}{{if eq .Destination "/app/backend/data"}}{{.Name}}{{end}}{{end}}')" OLLAMA_VOL="$(docker inspect ollama --format '{{range .Mounts}}{{if eq .Destination "/root/.ollama"}}{{.Name}}{{end}}{{end}}')" ``` Stop the application stack for a consistent local-volume archive: ```bash docker compose stop ``` Archive both volumes: ```bash docker run --rm -v "$WEBUI_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/open-webui-data.tar.gz -C /source . docker run --rm -v "$OLLAMA_VOL:/source:ro" -v "$BACKUP_DIR:/backup" \ alpine:3 tar -czf /backup/ollama-models.tar.gz -C /source . ``` Back up configuration and restart: ```bash cp .env compose.yaml "$BACKUP_DIR/" sudo cp /etc/caddy/Caddyfile "$BACKUP_DIR/Caddyfile" chmod 600 "$BACKUP_DIR/.env" docker compose start ``` Verify the archives: ```bash ls -lh "$BACKUP_DIR" tar -tzf "$BACKUP_DIR/open-webui-data.tar.gz" | head tar -tzf "$BACKUP_DIR/ollama-models.tar.gz" | head ``` Keep a protected copy away from the VM. Raff [Data Protection](/products/data-protection) can protect the infrastructure layer; application-aware backups are still valuable before upgrades and migrations. **Verify:** The backup set should contain both volume archives, `.env`, `compose.yaml`, and the Caddyfile, and the two containers should return to a running state after `docker compose start`. ## Step 14 — Update, troubleshoot, verify end to end, and clean up safely Before an update, create a fresh backup and review the release notes for both Open WebUI and Ollama. Open WebUI explicitly recommends pinned release tags for shared/production deployments. To upgrade, edit only the version values in `.env` after selecting exact target releases: ```bash cd /opt/open-webui nano .env ``` Then pull and recreate: ```bash docker compose pull docker compose up -d ``` Check versions and health: ```bash docker compose ps docker compose exec ollama ollama --version docker logs open-webui 2>&1 | head -n 30 curl -I https://ai.example.com ``` If Open WebUI cannot see Ollama, test Docker DNS and the API from the Open WebUI container: ```bash docker compose exec open-webui python3 -c \ "import urllib.request; print(urllib.request.urlopen('http://ollama:11434/api/tags', timeout=10).status)" ``` If Caddy returns 502, test the local Open WebUI backend: ```bash curl -I http://127.0.0.1:3000 docker compose logs --tail=120 open-webui sudo journalctl -u caddy -n 100 --no-pager ``` If the model does not appear: ```bash docker compose exec ollama ollama list docker compose logs --tail=120 ollama ``` If model responses are slow, inspect actual resource use instead of assuming a network problem: ```bash docker stats --no-stream free -h ``` For the final end-to-end check: ```bash cd /opt/open-webui docker compose config -q docker compose ps sudo ss -lntp | grep -E ':(80|443|3000|11434)\b' || true curl -I https://ai.example.com docker compose exec ollama ollama list ``` Expected architecture: ```text Internet | | HTTPS 443 v Caddy | | 127.0.0.1:3000 v Open WebUI container | | private Docker network: ollama:11434 v Ollama container ``` To stop the stack without deleting chats or models: ```bash docker compose down ``` Named volumes remain after a normal `down`. To restart: ```bash docker compose up -d ``` Do **not** run the following unless you intentionally want to delete Open WebUI data and downloaded Ollama models after verifying backups: ```bash docker compose down -v ``` **Verify:** Open WebUI should load over HTTPS, `llama3.2:3b` should answer a chat prompt, port 3000 should remain loopback-only, port 11434 should not be published on the host, and normal container recreation should preserve users, chats, and models. ## Conclusion You now have Open WebUI and Ollama on Ubuntu 24.04 using a private two-container Docker Compose architecture. Caddy handles public HTTPS, Open WebUI is reachable only through a loopback backend port, and Ollama is reachable only inside the Docker network. This avoids exposing the unauthenticated Ollama API merely to let a Dockerized UI reach it. The deployment also pins stable versions, keeps a persistent `WEBUI_SECRET_KEY`, preserves Open WebUI and Ollama data in named volumes, includes a complete backup set, and gives you a controlled upgrade path. The saved Raff test environment remains the original CPU-only 8 vCPU / 16 GB setup with `llama3.2:3b`; measure your own CPU, RAM, GPU, model size, context, and concurrency before choosing production capacity. For adjacent workflows, continue with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Caddy Reverse Proxy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy), or [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Open WebUI — Quick Start](https://docs.openwebui.com/getting-started/quick-start/) - [Open WebUI — Environment Variable Configuration](https://docs.openwebui.com/reference/env-configuration/) - [Open WebUI — Hardening](https://docs.openwebui.com/getting-started/advanced-topics/hardening/) - [Open WebUI — Updating](https://docs.openwebui.com/getting-started/updating/) - [Open WebUI — Ollama connection](https://docs.openwebui.com/getting-started/quick-start/connect-a-provider/starting-with-ollama/) - [Ollama — Docker image](https://hub.docker.com/r/ollama/ollama) - [Ollama — FAQ](https://docs.ollama.com/faq) - [Ollama — llama3.2:3b](https://ollama.com/library/llama3.2:3b) - Open WebUI/Ollama guidance re-verified: 2026-09-04 --- ### How to Build a Remote Development VM with code-server and Tailscale URL: https://rafftechnologies.com/learn/tutorials/build-remote-development-vm-code-server-tailscale Description: Build a private remote development VM on Ubuntu 24.04 with code-server and Tailscale Serve, HTTPS, localhost binding, backups, and safe updates. A remote development VM can give you a persistent Linux workspace that you access from a browser without publishing your editor to the public internet. In this setup, **code-server stays bound to `127.0.0.1:8080`**, Tailscale connects the VM to your private tailnet, and **Tailscale Serve** terminates HTTPS and forwards only tailnet-authorized traffic to the local code-server process. Raff Technologies is the VM platform used by the original tutorial. The saved test environment is Ubuntu 24.04 LTS on a Raff 2 vCPU / 4 GB RAM VM. This revision keeps that tested-on record but updates the workflow against current upstream guidance on September 4, 2026. It pins code-server **4.133.0**, keeps code-server's own password authentication as a second layer behind Tailscale, uses the current `tailscale serve --bg` syntax, and avoids stale claims about hourly billing, unlimited bandwidth, or fixed VM sizing. This architecture is intentionally private. You do not need a public domain, Let's Encrypt, Nginx, Caddy, or an inbound firewall rule for port 8080. Your browser connects to the VM's private `*.ts.net` HTTPS URL through Tailscale, while code-server remains a loopback-only service. Tailscale access controls still apply to Serve, so a team can further restrict which tailnet users or devices may reach the development VM. Prerequisites: - An Ubuntu 24.04 VM with SSH and sudo access - A non-root Linux user for daily development - A Tailscale account/tailnet and a second device that can join it - Enough CPU, RAM, and disk for your actual development workload ## Step 1 — Verify Ubuntu, SSH access, resources, and existing listeners Confirm the operating system: ```bash cat /etc/os-release ``` Check memory and disk space: ```bash free -h df -h / ``` Check whether anything is already listening on code-server's default port: ```bash sudo ss -ltnp | grep ':8080' || true ``` Keep your current SSH session open while you configure Tailscale and code-server. If you later change firewall or SSH policy, a working fallback session reduces lockout risk. Do not treat the original 2 vCPU / 4 GB test VM as a universal sizing rule. A Node.js project, a large monorepo, local containers, compilers, language servers, and browser tabs can have very different resource requirements. **Verify:** Ubuntu should report 24.04, the VM should have enough free resources for your workload, and you should know whether port 8080 is already occupied before continuing. ## Step 2 — Install the baseline development utilities Update package metadata and install the tools used by this tutorial: ```bash sudo apt update sudo apt install -y \ git curl ca-certificates openssl build-essential unzip ``` Check the tools: ```bash git --version curl --version | head -1 openssl version ``` A full unattended `apt upgrade -y` is not required just to install code-server. Apply normal OS security updates according to your server maintenance policy, especially if the VM already runs other workloads. For a fresh server, complete your normal SSH and host-hardening baseline before making it a daily development machine. See [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). **Verify:** Git, curl, and OpenSSL should return installed versions without errors. ## Step 3 — Install a pinned code-server release The code-server project documents its official `install.sh` as the easiest Linux installation method and supports an exact `--version` argument. The current stable release verified for this revision is **4.133.0**. Preview what the installer will do: ```bash curl -fsSL https://code-server.dev/install.sh | \ sh -s -- --dry-run --version=4.133.0 ``` Then install the pinned release: ```bash curl -fsSL https://code-server.dev/install.sh | \ sh -s -- --version=4.133.0 ``` Enable and start the packaged systemd service for your current user: ```bash sudo systemctl enable --now code-server@$USER ``` Check the installed version and service: ```bash code-server --version sudo systemctl is-active code-server@$USER ``` The official Debian/Ubuntu installation flow runs code-server through the `code-server@.service` template. Do not confuse that with a separate `systemctl --user` unit unless you deliberately created one yourself. **Verify:** `code-server --version` should report `4.133.0` for this revision and `code-server@$USER` should be active. ## Step 4 — Keep code-server on localhost with its own password authentication code-server's default configuration lives at: ```text ~/.config/code-server/config.yaml ``` Its secure default pattern is loopback binding plus password authentication. This tutorial keeps both instead of using Tailscale as the only authentication layer. Generate a new random password and write a restrictive config: ```bash umask 077 CODE_SERVER_PASSWORD="$(openssl rand -base64 24 | tr -d '\n')" mkdir -p ~/.config/code-server cat > ~/.config/code-server/config.yaml < ``` Tailscale may route a connection directly peer-to-peer or through a relay depending on NAT/firewall conditions. Either path can be valid; do not use the transport path alone as a health verdict. If your tailnet uses custom access controls, make sure your intended user/device is allowed to reach the VM. Tailscale Serve inherits the tailnet's access-control policy. **Verify:** The client should see the VM as an authorized tailnet device and should be able to reach it according to your tailnet policy. ## Step 8 — Publish localhost:8080 privately with Tailscale Serve Create a persistent private HTTPS reverse proxy: ```bash sudo tailscale serve --bg localhost:8080 ``` Check the active Serve configuration: ```bash sudo tailscale serve status ``` Current Tailscale documentation states that `--bg` keeps the Serve configuration active across device reboots and Tailscale restarts. The HTTPS endpoint is restricted to your tailnet; **Tailscale Serve is not Tailscale Funnel**. If HTTPS certificates are not yet enabled for your tailnet, the CLI may give you a consent/setup URL. Complete that one-time tailnet configuration and rerun the command if necessary. Tailscale Serve terminates HTTPS and proxies to the local HTTP backend. code-server itself can therefore keep `cert: false` on loopback. Do not run `tailscale funnel` for this tutorial. Funnel is intended for public internet exposure, which would change the security model. **Verify:** `sudo tailscale serve status` should show an HTTPS `*.ts.net` URL forwarding to `http://localhost:8080`. ## Step 9 — Sign in through the private HTTPS URL and verify browser features From a device that is signed into the authorized tailnet, open the HTTPS URL shown by: ```bash sudo tailscale serve status ``` Retrieve the code-server password on the VM when needed: ```bash awk -F': ' '/^password:/ {print $2}' ~/.config/code-server/config.yaml ``` Use that password to sign in. After login, verify more than the landing page: - open the Explorer panel; - open an integrated terminal; - create and save a test file; - reconnect after refreshing the page; - open a second tab and confirm the editor remains responsive. code-server depends on WebSockets for normal browser/editor communication. Tailscale Serve's HTTP reverse proxy handles the HTTPS frontend while forwarding to the local service, so you do not need an Nginx-style WebSocket header block here. :::cta Deploy Your Remote Development VM Launch a Raff Ubuntu VM and keep your browser IDE private with code-server and Tailscale. ::: **Verify:** The `*.ts.net` HTTPS URL should load only from an authorized tailnet device, code-server should request its password, and the integrated terminal/file editor should work after login. ## Step 10 — Create a clean workspace and understand code-server extensions Create a projects directory: ```bash mkdir -p ~/projects cd ~/projects ``` Clone a repository you are authorized to access. For a harmless public test: ```bash git clone https://github.com/octocat/Hello-World.git cd Hello-World git status ``` Open `~/projects/Hello-World` in code-server. You can install extensions from the Extensions view or CLI: ```bash code-server --install-extension ``` One important difference from Microsoft's desktop VS Code is the marketplace. Current code-server documentation states that it cannot use Microsoft's extension marketplace under Microsoft's marketplace terms; code-server uses Open VSX / compatible galleries instead. Some Microsoft-only or closed-source extensions may therefore be unavailable or behave differently. Extensions are stored under: ```text ~/.local/share/code-server/extensions ``` Editor settings and related state are also stored under `~/.local/share/code-server` by default. **Verify:** You should be able to open the cloned workspace, run `git status` from the integrated terminal, save a file, and install at least one extension that is available through code-server's supported extension gallery. ## Step 11 — Protect source code, Git credentials, and unpushed work A remote development VM often contains more sensitive material than a generic test server: source repositories, `.env` files, package-registry tokens, SSH agent access, Git credentials, and unpushed commits. Prefer short-lived or scoped credentials where your Git/package provider supports them. Avoid casually copying your laptop's long-lived private SSH key into the VM. If you use SSH-agent or GPG-agent forwarding, understand that a compromised remote account may be able to use the forwarded agent while the session exists. Keep project secrets out of Git: ```bash cd ~/projects/Hello-World git status --ignored ``` Review permissions on SSH/config directories if you use them: ```bash ls -ld ~/.ssh ~/.config/code-server 2>/dev/null || true ``` For team access, use separate Linux/tailnet identities rather than sharing one code-server password broadly. code-server itself is primarily a single-user tool; the Coder project recommends VM/workspace isolation when multiple users need independent environments. **Verify:** Sensitive `.env`/key material should not be tracked unintentionally, and the development VM should use credentials appropriate for a remote machine rather than a copy of every local secret. ## Step 12 — Back up code-server state and preserve source repositories correctly Treat Git remotes as the primary source backup for repositories: push commits you cannot afford to lose. Then protect the editor state and any non-Git workspace files separately. Create a protected backup directory: ```bash mkdir -p ~/backups chmod 700 ~/backups STAMP="$(date +%F-%H%M%S)" ``` Archive code-server configuration and editor state: ```bash tar -czf "$HOME/backups/code-server-state-$STAMP.tar.gz" \ -C "$HOME" \ .config/code-server \ .local/share/code-server ``` List the archive: ```bash tar -tzf "$HOME/backups/code-server-state-$STAMP.tar.gz" | head ``` Do not blindly archive entire development trees full of `node_modules`, build artifacts, caches, databases, or secrets. Back up non-Git project data intentionally according to what the project actually contains. Keep at least one recovery copy away from the VM. Raff [Data Protection](/products/data-protection) can provide an additional infrastructure-level recovery layer, but repository pushes and application-aware backups are still important for active development work. **Verify:** Important repositories should have their needed commits on a remote Git service, and the code-server state archive should be readable without errors. ## Step 13 — Update code-server and Tailscale without losing the private-access model Before upgrading, check the current versions: ```bash code-server --version tailscale version ``` For code-server, review the project's release notes and install the exact target version you chose. For example, this revision's pinned version can be reinstalled with: ```bash curl -fsSL https://code-server.dev/install.sh | \ sh -s -- --version=4.133.0 ``` After a future upgrade, restart and verify: ```bash sudo systemctl restart code-server@$USER sudo systemctl is-active code-server@$USER sudo ss -ltnp | grep ':8080' ``` For Tailscale installed from its official package source, use your normal APT update workflow: ```bash sudo apt update apt list --upgradable 2>/dev/null | grep -i tailscale || true ``` After upgrading Tailscale, confirm that Serve resumed: ```bash tailscale status sudo tailscale serve status ``` The security invariants should survive every update: code-server remains on `127.0.0.1:8080`, Serve remains private to the tailnet, and Funnel remains unused. **Verify:** After updates/restarts, the browser should still use the private HTTPS Serve URL and `ss` should still show code-server bound only to loopback. ## Step 14 — Run the final security check and roll back safely Run the final server-side checks: ```bash sudo systemctl is-active code-server@$USER tailscale status tailscale ip -4 sudo tailscale serve status sudo ss -ltnp | grep ':8080' stat -c '%a %n' ~/.config/code-server/config.yaml ``` From the client, confirm: 1. the `*.ts.net` HTTPS URL opens while Tailscale is connected; 2. code-server still requires its password; 3. a workspace and terminal work normally; 4. disconnecting the client from Tailscale makes the private Serve URL unreachable; 5. the VM's public IP on port 8080 does not expose code-server. To disable only the private Serve endpoint: ```bash sudo tailscale serve reset ``` To stop code-server: ```bash sudo systemctl disable --now code-server@$USER ``` To leave the tailnet when this VM no longer needs Tailscale: ```bash sudo tailscale down ``` Do not remove project files, editor state, Git credentials, or backups until you have verified what needs to be retained. If you later uninstall code-server, follow the uninstall path matching the installation method reported by the official installer. **Verify:** After Serve reset, the private HTTPS URL should stop serving code-server while SSH/admin access remains intact. If you re-enable the services, the original private architecture should return without opening public port 8080. ## Troubleshooting ### `code-server@$USER` is inactive Inspect the service log: ```bash sudo journalctl -u code-server@$USER -n 120 --no-pager ``` Then verify the YAML and port: ```bash cat ~/.config/code-server/config.yaml sudo ss -ltnp | grep ':8080' || true ``` A malformed config or another process already using port 8080 will prevent a normal start. ### Tailscale Serve shows a URL but the browser cannot connect Check the VM: ```bash tailscale status sudo tailscale serve status curl -I http://127.0.0.1:8080 ``` Then confirm the client device is logged into the same tailnet and permitted by your tailnet access controls. Serve does not make the service public. ### Tailscale asks you to enable HTTPS certificates Follow the consent/setup URL provided by the CLI. Serve HTTPS requires certificate support for the tailnet's `*.ts.net` names. After enabling it, rerun: ```bash sudo tailscale serve --bg localhost:8080 ``` ### The browser works but some editor actions disconnect Confirm the client is not aggressively blocking WebSockets and that you are using the Serve HTTPS URL rather than manually proxying code-server through another web server. Inspect code-server logs while reproducing the problem: ```bash sudo journalctl -fu code-server@$USER ``` ### An extension is missing from the marketplace code-server does not use Microsoft's official VS Code marketplace by default/under Microsoft's marketplace terms. Search Open VSX or the supported gallery, or install a trusted `.vsix` obtained from the extension project's official release channel when licensing and compatibility allow it. ### The VM works through Tailscale but public SSH is still open That is not automatically a code-server problem. Decide your SSH exposure separately. If you later move SSH to Tailscale-only access, test Tailscale SSH or normal SSH over the tailnet first and keep a provider console/recovery path before removing the existing public SSH rule. ## Conclusion You now have a remote development VM on Ubuntu 24.04 with code-server kept on `127.0.0.1:8080` and a private Tailscale Serve HTTPS endpoint for browser access. The setup keeps code-server password authentication enabled, respects tailnet access controls, avoids Tailscale Funnel, and does not require public port 8080, a public domain, or a separate reverse proxy. The workflow also accounts for code-server's supported extension marketplace, persistent editor state, Git/secrets hygiene, upgrades, backups, and rollback. The original Raff 2 vCPU / 4 GB test environment is preserved as historical test metadata; choose production resources from the actual languages, repositories, containers, compilers, and concurrency your development workflow uses. For adjacent hardening, continue with [Configure SSH Keys on Ubuntu](/learn/tutorials/configure-ssh-keys-ubuntu), [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [code-server — Install](https://coder.com/docs/code-server/install) - [code-server — FAQ and configuration](https://coder.com/docs/code-server/FAQ) - [code-server — Secure exposure guide](https://coder.com/docs/code-server/guide) - [code-server — Releases](https://github.com/coder/code-server/releases) - [Tailscale — Install on Linux](https://tailscale.com/docs/install/linux) - [Tailscale — Serve](https://tailscale.com/docs/features/tailscale-serve) - [Tailscale — Serve CLI reference](https://tailscale.com/docs/reference/tailscale-cli/serve) - [Tailscale — code-server integration](https://tailscale.com/docs/integrations/codeserver) - Upstream guidance re-verified: 2026-09-04 --- ### How to Set Up UFW Firewall on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04 Description: Set up UFW on Ubuntu 24.04 without losing SSH access. Configure IPv4/IPv6 rules, ports, source restrictions, logging, rule order, and Docker caveats. UFW, short for Uncomplicated Firewall, is Ubuntu's standard command-line frontend for building a host-based firewall. A safe Ubuntu 24.04 baseline is straightforward: identify the SSH port you are actually using, allow that path **before** enabling UFW, keep the default inbound policy restrictive, open only the services the server needs, and verify the result from a second connection before closing your original SSH session. Raff Technologies is the VM platform used by the original tutorial. The saved tested-on record remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 2 GB RAM Linux VM; UFW, OpenSSH, IPv6, logging, and Docker guidance reviewed in July 2026`. This revision re-verifies the firewall workflow against current Ubuntu, UFW, and Docker documentation on September 4, 2026 without claiming a new server-side test. The most important caveat is Docker: a normal UFW policy does **not reliably protect Docker-published container ports** because Docker creates its own NAT/firewall rules and can divert that traffic before UFW's normal host `INPUT` rules. For private container services, bind published ports to loopback or use Docker-aware/upstream filtering instead of assuming UFW will block them. Prerequisites: - An Ubuntu 24.04 VM with SSH access - A non-root user with sudo privileges - Knowledge of every service that must remain reachable - A second terminal or recovery path for SSH verification ## Step 1 — Inspect the current SSH, network, and firewall state Do not enable a firewall before you understand how you are currently connected. Check Ubuntu: ```bash cat /etc/os-release ``` Check UFW state: ```bash sudo ufw status verbose ``` List listening TCP and UDP sockets: ```bash sudo ss -tulpn ``` Ask OpenSSH for its effective configured port or ports: ```bash sudo sshd -T | awk '$1 == "port" {print $2}' ``` If you use a provider-side firewall, security group, VPN, Tailscale, or a nonstandard SSH port, document that path before changing UFW. Keep the current SSH session open throughout the initial enablement. A second connection will be your proof that the firewall did not lock you out. **Verify:** You should know the active SSH port, which applications are listening, whether UFW is already active, and which services must remain reachable. ## Step 2 — Install UFW and understand its installation defaults Install UFW if it is not already present: ```bash sudo apt update sudo apt install -y ufw ``` Check its version: ```bash ufw --version ``` Ubuntu's current UFW documentation states that UFW is initially disabled. Its installation defaults are already designed around a common server baseline: deny incoming traffic, deny forwarded/routed traffic, and allow outgoing traffic. This tutorial still sets the intended host defaults explicitly later so the final policy is easy to audit. UFW is a frontend for Linux netfilter. It is useful for host firewall rules, but it is not intended to replace every advanced packet-filtering or routing feature. **Verify:** `ufw --version` should return an installed version and `sudo ufw status` should return a valid status rather than `command not found`. ## Step 3 — Keep IPv6 firewalling aligned with the server's network configuration Check UFW's IPv6 setting: ```bash grep '^IPV6=' /etc/default/ufw ``` Ubuntu 24.04's UFW framework enables IPv6 support by default. A typical result is: ```text IPV6=yes ``` When IPv6 support is enabled, generic rules such as: ```bash sudo ufw allow 22/tcp ``` can create rules that apply to both IPv4 and IPv6. If your server has working IPv6 or an `AAAA` DNS record, keep IPv6 firewalling enabled and test both address families. Do not treat `IPV6=no` as a harmless way to ignore IPv6: current UFW framework documentation states that disabling IPv6 support changes how non-loopback IPv6 traffic is handled. Inspect the host addresses: ```bash ip -brief address ``` If the VM intentionally has no IPv6 service, document that choice at both the host and upstream network layers instead of leaving stale public IPv6 DNS/routes. **Verify:** You should know whether the VM is single-stack or dual-stack, and `/etc/default/ufw` should match that intended design. ## Step 4 — Allow the active SSH path before enabling UFW If SSH uses the normal OpenSSH profile on TCP 22, inspect the profile first: ```bash sudo ufw app info OpenSSH ``` Then add the rule: ```bash sudo ufw allow OpenSSH comment 'SSH administration' ``` If SSH uses a custom port, allow that exact port instead. Example: ```bash sudo ufw allow 2222/tcp comment 'SSH administration' ``` Do **not** add both rules unless sshd intentionally listens on both ports. You can preview the effect of a rule without applying it by using UFW's `--dry-run` option. For example: ```bash sudo ufw --dry-run allow 2222/tcp ``` Review rules that have been added from the command line: ```bash sudo ufw show added ``` This step is the critical lockout safeguard. UFW's own remote-management documentation recommends allowing the SSH port before `ufw enable` because enabling UFW rebuilds its chains and can interrupt existing remote connections. **Verify:** `sudo ufw show added` should contain an allow rule for the exact SSH path you are using before you enable the firewall. ## Step 5 — Set and review the default policies Apply a common application-server baseline: ```bash sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw default deny routed ``` The routed policy matters when the host forwards traffic between interfaces or networks. A normal standalone application VM generally does not need to be an IP router. Review the pending rules again: ```bash sudo ufw show added ``` Preview enablement without changing the live firewall: ```bash sudo ufw --dry-run enable ``` Default policy changes can affect existing rules, so make them deliberately rather than toggling defaults repeatedly on a production server. **Verify:** Your intended defaults should be deny incoming, allow outgoing, deny routed, and the SSH allow rule must still be present. ## Step 6 — Enable UFW and test a second SSH connection Enable the firewall: ```bash sudo ufw enable ``` UFW may warn that enabling it can disrupt existing SSH connections. Continue only because the correct SSH rule was added first. Check the live policy: ```bash sudo ufw status verbose ``` Then, **without closing the original session**, open a second terminal from your workstation and connect again: ```bash ssh your_user@your_server_ip ``` If SSH uses a custom port: ```bash ssh -p 2222 your_user@your_server_ip ``` Do not consider the firewall rollout successful until this new session works. :::cta Deploy Your Server Launch a Raff Ubuntu VM and apply a deny-by-default host firewall before exposing application services. ::: **Verify:** UFW should report `Status: active`, the correct defaults, and the new independent SSH session should connect successfully. ## Step 7 — Allow only the ports and application profiles the server needs To allow a public TCP port explicitly: ```bash sudo ufw allow 443/tcp comment 'HTTPS' ``` For a normal public web server using both HTTP and HTTPS: ```bash sudo ufw allow 80/tcp comment 'HTTP' sudo ufw allow 443/tcp comment 'HTTPS' ``` This is the core `ufw allow port` pattern: specify the port and protocol you actually need rather than opening a broad range. Applications can also install UFW profiles. List them: ```bash sudo ufw app list ``` For Nginx, inspect the profile before allowing it: ```bash sudo ufw app info 'Nginx Full' ``` Then, if it matches your intended ports: ```bash sudo ufw allow 'Nginx Full' ``` Do not keep duplicate numeric rules and application-profile rules without a reason. Application profiles live under `/etc/ufw/applications.d`, and UFW's current documentation supports `ufw app info`, `app list`, and `app update` for inspecting and maintaining them. For a complete web-server path, see [Install Nginx on Ubuntu 24.04](/learn/tutorials/install-nginx-ubuntu-24-04). **Verify:** `sudo ufw status numbered` should show only the public services you deliberately intend to expose. ## Step 8 — Restrict databases and admin services by source address Do not expose a database or administrative port to `Anywhere` merely because an application needs remote access. Allow PostgreSQL only from a private subnet: ```bash sudo ufw allow proto tcp from 10.0.0.0/24 to any port 5432 \ comment 'Private PostgreSQL' ``` Allow an admin service only from one trusted public address: ```bash sudo ufw allow proto tcp from 203.0.113.5 to any port 9090 \ comment 'Admin access' ``` `203.0.113.5` is a documentation example. Replace it with the real trusted source. For multi-VM workloads, combine a [Raff VPC](/products/vpc) with correct service binding. For example, a database can bind to its private address rather than `0.0.0.0`. UFW source filtering is an additional control, not a substitute for application authentication and correct bind addresses. **Verify:** Private/admin ports should be allowed only from the expected source IP or subnet, and the application itself should listen only on the intended interface. ## Step 9 — Use rule order deliberately because the first matching rule wins UFW rule order matters. Current UFW documentation states that the **first matching rule wins**, so a broad allow placed before a more specific deny can defeat the intended restriction. Display rules in order: ```bash sudo ufw status numbered ``` To insert a rule at a specific position: ```bash sudo ufw insert 1 deny from 203.0.113.25 ``` To place an address-family-specific rule before existing rules of the same IP type: ```bash sudo ufw prepend deny from 203.0.113.25 ``` Before inserting a production rule, preview it: ```bash sudo ufw --dry-run insert 1 deny from 203.0.113.25 ``` Use rule ordering to express actual policy, not as a substitute for simplifying an overly complicated ruleset. **Verify:** `sudo ufw status numbered` should place narrow exceptions/restrictions where they will be evaluated before broader rules that could otherwise match first. ## Step 10 — Rate-limit SSH only after the basic SSH policy is correct UFW supports a `limit` action for connection-rate limiting, commonly used for SSH: ```bash sudo ufw limit OpenSSH comment 'Rate-limited SSH' ``` For a custom port: ```bash sudo ufw limit 2222/tcp comment 'Rate-limited SSH' ``` Do not add a `limit` rule alongside a broad earlier `allow` rule for the same traffic and assume the later rule will win. Check the actual ordering. UFW's rate limiting is a basic brute-force mitigation, not a substitute for SSH keys, disabling unnecessary password authentication, account controls, or upstream DDoS protection. It can also affect legitimate automation or multiple users sharing one NAT address. For SSH-key setup, use [Configure SSH Keys on Ubuntu](/learn/tutorials/configure-ssh-keys-ubuntu). **Verify:** `sudo ufw status numbered` should show the intended `LIMIT` rule in an order where a broader prior `ALLOW` does not bypass it. ## Step 11 — Delete rules safely and understand IPv4/IPv6 deletion behavior Show numbered rules: ```bash sudo ufw status numbered ``` Delete a single numbered rule: ```bash sudo ufw delete 3 ``` Run `status numbered` again after every numbered deletion because rule numbers change. When IPv6 is enabled, a generic rule can produce both IPv4 and IPv6 entries. Deleting **one numeric entry** removes only that listed rule. If you want to remove the generic rule across the address families UFW created, delete it by repeating its original syntax: ```bash sudo ufw delete allow 443/tcp ``` Reload UFW after changes that require it: ```bash sudo ufw reload ``` Avoid `ufw reset` for routine cleanup. Reset disables the firewall and returns it to installation defaults, which means you must rebuild SSH and service rules. **Verify:** The unwanted rule should be gone from both the numbered status and, when relevant, its IPv4/IPv6 counterpart. ## Step 12 — Enable useful logging and inspect more than `ufw status` Enable low-level logging: ```bash sudo ufw logging low ``` UFW supports `off`, `low`, `medium`, `high`, and `full`. Current documentation warns that higher levels can generate substantial log volume, so `low` is a sensible default for a public server. Inspect recent kernel firewall events: ```bash sudo journalctl -k -g 'UFW' --since '15 minutes ago' ``` On systems where rsyslog writes a dedicated UFW file: ```bash sudo test -f /var/log/ufw.log && \ sudo tail -n 50 /var/log/ufw.log ``` Use UFW's reports for deeper inspection: ```bash sudo ufw show listening sudo ufw show raw ``` `ufw status` shows rules managed through the UFW CLI, but current UFW documentation notes that it does not show every rule loaded from `/etc/ufw/*.rules`. `ufw show raw` is the stronger view when you need the complete firewall state. **Verify:** Logging should be enabled at the intended level, `show listening` should correlate services with firewall rules, and `show raw` should return the complete live netfilter view UFW exposes. ## Step 13 — Do not assume UFW protects Docker-published ports This is the most common advanced UFW mistake on application servers. List Docker-published ports: ```bash docker ps --format 'table {{.Names}}\t{{.Ports}}' ``` A publication such as: ```text 0.0.0.0:8080->80/tcp ``` can be reachable even when UFW appears to deny TCP 8080. Docker's current documentation explains that Docker creates NAT/firewall rules for bridge networks and that published traffic can be diverted before it reaches the `INPUT` and `OUTPUT` chains UFW normally manages. For a service intended only for a host-side reverse proxy, publish it to loopback instead: ```text 127.0.0.1:8080:80 ``` or in Compose: ```yaml ports: - "127.0.0.1:8080:80" ``` For advanced source filtering of Docker bridge traffic, use filtering appropriate to the Docker firewall backend. With Docker's iptables backend, `DOCKER-USER` is the documented pre-Docker user chain. Docker 29 also has an **experimental nftables backend**, where there is no `DOCKER-USER` chain and custom nftables chains/tables are used instead. Do not set Docker's `iptables`/`ip6tables` options to `false` casually. Docker warns that disabling its firewall-rule management without a complete replacement policy is likely to break container networking. See [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) for the container baseline. **Verify:** Private containers should not publish to `0.0.0.0` unnecessarily, and any public Docker ports must be treated as a separate firewall exposure rather than assumed protected by UFW. ## Step 14 — Run the final firewall audit and keep a safe rollback path Audit the live system: ```bash sudo ufw status verbose sudo ufw status numbered sudo ufw show listening sudo ss -tulpn sudo systemctl is-enabled ufw ``` The firewall is healthy when: - UFW is active; - incoming traffic is denied by default; - outgoing traffic is allowed unless you intentionally chose otherwise; - routed traffic is denied unless the VM is meant to forward packets; - SSH works from a fresh second connection; - public services have explicit rules; - private/admin services use source restrictions and/or private binding; - Docker-published ports have been audited separately; - IPv4 and IPv6 behavior match the server's actual network design. Test important public ports from another machine. A localhost `curl` does not prove that the same traffic is reachable from the internet. To temporarily disable UFW while preserving the configured rules: ```bash sudo ufw disable ``` To re-enable it after correcting a rule: ```bash sudo ufw enable ``` Use a full reset only when you intentionally want to rebuild the entire policy: ```bash sudo ufw reset ``` If you are locked out of SSH, use an existing open session or provider recovery console to correct the rule. Do not remove the last known-good remote-management path before a replacement has been tested. **Verify:** A fresh SSH session and every required application path should work, unnecessary ports should fail from an external client, and the rules should remain enabled across a reboot. ## Troubleshooting ### SSH stops accepting new connections after UFW is enabled Keep the original session open and check: ```bash sudo sshd -T | awk '$1 == "port" {print $2}' sudo ufw status numbered ``` Add the correct port if it is missing, then test a new session before closing the original one. ### `ufw status` says a Docker port is blocked but the container is reachable That can be expected with Docker port publishing. Inspect: ```bash docker ps --format 'table {{.Names}}\t{{.Ports}}' sudo ufw show raw ``` Bind private container ports to `127.0.0.1`, use an upstream firewall, or implement Docker-backend-aware filtering. ### A deny rule does not work Check rule ordering: ```bash sudo ufw status numbered ``` A broader allow may match first. Insert or prepend the specific restriction before the broad rule, then retest externally. ### IPv4 works but IPv6 behaves differently Check: ```bash grep '^IPV6=' /etc/default/ufw ip -6 address sudo ufw status numbered ``` Also verify public `AAAA` DNS and upstream IPv6 routing/firewall policy. ### Logging is filling the disk Reduce the level: ```bash sudo ufw logging low ``` or temporarily disable UFW-managed logging: ```bash sudo ufw logging off ``` `medium`, `high`, and `full` can be noisy on busy hosts. ### A custom rule is active but missing from `ufw status` Rules placed directly in `/etc/ufw/before.rules`, `after.rules`, or their IPv6 counterparts are not fully represented by normal `ufw status`. Inspect: ```bash sudo ufw show raw ``` ## Conclusion You now have a practical Ubuntu 24.04 UFW baseline that protects the active SSH path before enablement, denies unsolicited inbound traffic, handles IPv4 and IPv6 deliberately, opens only required ports, supports source-restricted access, respects first-match rule ordering, provides useful logging, and includes an external verification and rollback workflow. The key operational habit is to compare three views whenever the server changes: `ufw status numbered`, `ufw show listening`, and `ss -tulpn`. Firewall rules should evolve with the applications that are actually listening. Docker-published ports require a separate audit because Docker's own networking rules can bypass the assumptions behind ordinary UFW host filtering. For the next layer, continue with [Configure SSH Keys on Ubuntu](/learn/tutorials/configure-ssh-keys-ubuntu), [Secure Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server), and [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04). ## Sources - [Ubuntu Server — Firewall](https://ubuntu.com/server/docs/security-firewall/) - [Ubuntu 24.04 UFW framework manual](https://manpages.ubuntu.com/manpages/noble/man8/ufw-framework.8.html) - [Ubuntu UFW manual](https://manpages.ubuntu.com/manpages/resolute/man8/ufw.8.html) - [Docker — Packet filtering and firewalls](https://docs.docker.com/engine/network/packet-filtering-firewalls/) - [Docker — Docker with iptables](https://docs.docker.com/engine/network/firewall-iptables/) - [Docker — Docker with nftables](https://docs.docker.com/engine/network/firewall-nftables/) - Guidance re-verified: 2026-09-04 --- ### How to Harden an Ubuntu 24.04 Server URL: https://rafftechnologies.com/learn/tutorials/secure-ubuntu-24-04-server Description: Harden Ubuntu 24.04 with SSH keys, safe OpenSSH drop-ins, UFW, automatic security updates, AppArmor, access auditing, logging, and recovery checks. Ubuntu 24.04 is reasonably secure as a fresh installation, but production hardening is about reducing attack surface and making access, updates, network exposure, application confinement, logging, and recovery deliberate. A useful baseline does not come from copying a long list of random `sysctl` values or disabling every feature. It comes from verifying which users, services, ports, packages, and recovery paths your server actually needs. Raff Technologies is the VM platform used by the original tutorial. The saved tested-on record remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 2 GB RAM Linux VM; OpenSSH, UFW, unattended-upgrades, Fail2Ban, and recovery guidance reviewed in July 2026`. This revision re-verifies the workflow against current Ubuntu Server documentation on September 5, 2026 without claiming a new end-to-end machine test. This tutorial hardens a general-purpose internet-connected Ubuntu server with a non-root administrator, tested SSH keys, safe OpenSSH drop-ins, a deny-by-default UFW policy, verified automatic security updates, service/account review, AppArmor, optional Fail2Ban, logging, and a tested recovery plan. It intentionally avoids hard-coded SSH cipher lists, cargo-cult kernel tweaks, and claims of CIS/FIPS/compliance. Those controls require workload-specific testing and, where applicable, the appropriate compliance tooling. Prerequisites: - An Ubuntu 24.04 server with working administrative access - A non-root sudo-capable account, or permission to create one - A second terminal for testing new SSH sessions - A provider console/rescue path or another recovery method - Knowledge of the applications and ports the server must keep ## Step 1 — Inventory the server before changing security controls Start by recording the server state you are about to change. Confirm Ubuntu: ```bash cat /etc/os-release uname -r ``` Check the current user and sudo capability: ```bash id sudo -v ``` List listening sockets: ```bash sudo ss -tulpn ``` List failed and enabled services: ```bash systemctl --failed systemctl list-unit-files --type=service --state=enabled ``` Check the current SSH port and effective authentication settings: ```bash sudo sshd -T | grep -E \ '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication) ' ``` Check UFW and AppArmor: ```bash sudo ufw status verbose sudo aa-status ``` Do not change a control until you know which production dependency it could affect. For example, an application may need a public listener, a backup agent may require outbound access, and a deployment system may rely on a specific SSH account. **Verify:** You should have a clear list of current administrators, listening ports, enabled services, SSH settings, firewall state, and whether AppArmor is loaded. ## Step 2 — Apply pending Ubuntu updates and plan required reboots Refresh package metadata and install the updates your maintenance policy allows: ```bash sudo apt update sudo apt upgrade ``` Review packages before accepting the upgrade on a production server instead of automatically using `-y` when you need change control. Check whether a reboot is required: ```bash if [ -f /var/run/reboot-required ]; then cat /var/run/reboot-required else echo "No reboot required" fi ``` If a reboot is required, schedule it when the workload can tolerate it and confirm the server returns healthy afterward. Review configured repositories: ```bash find /etc/apt/sources.list.d -maxdepth 1 -type f -print ``` Minimize third-party repositories. Ubuntu's current security guidance explicitly recommends avoiding unnecessary third-party package sources because every additional repository adds a software supply-chain and maintenance dependency. Do not remove packages just because they look unfamiliar. Package dependencies, cloud agents, networking, boot, and storage components can be critical even when they are not obvious application dependencies. **Verify:** `apt update` should complete successfully, required upgrades should be understood/applied according to policy, and you should know whether a reboot is pending. ## Step 3 — Use a dedicated non-root administrator and verify sudo access If your image already provides a non-root sudo account, keep it and verify it instead of creating another unnecessary administrator: ```bash id sudo whoami ``` The second command should return: ```text root ``` If you are currently administering the machine only as root, create a replacement account. Replace `deploy` with your chosen username: ```bash sudo adduser deploy sudo usermod -aG sudo deploy ``` Verify membership: ```bash id deploy ``` Then test the new account in a separate session before changing root SSH access: ```bash ssh deploy@your_server_ip sudo whoami ``` Use separate administrator identities where practical. Sharing one Linux account or one private key between several people makes revocation and log attribution harder. Review current sudo members: ```bash getent group sudo ``` **Verify:** At least one non-root administrator should have a tested SSH path and working `sudo`, and every sudo member should have a current operational reason for that access. ## Step 4 — Install and test SSH key authentication before disabling passwords Generate an Ed25519 key on the administrator's local computer if needed: ```bash ssh-keygen -t ed25519 -C "ubuntu-admin" ``` Copy only the public key to the server: ```bash ssh-copy-id your_user@your_server_ip ``` On the server, review key permissions: ```bash chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R "$USER":"$USER" ~/.ssh ``` Open a **new** terminal and verify key authentication: ```bash ssh your_user@your_server_ip ``` Do not disable password authentication, root login, or the old working access method until this separate key-based session succeeds. For key rotation, multiple administrators, and client configuration, use [Generate SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04). **Verify:** A new independent SSH session should authenticate with the intended public key and the account should still have working sudo access. ## Step 5 — Harden OpenSSH with an early drop-in and verify the effective configuration Ubuntu places this line near the top of `/etc/ssh/sshd_config`: ```text Include /etc/ssh/sshd_config.d/*.conf ``` OpenSSH uses the **first obtained value** for most directives. That means a late file name such as `99-hardening.conf` does not necessarily override an earlier snippet. Inspect existing snippets first: ```bash sudo ls -1 /etc/ssh/sshd_config.d/ sudo grep -RniE \ '^(PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|PubkeyAuthentication|MaxAuthTries|LoginGraceTime)' \ /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null || true ``` Create an early local hardening snippet: ```bash sudo tee /etc/ssh/sshd_config.d/00-raff-hardening.conf > /dev/null <<'EOF' PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no MaxAuthTries 3 LoginGraceTime 30 EOF ``` Protect it with normal root-owned configuration permissions: ```bash sudo chown root:root /etc/ssh/sshd_config.d/00-raff-hardening.conf sudo chmod 644 /etc/ssh/sshd_config.d/00-raff-hardening.conf ``` Validate syntax: ```bash sudo sshd -t ``` Then verify **effective values**, which is more important than merely reading the file: ```bash sudo sshd -T | grep -E \ '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|logingracetime) ' ``` If your configuration uses `Match` blocks, evaluate the intended user/context as well: ```bash sudo sshd -T -C user="$USER",host="$(hostname)",addr=127.0.0.1 | \ grep -E '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|logingracetime) ' ``` Restart SSH only after validation: ```bash sudo systemctl restart ssh.service ``` Keep the original session open. Test a new key-based login again, then confirm a password-only attempt is rejected: ```bash ssh -o PreferredAuthentications=password \ -o PubkeyAuthentication=no \ your_user@your_server_ip ``` Do not hard-code custom `Ciphers`, `MACs`, or `KexAlgorithms` in a general baseline unless a defined security/compliance requirement calls for it. Ubuntu's OpenSSH defaults evolve with security updates; custom crypto lists need compatibility testing and long-term maintenance. **Verify:** `sshd -t` should pass, `sshd -T` should show the intended settings, a fresh key login should work, and password-only/root SSH access should not provide an unintended login path. ## Step 6 — Configure UFW without risking SSH lockout Determine the effective SSH port: ```bash sudo sshd -T | awk '$1 == "port" {print $2}' ``` If SSH uses the standard OpenSSH profile, inspect and allow it before enabling UFW: ```bash sudo ufw app info OpenSSH sudo ufw allow OpenSSH comment 'SSH administration' ``` For a custom SSH port, allow the actual port instead: ```bash sudo ufw allow 2222/tcp comment 'SSH administration' ``` Set a common application-server baseline: ```bash sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw default deny routed ``` Review before enabling: ```bash sudo ufw show added sudo ufw --dry-run enable ``` Then enable and inspect: ```bash sudo ufw enable sudo ufw status verbose ``` Open another new SSH connection before closing existing sessions. Only add application ports when a real service requires them. For example, a public web server may need TCP 80/443; a private database normally should not be opened to `Anywhere`. :::cta Deploy Your Hardened Server Launch a Raff Ubuntu VM and apply this layered security baseline before placing production workloads on it. ::: For source restrictions, IPv6, rule ordering, Docker caveats, and rollback, use [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). **Verify:** UFW should be active with deny-incoming/deny-routed defaults, the correct SSH rule should exist, and a second SSH connection should still succeed. ## Step 7 — Verify automatic security updates instead of overwriting Ubuntu defaults blindly Ubuntu Server uses `unattended-upgrades` for automatic security updates and current Ubuntu documentation states that security updates are applied automatically by default. Check whether the package is installed: ```bash dpkg -s unattended-upgrades 2>/dev/null | grep '^Status:' || true ``` Install it only if it is absent: ```bash sudo apt install -y unattended-upgrades ``` Inspect the periodic settings: ```bash apt-config dump | grep -E \ 'APT::Periodic::(Update-Package-Lists|Unattended-Upgrade)' ``` Inspect the timers that drive APT maintenance: ```bash systemctl list-timers apt-daily.timer apt-daily-upgrade.timer --all ``` Review the actual unattended-upgrades policy: ```bash sudo less /etc/apt/apt.conf.d/50unattended-upgrades ``` Test it without installing packages: ```bash sudo unattended-upgrade --dry-run --debug ``` Review recent service activity: ```bash sudo journalctl -u unattended-upgrades --since '7 days ago' --no-pager ``` Do not assume third-party repositories are included just because they exist in APT. Ubuntu's current documentation explicitly notes that adding a repository does not automatically make `unattended-upgrades` select packages from that origin. Automatic reboot behavior is workload-dependent. Do not enable unattended reboots blindly on a single production node; define a maintenance/redundancy strategy first. **Verify:** The APT timers should be scheduled, unattended security upgrades should be enabled according to your policy, the dry run should complete without configuration errors, and third-party origins should be consciously included or excluded. ## Step 8 — Remove or disable only services you have positively identified as unnecessary Audit listeners again: ```bash sudo ss -tulpn ``` Review enabled services: ```bash systemctl list-unit-files --type=service --state=enabled ``` Inspect a service before disabling it: ```bash systemctl status service-name systemctl cat service-name ``` Only after confirming it is not needed: ```bash sudo systemctl disable --now service-name ``` Review package cleanup candidates without immediately deleting them: ```bash sudo apt autoremove --dry-run ``` Do not use a generic hardening list to remove packages, disable IPv6, disable ICMP, turn off forwarding, or change kernel parameters without understanding the server role. Those actions can break containers, VPNs, routing, monitoring, clustering, cloud networking, and application dependencies. For each public listener, answer four questions: 1. Does the service need to run? 2. Does it need to listen on this interface? 3. Does it need a public firewall rule? 4. How is it authenticated and updated? **Verify:** Every remaining listening service and enabled boot service should have a documented operational purpose, and no unreviewed package/service should have been removed merely because it looked unfamiliar. ## Step 9 — Keep AppArmor enabled and inspect confinement status AppArmor is Ubuntu's mandatory access control system. Current Ubuntu documentation states that it is installed and loaded by default, and strongly recommends using it as a defense-in-depth layer. Check its state: ```bash sudo aa-status ``` Also check the profile-loading service: ```bash systemctl is-enabled apparmor.service systemctl status apparmor.service --no-pager ``` Review recent AppArmor denials: ```bash sudo journalctl -k -g 'apparmor="DENIED"' --since '24 hours ago' --no-pager ``` Do not disable AppArmor globally because one application fails. Ubuntu 24.04 integrates AppArmor more deeply into the kernel than older releases, and disabling it reduces the system's security posture. First determine which profile denied which operation, then make a narrow local profile adjustment when the application genuinely requires that access. Optional profile-management tools are available through: ```bash sudo apt install apparmor-utils ``` Do not force experimental profiles into enforcement on a production application without testing. `complain` mode is useful when developing or validating a profile; `enforce` mode blocks violations. **Verify:** `aa-status` should show AppArmor loaded with profiles present, and any `DENIED` events should be understood rather than worked around by disabling AppArmor wholesale. ## Step 10 — Audit administrator accounts, SSH keys, and stale access List users with interactive shells: ```bash awk -F: '$7 !~ /(nologin|false)$/ {print $1, $6, $7}' /etc/passwd ``` Review sudo access: ```bash getent group sudo ``` Find authorized-key files under normal home directories: ```bash sudo find /home -maxdepth 3 -type f -name authorized_keys -print ``` Review each administrative user's key file with line numbers, for example: ```bash sudo nl -ba /home/deploy/.ssh/authorized_keys ``` Disabling a user's Unix password does **not** revoke an already-authorized SSH public key. When removing access, audit both the account and its `authorized_keys`, active sessions, deployment systems, CI/CD credentials, API tokens, and any external identity source. If multiple people administer the server, use individual accounts/keys rather than one shared private key. Do not add an OpenSSH `AllowUsers`/`AllowGroups` rule until you have inventoried every required human and automation identity; an incomplete allowlist is a common lockout source. **Verify:** Every interactive account, sudo member, and authorized SSH key should map to a current owner or automation purpose, with stale access removed through a tested change process. ## Step 11 — Add Fail2Ban only when it solves a real log-based attack surface Fail2Ban is optional. It watches authentication/log events and temporarily blocks sources that repeatedly match failure patterns. It is not a substitute for SSH keys, firewall restrictions, timely updates, or upstream DDoS controls. If your public SSH service receives repeated authentication noise and Fail2Ban fits the threat model, use the dedicated tutorial: [Install Fail2Ban on Ubuntu 24.04 for SSH Protection](/learn/tutorials/install-fail2ban-ubuntu-24-04) At minimum, if Fail2Ban is already installed, verify the service and SSH jail: ```bash systemctl is-active fail2ban sudo fail2ban-client status sudo fail2ban-client status sshd ``` Review its recent logs: ```bash sudo journalctl -u fail2ban --since '24 hours ago' --no-pager ``` Do not infer security quality from raw ban counts. Internet scanning levels, SSH exposure, authentication methods, jail thresholds, and source networks all change how many bans a server records. **Verify:** If Fail2Ban is part of your design, it should be active with only intended jails; if it is not part of your design, SSH should still be protected by the stronger primary controls already configured. ## Step 12 — Review time, authentication logs, failed units, disk, and security signals Correct time is required for authentication, TLS validation, logs, package metadata, and incident reconstruction. Check synchronization: ```bash timedatectl status ``` Review SSH events: ```bash sudo journalctl -u ssh --since '24 hours ago' --no-pager ``` Review warning-or-higher system messages: ```bash sudo journalctl -p warning --since '24 hours ago' --no-pager ``` Check failed services: ```bash systemctl --failed ``` Check disk and inode pressure: ```bash df -h df -i ``` Review recent logins: ```bash last -a | head -n 20 ``` If your environment has centralized logging or monitoring, forward security-relevant events off the server so an attacker with root access cannot silently erase the only copy. Define alerts around unexpected service failures, disk exhaustion, authentication anomalies, newly exposed ports, and backup failures rather than relying on manual review alone. **Verify:** Time synchronization should be healthy, there should be no unexplained failed services or disk exhaustion, and suspicious authentication/system events should have an investigation path. ## Step 13 — Prepare backups and a recovery path before declaring the server hardened A security change can be correct and still cause an outage. A hardened server needs a recovery path that does not depend on the same control you might accidentally break. Before production use: - keep application/data backups on an appropriate schedule; - retain at least one recovery copy outside the VM; - protect backup credentials separately from application credentials; - test restoring critical data and configuration; - document the SSH port, UFW policy, administrator identities, and important service paths; - verify a provider console, rescue environment, or equivalent out-of-band path before removing the last known-good SSH method. Raff [Data Protection](/products/data-protection) can provide an infrastructure-level recovery layer. Application-aware backups remain necessary for databases and workloads that need consistency beyond a VM-level recovery point. Do not call a backup strategy complete merely because jobs report success. Restore testing is what proves that the backup is usable. **Verify:** You should know how to regain administrative access after an SSH/UFW mistake and how to restore the server's critical application data/configuration from a separate recovery copy. ## Step 14 — Run the final Ubuntu server hardening checklist Verify SSH syntax and effective settings: ```bash sudo sshd -t sudo sshd -T | grep -E \ '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|logingracetime) ' ``` Verify firewall and network exposure: ```bash sudo ufw status numbered sudo ufw show listening sudo ss -tulpn ``` Verify AppArmor: ```bash sudo aa-status ``` Verify automatic updates: ```bash systemctl list-timers apt-daily.timer apt-daily-upgrade.timer --all sudo unattended-upgrade --dry-run ``` Verify accounts and service health: ```bash getent group sudo systemctl --failed ``` Check pending package updates and reboot state: ```bash sudo apt update apt list --upgradable 2>/dev/null test -f /var/run/reboot-required && \ cat /var/run/reboot-required || \ echo "No reboot required" ``` Finally, test from another machine: 1. a fresh key-based SSH session works; 2. password-only SSH does not provide an unintended login path; 3. required public application ports work; 4. unnecessary ports are not reachable; 5. backup/recovery access is documented and tested. This tutorial is a practical baseline, not a certification. If your organization must meet CIS, FIPS, PCI DSS, HIPAA, SOC 2 controls, or another standard, map the applicable requirements to the actual system and use supported auditing/compliance tooling. Do not claim compliance simply because a generic server-hardening checklist was completed. **Verify:** The server should pass the final checks with no unexplained access, listeners, failed services, pending recovery gap, or security control that exists only on paper. ## Troubleshooting ### A new SSH session stops working after the hardening change Keep an existing session open and check: ```bash sudo sshd -t sudo sshd -T | grep -E \ '^(port|permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication) ' sudo ufw status numbered ``` Inspect all snippets because an earlier file may have supplied the first value: ```bash sudo ls -1 /etc/ssh/sshd_config.d/ sudo grep -RniE \ '^(PermitRootLogin|PubkeyAuthentication|PasswordAuthentication|KbdInteractiveAuthentication)' \ /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null ``` Correct the effective setting before restarting SSH again. ### `PasswordAuthentication no` appears in a file but `sshd -T` says `yes` OpenSSH normally uses the first obtained value for most directives. Another earlier snippet may already define the option. Inspect snippet order and use `sshd -T` as the authority for the effective configuration. ### UFW is active but a Docker container port is still reachable Docker-published traffic can bypass ordinary UFW host-filter assumptions. Inspect: ```bash docker ps --format 'table {{.Names}}\t{{.Ports}}' sudo ufw show raw ``` Bind private container ports to loopback or use Docker-aware/upstream filtering. The full Docker caveat is covered in the UFW tutorial. ### `unattended-upgrade --dry-run` does not include a third-party package That can be expected. Adding an APT repository does not automatically add its origin to the unattended-upgrades policy. Review `/etc/apt/apt.conf.d/50unattended-upgrades` and the third-party vendor's supported update approach before modifying allowed origins. ### AppArmor blocks an application Inspect the denial rather than disabling AppArmor: ```bash sudo journalctl -k -g 'apparmor="DENIED"' --since '1 hour ago' --no-pager ``` Identify the profile and operation, then make a narrow tested profile adjustment if the access is legitimately required. ### A security scanner demands many sysctl or SSH crypto changes Determine which benchmark/profile generated the finding and whether it applies to this server. Security benchmark recommendations can conflict with application functionality and distro defaults. Apply standards-driven changes through a tested compliance process rather than copying them into a general baseline. ## Conclusion You now have an Ubuntu 24.04 hardening baseline built around verified access and reduced attack surface: non-root administration, tested SSH keys, effective OpenSSH configuration checks, deny-by-default UFW, automatic security updates, service/account review, AppArmor confinement, optional Fail2Ban, security logging, and recovery planning. The most important operational habit is continuous verification. Re-run the listener, firewall, account, update, AppArmor, service-health, and backup checks after application deployments and access changes. Hardening is not a one-time state and it is not synonymous with compliance; it is an ongoing process of keeping the server's privileges and exposed surface aligned with what the workload actually requires. For adjacent procedures, use [Generate SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04), [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Install Fail2Ban on Ubuntu 24.04](/learn/tutorials/install-fail2ban-ubuntu-24-04). ## Sources - [Ubuntu Server — Security suggestions](https://ubuntu.com/server/docs/explanation/security/security_suggestions/) - [Ubuntu Server — OpenSSH server](https://ubuntu.com/server/docs/how-to/security/openssh-server/) - [Ubuntu Server — User management](https://ubuntu.com/server/docs/how-to/security/user-management/) - [Ubuntu Server — Automatic updates](https://ubuntu.com/server/docs/how-to/software/automatic-updates/) - [Ubuntu Server — AppArmor](https://ubuntu.com/server/docs/how-to/security/apparmor/) - [Ubuntu Server — Firewall](https://ubuntu.com/server/docs/security-firewall/) - Upstream guidance re-verified: 2026-09-05 --- ### How to Deploy Uptime Kuma with Docker on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/deploy-uptime-kuma-docker-ubuntu-24-04 Description: Deploy Uptime Kuma 2 with Docker Compose on Ubuntu 24.04 using localhost-only port 3001, Caddy HTTPS, monitors, status pages, backups, and safe updates. Uptime Kuma is a self-hosted monitoring application for checking websites, APIs, network services, certificates, and other endpoints from your own server. A safer production pattern on Ubuntu 24.04 is to run Uptime Kuma with Docker Compose, keep its application port bound only to `127.0.0.1:3001`, and let Caddy expose the dashboard over public HTTPS. This avoids publishing the Uptime Kuma web service directly to every network interface. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Ubuntu 24.04 LTS on Raff 1 vCPU / 2 GB RAM VM`. This revision updates the deployment against current Uptime Kuma v2 documentation and Uptime Kuma **2.5.3**, the latest stable release verified on September 5, 2026. It does not claim a new benchmark or a fresh end-to-end hardware retest. The official Uptime Kuma Docker documentation requires `/app/data` to live on a filesystem with working POSIX file locks and specifically warns about file-locking problems with storage such as NFS. This guide therefore keeps the data directory on local VM storage, backs it up before upgrades, and treats the backup as sensitive because it can contain monitoring configuration, users, notification credentials, and application history. Prerequisites: - An Ubuntu 24.04 VM with SSH and sudo access - Docker Engine and Docker Compose v2 - A domain such as `status.example.com` pointed to the VM - TCP 80 and 443 available for Caddy - A second administrative SSH session or recovery path before firewall changes ## Step 1 — Verify Ubuntu, DNS, Docker, ports, and local storage Confirm the operating system: ```bash cat /etc/os-release ``` Verify Docker and Compose: ```bash docker --version docker compose version ``` If Docker is not installed, use [How to Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04) before continuing. Check the domain in both address families: ```bash dig +short A status.example.com dig +short AAAA status.example.com ``` Check whether another service already owns the public web ports: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` Check free disk space and filesystem type for `/opt`: ```bash df -h /opt df -T /opt ``` Uptime Kuma's current install documentation warns that its data directory needs a filesystem with POSIX file-lock support. Keep `/app/data` on normal local storage for this deployment rather than an NFS-style mount. **Verify:** Ubuntu should report 24.04, Docker Compose should work, DNS should point to this VM, ports 80/443 should be available or intentionally owned by your reverse proxy, and `/opt` should be backed by suitable local storage. ## Step 2 — Create a dedicated Uptime Kuma project directory Create the deployment directory: ```bash sudo install -d -o "$USER" -g "$USER" /opt/uptime-kuma cd /opt/uptime-kuma ``` Create the local data and backup directories: ```bash mkdir -p data backups chmod 700 backups ``` The project will use: ```text /opt/uptime-kuma/ ├── compose.yaml ├── data/ └── backups/ ``` The `data` directory is mapped to `/app/data` in the container. Do not place it on unsupported network storage merely to make backups easier. **Verify:** `/opt/uptime-kuma`, `data`, and `backups` should exist and be writable by your administrative user. ## Step 3 — Pin Uptime Kuma 2.5.3 in Docker Compose Uptime Kuma's official Docker tags documentation recommends the `2` tag for the current v2 release line. This tutorial pins the exact stable release verified on September 5, 2026 so a later `docker compose pull` cannot silently move the tutorial to a newer application version. Create `compose.yaml`: ```bash cd /opt/uptime-kuma nano compose.yaml ``` Add: ```yaml services: uptime-kuma: image: louislam/uptime-kuma:2.5.3 container_name: uptime-kuma restart: unless-stopped ports: - "127.0.0.1:3001:3001" volumes: - ./data:/app/data ``` Do not use `louislam/uptime-kuma:latest` for a v2 deployment. Current upstream documentation marks `latest` as deprecated and notes that it points to the v1 line. Validate the Compose file: ```bash docker compose config -q docker compose config --services ``` Inspect the rendered port mapping: ```bash docker compose config | grep -A 8 -n 'ports:' ``` **Verify:** Compose validation should succeed, the service should be `uptime-kuma`, the image should be `2.5.3`, and host port 3001 should be bound to `127.0.0.1` rather than `0.0.0.0`. ## Step 4 — Pull the image and start Uptime Kuma Pull the pinned image: ```bash cd /opt/uptime-kuma docker compose pull ``` Start the stack: ```bash docker compose up -d ``` Check its state: ```bash docker compose ps ``` Inspect startup logs: ```bash docker compose logs --tail=100 uptime-kuma ``` Check the image actually in use: ```bash docker inspect uptime-kuma --format '{{.Config.Image}}' ``` **Verify:** The container should remain running without a restart loop, logs should not show repeated database/file-lock errors, and the inspected image should be `louislam/uptime-kuma:2.5.3`. ## Step 5 — Verify Uptime Kuma is reachable locally but not published publicly Test the local backend: ```bash curl -I http://127.0.0.1:3001 ``` An HTTP response such as `200`, `302`, or another valid application response confirms that the web service is listening. Inspect host listeners: ```bash sudo ss -lntp | grep ':3001' ``` The intended host-side listener is: ```text 127.0.0.1:3001 ``` Check Docker's published ports: ```bash docker compose ps ``` Because this Compose file publishes only to loopback, you do not need a public UFW rule for TCP 3001. This matters because Docker's published-port firewall rules can bypass assumptions based on ordinary UFW `INPUT` filtering. Binding a private backend to loopback is stronger than publishing `0.0.0.0:3001` and hoping a host firewall rule always protects it. **Verify:** Uptime Kuma should answer on `127.0.0.1:3001`, and there should be no `0.0.0.0:3001` or public IPv6 listener for the application port. ## Step 6 — Install Caddy for the public HTTPS endpoint Install prerequisites: ```bash sudo apt update sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl ``` Add Caddy's official repository key: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \ sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg ``` Add the stable repository: ```bash curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \ sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install -y caddy ``` Uptime Kuma's reverse-proxy documentation recommends HTTPS for public deployments and notes that its application uses WebSockets. Caddy's `reverse_proxy` supports WebSocket upgrades automatically, so no Nginx-style manual `Upgrade`/`Connection` header boilerplate is needed here. For the full proxy workflow, see [Caddy Reverse Proxy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy). **Verify:** `caddy version` should return a version, and `systemctl is-active caddy` should report `active` unless another process is still occupying ports 80/443. ## Step 7 — Configure UFW without opening port 3001 Check UFW first: ```bash sudo ufw status verbose ``` If UFW is already active, confirm the SSH path you are using is allowed, then add public web traffic: ```bash sudo ufw allow 80/tcp comment 'HTTP for Caddy' sudo ufw allow 443/tcp comment 'HTTPS for Caddy' ``` Do **not** add a public rule for port 3001. If UFW is inactive, do not blindly run `ufw enable` over a remote connection. Configure and verify SSH access first using [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). If a provider-side firewall is also used, allow the required administration path and public TCP 80/443 there as well. **Verify:** SSH should still work from a fresh connection, public 80/443 should be permitted as intended, and there should be no deliberate public firewall rule for 3001. ## Step 8 — Reverse proxy Uptime Kuma through Caddy Back up the current Caddy configuration: ```bash sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak ``` Configure the status hostname: ```bash sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF' status.example.com { reverse_proxy 127.0.0.1:3001 } EOF ``` Replace `status.example.com` with your real hostname. Uptime Kuma's current reverse-proxy documentation says it does not support being served from a normal URL subdirectory such as `/uptimekuma`; use a domain or subdomain instead. Format and validate: ```bash sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo caddy validate --config /etc/caddy/Caddyfile ``` Reload Caddy: ```bash sudo systemctl reload caddy ``` Test HTTP redirect and HTTPS: ```bash curl -I http://status.example.com curl -I https://status.example.com ``` **Verify:** HTTP should redirect to HTTPS, HTTPS should return an Uptime Kuma response with a trusted certificate, and Caddy should proxy to the loopback backend without a 502 error. ## Step 9 — Complete the first-run database and administrator setup Open: ```text https://status.example.com ``` Complete Uptime Kuma's first-run setup. For this single-node Docker deployment, keep the application data under the local `/app/data` mount and use the default/local database path presented by the installer unless you have a separately designed external database architecture. ![Uptime Kuma database setup screen on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/uptime_kuma_docker_ubuntu_24_04_01_database_setup_webp_ab1c8bf320.png) Create the administrator account with a unique strong password. ![Uptime Kuma dashboard after first login on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/uptime_kuma_docker_ubuntu_24_04_02_dashboard_webp_214882a499.png) Do not expose setup over raw HTTP on a public interface merely for convenience. Complete account creation through the HTTPS hostname. **Verify:** You should be able to log in through `https://status.example.com`, reach the dashboard, and confirm that subsequent container recreation does not return you to a fresh unconfigured instance. ## Step 10 — Add and verify an HTTP(s) monitor Create a new HTTP(s) monitor in the dashboard. A practical starter configuration is: ```text Monitor Type: HTTP(s) Friendly Name: Raff Website URL: https://rafftechnologies.com Heartbeat Interval: 60 seconds Retries: 0 Accepted Status Codes: 200-299 ``` Uptime Kuma v2 changed the default retry count for newly created monitors to `0`. Add retries only when they reflect the failure semantics you actually want; retries delay alerting and can hide short outages if configured too aggressively. ![Uptime Kuma HTTP monitor configuration screen](https://raff-images.s3.raffusercloud.com/uptime_kuma_docker_ubuntu_24_04_03_add_monitor_webp_27c995437c.png) Before blaming Uptime Kuma when a monitor stays down, test the target from the monitoring VM: ```bash curl -I https://rafftechnologies.com ``` Inspect application logs if needed: ```bash cd /opt/uptime-kuma docker compose logs --tail=100 uptime-kuma ``` **Verify:** The monitor should save successfully and eventually report `Up` when the target is reachable and its response matches your accepted status criteria. ## Step 11 — Configure notifications without leaking provider secrets Uptime Kuma supports multiple native notification providers and can also integrate with Apprise for additional services. Open the dashboard's notification settings, choose the provider you actually use, enter its credentials/webhook/token, and use Uptime Kuma's test action before attaching the notification to production monitors. Treat notification credentials as secrets. Avoid: - pasting webhook URLs or API tokens into public screenshots; - committing notification credentials to Git; - copying the Uptime Kuma `data` directory to an unprotected shared location; - sending full backups through chat or ticket systems without encryption/access controls. After adding the notification, attach it to the monitor and test a controlled notification path rather than creating a real outage on a production service. **Verify:** The provider's test notification should arrive at the intended destination, and no credential should be present in `compose.yaml`, shell history, or public documentation unless that provider explicitly requires an environment-based deployment design. ## Step 12 — Create a public status page with the correct expectations Create a status page from the Uptime Kuma dashboard and add only the monitors you intend to expose publicly. Uptime Kuma's current status-page documentation says status pages are intended for public users, cache results for **5 minutes**, and refresh on a **5-minute** cycle. They therefore should not be described as identical to the authenticated dashboard's live update behavior. You can use multiple status pages and, when needed, map a status page to a dedicated domain. If you use domain-based status pages behind a reverse proxy, make sure the proxy preserves the host information Uptime Kuma needs. Caddy does this appropriately in the normal reverse-proxy flow. Do not put internal hostnames, private IPs, customer names, incident notes, or sensitive infrastructure labels on a public status page unless disclosure is intentional. **Verify:** Open the status page in a private/incognito browser session and confirm that it shows only the intended services without exposing administrative controls or sensitive monitor details. ## Step 13 — Back up `/app/data` before updates or migrations Uptime Kuma v2 removed the old JSON backup/restore feature; current upstream migration guidance says backing up the **data directory** is the supported backup method. Create a timestamped backup directory: ```bash cd /opt/uptime-kuma STAMP="$(date +%F-%H%M%S)" BACKUP_DIR="/opt/uptime-kuma/backups/$STAMP" mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" ``` Stop Uptime Kuma for a consistent filesystem-level copy: ```bash docker compose stop uptime-kuma ``` Archive the local data directory and Compose configuration: ```bash tar -czf "$BACKUP_DIR/uptime-kuma-data.tar.gz" -C /opt/uptime-kuma data cp compose.yaml "$BACKUP_DIR/" sudo cp /etc/caddy/Caddyfile "$BACKUP_DIR/Caddyfile" ``` Restart the application: ```bash docker compose start uptime-kuma ``` Inspect the archive: ```bash ls -lh "$BACKUP_DIR" tar -tzf "$BACKUP_DIR/uptime-kuma-data.tar.gz" | head ``` Keep a protected copy outside this VM. The backup can contain monitoring metadata and notification credentials, so access to the backup should be at least as restricted as access to the dashboard itself. Raff [Data Protection](/products/data-protection) can provide an infrastructure-level recovery layer, but an application-level `/app/data` backup remains valuable before Uptime Kuma upgrades and migrations. **Verify:** The backup should contain the complete local `data` directory plus Compose/Caddy configuration, Uptime Kuma should return to a running state, and at least one protected copy should exist away from the live VM. ## Step 14 — Update, troubleshoot, verify end to end, and roll back safely Before an application update, read the Uptime Kuma release notes and create a fresh backup. This tutorial pins `2.5.3`. To move to a later stable v2 release, edit only the image tag after reviewing the target release: ```bash cd /opt/uptime-kuma nano compose.yaml ``` Then pull and recreate: ```bash docker compose pull docker compose up -d --force-recreate ``` Check state and logs immediately: ```bash docker compose ps docker compose logs --tail=120 uptime-kuma docker inspect uptime-kuma --format '{{.Config.Image}}' ``` The official update workflow also uses `docker compose pull` followed by `docker compose up -d --force-recreate`. If you are still running Uptime Kuma v1 elsewhere, do **not** treat v1→v2 as an ordinary image update. Upstream calls it a major migration, requires a backup of the data directory, warns that migration can take significant time, and says the migration should not be interrupted. If Caddy returns 502: ```bash curl -I http://127.0.0.1:3001 sudo journalctl -u caddy -n 100 --no-pager docker compose logs --tail=100 uptime-kuma ``` If the monitor stays down: ```bash curl -I https://your-monitored-target.example docker compose logs --tail=100 uptime-kuma ``` If you forget the administrator password, upstream documents a container CLI reset path. Enter the container and run the reset tool, then choose a strong replacement password: ```bash docker exec -it uptime-kuma bash npm run reset-password ``` For the final end-to-end audit: ```bash cd /opt/uptime-kuma docker compose config -q docker compose ps sudo ss -lntp | grep -E ':(80|443|3001)\b' || true curl -I https://status.example.com sudo ufw status numbered ``` Expected architecture: ```text Internet | | HTTPS 443 v Caddy | | 127.0.0.1:3001 v Uptime Kuma 2.5.3 | v local /app/data ``` To stop the application without deleting monitoring data: ```bash docker compose down ``` The bind-mounted `/opt/uptime-kuma/data` directory remains. To start again: ```bash docker compose up -d ``` To remove Uptime Kuma permanently, first verify an external backup, then remove the stack and project data only when deletion is intentional. Do not casually delete `/opt/uptime-kuma/data` during troubleshooting. **Verify:** The dashboard should load over HTTPS, the admin can log in, the monitor should report correctly, notifications/status page should work as designed, port 3001 should remain loopback-only, the data directory should persist across container recreation, and a tested backup should exist before any version change. ## Conclusion You now have Uptime Kuma v2 running on Ubuntu 24.04 with Docker Compose, local persistent storage, loopback-only application exposure, Caddy HTTPS, a verified HTTP monitor, optional notifications and a public status page, plus a backup and controlled update workflow. The important operational boundaries are straightforward: keep `/app/data` on a filesystem with proper POSIX locks, do not publish port 3001 unnecessarily, treat the data backup as sensitive, and never upgrade a v1 deployment to v2 without following the dedicated migration process. Recheck the monitoring VM itself after major updates so the system responsible for reporting outages does not quietly become an unmonitored failure point. For adjacent procedures, use [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Caddy Reverse Proxy on Ubuntu 24.04](/learn/tutorials/install-caddy-ubuntu-24-04-reverse-proxy), and [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). ## Sources - [Uptime Kuma — How to Install](https://github.com/louislam/uptime-kuma/wiki/%F0%9F%94%A7-How-to-Install) - [Uptime Kuma — Docker Tags](https://github.com/louislam/uptime-kuma/wiki/Docker-Tags) - [Uptime Kuma — Releases](https://github.com/louislam/uptime-kuma/releases) - [Uptime Kuma — Reverse Proxy](https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy) - [Uptime Kuma — How to Update](https://github.com/louislam/uptime-kuma/wiki/%F0%9F%86%99-How-to-Update) - [Uptime Kuma — Migration from v1 to v2](https://github.com/louislam/uptime-kuma/wiki/Migration-From-v1-To-v2) - [Uptime Kuma — Status Page](https://github.com/louislam/uptime-kuma/wiki/Status-Page) - [Uptime Kuma — Notification Methods](https://github.com/louislam/uptime-kuma/wiki/Notification-Methods) - Upstream guidance re-verified: 2026-09-05 --- ### How to Install OpenClaw on Ubuntu 24.04 with Telegram URL: https://rafftechnologies.com/learn/tutorials/deploy-openclaw-ai-agent-ubuntu-24-04 Description: Install OpenClaw on Ubuntu 24.04 with Telegram pairing, a loopback-only Gateway, secure credentials, SSH-tunneled Control UI, backups, and safe updates. OpenClaw is a self-hosted AI assistant that connects model providers, tools, messaging channels, and a local control Gateway. On an Ubuntu 24.04 VM, the safest baseline is to keep the Gateway on its default **loopback-only** bind, run it as the managed user service installed by OpenClaw, connect Telegram through long polling, and avoid opening the Gateway port to the public internet. Telegram does not need an inbound web port in this default mode. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 4 GB RAM VM`. This revision re-verifies the deployment against current OpenClaw documentation on September 5, 2026 and pins **OpenClaw 2026.9.1**, the current npm `latest` release at verification time. It does not claim a new hardware benchmark or a fresh end-to-end retest. OpenClaw's Gateway listens on port `18789` and binds to loopback by default. Current upstream security guidance explicitly recommends keeping it on loopback where possible, using an SSH tunnel or Tailscale Serve for remote UI access, and never exposing an unauthenticated Gateway on `0.0.0.0`. This tutorial therefore does not add a public UFW rule for 18789. Prerequisites: - An Ubuntu 24.04 VM with SSH and sudo access - A non-root administrative user - A supported model-provider login or API key - A Telegram account - A Telegram bot token created with the real `@BotFather` - A second SSH session or recovery path before changing firewall/access settings ## Step 1 — Verify Ubuntu, resources, SSH, and network exposure Confirm the OS: ```bash cat /etc/os-release uname -r ``` Check memory and disk space: ```bash free -h df -h / ``` Confirm your current identity and sudo access: ```bash id sudo -v ``` List listening ports before installing anything: ```bash sudo ss -tulpn ``` Keep the current SSH session open while you work. Open a second SSH session now so you know the recovery path works before hardening or firewall changes. **Verify:** Ubuntu should report 24.04, sudo should work for the administrative user, and you should know which services/ports are already listening before OpenClaw is installed. ## Step 2 — Apply Ubuntu updates and check for a required reboot Update package metadata and review available upgrades: ```bash sudo apt update apt list --upgradable 2>/dev/null ``` Apply the updates according to your maintenance policy: ```bash sudo apt upgrade ``` Check whether a reboot is required: ```bash if [ -f /var/run/reboot-required ]; then cat /var/run/reboot-required else echo "No reboot required" fi ``` If a reboot is required, schedule it before installing the long-running Gateway service, then reconnect and confirm the VM is healthy. **Verify:** `apt update` should finish without repository errors, required security updates should be understood/applied, and any necessary reboot should be completed before continuing. ## Step 3 — Inspect and dry-run the official OpenClaw installer OpenClaw's current recommended Linux installer checks the operating system, verifies or installs a supported Node.js runtime, installs OpenClaw through npm by default, and can manage onboarding. On Linux it provisions the supported Node 24 LTS path when Node is missing; OpenClaw currently supports Node 22.22.3+, 24.15+, and 25.9+ and recommends Node 26 where appropriate. Download the official installer instead of immediately piping it into a shell: ```bash curl -fsSL --proto '=https' --tlsv1.2 \ https://openclaw.ai/install.sh \ -o /tmp/openclaw-install.sh ``` Inspect the beginning of the script and its help output: ```bash head -n 40 /tmp/openclaw-install.sh bash /tmp/openclaw-install.sh --help ``` Preview the exact install without changing the server: ```bash bash /tmp/openclaw-install.sh \ --dry-run \ --version 2026.9.1 \ --no-onboard ``` **Verify:** The script should come from `https://openclaw.ai/install.sh`, help output should display normal installer options, and the dry run should target OpenClaw `2026.9.1` without reporting an unsupported platform/runtime. ## Step 4 — Install OpenClaw 2026.9.1 and verify the CLI Run the inspected installer with an exact version pin and skip onboarding for now: ```bash bash /tmp/openclaw-install.sh \ --version 2026.9.1 \ --no-onboard \ --verify ``` Start a new shell if the installer updates your PATH, then check: ```bash openclaw --version node --version ``` The installer is preferred over `sudo npm install -g openclaw@latest` because it handles supported Node/runtime checks and avoids common root-owned npm-prefix problems on Linux. Remove the temporary installer copy when finished: ```bash rm -f /tmp/openclaw-install.sh ``` **Verify:** `openclaw --version` should report `2026.9.1`, and `node --version` should report a runtime supported by current OpenClaw requirements. ## Step 5 — Run onboarding and install the managed Gateway service Start OpenClaw's guided setup: ```bash openclaw onboard --install-daemon ``` During onboarding: - choose the model provider you actually use; - authenticate with the provider or enter its API key when prompted; - keep the Gateway on its normal local/loopback configuration; - install the managed daemon/service; - skip optional channels/skills/plugins you do not need yet; - keep workspace/state under your user account. Do not paste provider secrets into screenshots, tickets, shell commands, Git repositories, or public documentation. Use the OpenClaw prompt/configuration flow so credentials are stored in the application's supported state/auth stores. After onboarding: ```bash openclaw config validate openclaw doctor ``` **Verify:** Configuration validation should pass, `openclaw doctor` should not report an unresolved critical setup failure, and the managed Gateway service should be installed. ## Step 6 — Verify the Gateway service, loopback bind, and default port Check Gateway state: ```bash openclaw gateway status ``` Inspect the configured bind and port: ```bash openclaw config get gateway.bind openclaw config get gateway.port ``` If the values are not explicitly authored, OpenClaw's current defaults are loopback and port `18789`. Check the live listener: ```bash sudo ss -lntp | grep ':18789' || true ``` The intended security posture is a loopback listener such as: ```text 127.0.0.1:18789 ``` not a public `0.0.0.0:18789` listener. Check the managed user unit: ```bash systemctl --user status openclaw-gateway.service --no-pager ``` OpenClaw's Linux service flow uses a systemd **user** unit. `openclaw doctor` also checks systemd lingering so the Gateway can remain alive after logout. **Verify:** The Gateway should be running, port 18789 should be loopback-only, and the managed user service should be active without a restart loop. ## Step 7 — Apply a messaging-only tool baseline and run the security audit For a Telegram-first assistant that does not need arbitrary host command execution, start from a narrow tool posture: ```bash openclaw config set tools.profile messaging openclaw config set tools.exec.security deny openclaw config set tools.exec.ask always openclaw config set tools.elevated.enabled false ``` Validate the resulting configuration: ```bash openclaw config validate ``` Restart if OpenClaw tells you the changed settings require it: ```bash openclaw gateway restart ``` Run the security checks: ```bash openclaw security audit openclaw security audit --deep ``` Upstream recommends these audits after configuration changes and before expanding network/channel exposure. The deep audit adds live Gateway probes and additional runtime checks. This restrictive tool profile is a safe starting point, not a requirement for every OpenClaw workflow. If you later enable shell, browser, file-write, elevated, or automation tools, do so deliberately and re-run the audit. **Verify:** `openclaw config validate` should pass, the security audit should have no unexplained critical findings, and dangerous execution/elevated capabilities should remain disabled unless explicitly required. ## Step 8 — Protect OpenClaw state and secret-bearing files OpenClaw's current security checks expect private state permissions. Tighten the main state directory and config file: ```bash chmod 700 ~/.openclaw ``` If the config exists: ```bash chmod 600 ~/.openclaw/openclaw.json ``` Inspect without printing credential contents: ```bash stat -c '%a %n' ~/.openclaw stat -c '%a %n' ~/.openclaw/openclaw.json 2>/dev/null || true ``` OpenClaw state can include model auth profiles, channel credentials, pairing allowlists, session metadata/transcripts, and configuration. Do not sync `~/.openclaw` through a broad shared Dropbox/Drive/iCloud folder or copy it into public Git repositories. Run the built-in secret scan: ```bash openclaw secrets audit --check ``` **Verify:** `~/.openclaw` should be owner-only, the config should not be group/world-readable, and the secrets audit should not show an unexplained plaintext or unresolved-secret problem. ## Step 9 — Create a Telegram bot and store its token without printing it In Telegram, verify that the account is exactly: ```text @BotFather ``` Create a bot with: ```text /newbot ``` Save the token privately. OpenClaw's Telegram integration supports a config token, token file, or `TELEGRAM_BOT_TOKEN` environment fallback for the default account. This tutorial uses the environment fallback so the bot token is not copied into `openclaw.json`. Create/update OpenClaw's private environment file: ```bash mkdir -p ~/.openclaw touch ~/.openclaw/.env chmod 600 ~/.openclaw/.env sed -i '/^TELEGRAM_BOT_TOKEN=/d' ~/.openclaw/.env read -s -p "Telegram bot token: " TELEGRAM_BOT_TOKEN echo printf 'TELEGRAM_BOT_TOKEN=%s\n' "$TELEGRAM_BOT_TOKEN" >> ~/.openclaw/.env unset TELEGRAM_BOT_TOKEN ``` Register the Telegram channel using the environment value: ```bash openclaw channels add --channel telegram --use-env ``` Validate and restart if requested: ```bash openclaw config validate openclaw gateway restart ``` **Verify:** Telegram should appear as a configured channel, the token should not be visible in `openclaw config get` output, and `~/.openclaw/.env` should have mode `600`. ## Step 10 — Pair your Telegram DM with the Gateway Open the actual bot you created and send it a direct message such as: ```text /start ``` OpenClaw's default Telegram DM policy is **pairing**. Unknown senders receive a one-time pairing code; current upstream documentation says the code expires after one hour. On the VM, list pending Telegram pairings: ```bash openclaw pairing list telegram ``` Approve only the code associated with your own Telegram account: ```bash openclaw pairing approve telegram PAIRING_CODE ``` Do not change the DM policy to a globally open mode just to avoid pairing. If multiple people will message the bot, use explicit allowlists/pairing and treat each approved sender as delegated authority over whatever tools the agent is allowed to use. **Verify:** Your Telegram account should be approved, an unknown unapproved sender should not gain normal bot access, and `openclaw doctor` should not report an intentionally open DM policy. ## Step 11 — Send an end-to-end Telegram test message Run a final health check before messaging: ```bash openclaw gateway status openclaw doctor openclaw security audit ``` Then send the bot: ```text Reply with exactly: OpenClaw is running on Ubuntu 24.04. ``` The response proves the complete path: ```text Telegram -> OpenClaw channel -> Gateway -> model provider -> Gateway -> Telegram ``` ![OpenClaw AI agent responding through Telegram on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/openclaw_telegram_agent_response_ubuntu_24_04_webp_8de8d70bdd.png) The old screenshot may show an earlier OpenClaw UI/message format; use the successful Telegram round trip, current CLI status, and current logs as the authority for this revision. :::cta Deploy Your AI Agent VM Launch a Raff Ubuntu VM and run OpenClaw with a loopback-only Gateway, private credentials, and Telegram pairing. ::: **Verify:** The approved Telegram account should receive a valid model response, the Gateway should remain healthy, and no public port should have been required for Telegram long polling. ## Step 12 — Access the Control UI remotely through an SSH tunnel Do not expose the Control UI directly to the public internet. From your **local workstation**, open an SSH tunnel to the VM: ```bash ssh -N -L 18789:127.0.0.1:18789 your_user@your_server_ip ``` Keep that terminal running. On the VM, generate a short-lived browser handoff without trying to launch a GUI browser on the server: ```bash openclaw dashboard --no-open ``` If you need the current structured browser handoff data: ```bash openclaw dashboard --json ``` Then use the tunnel from your local browser. The base local endpoint is: ```text http://127.0.0.1:18789/ ``` Current OpenClaw dashboard guidance recommends localhost, Tailscale Serve, or an SSH tunnel. The `openclaw dashboard` command issues a short-lived one-time browser pairing/bootstrap rather than printing the shared Gateway secret in normal interactive output. **Verify:** The Control UI should load through the SSH tunnel while `sudo ss -lntp | grep 18789` still shows the Gateway only on loopback. ## Step 13 — Back up OpenClaw state before upgrades or major configuration changes Current OpenClaw includes a first-party backup command. Create a protected backup directory outside the live `~/.openclaw` tree: ```bash mkdir -p ~/Backups/openclaw chmod 700 ~/Backups/openclaw ``` Create and immediately verify a full archive: ```bash openclaw backup create \ --output ~/Backups/openclaw \ --verify ``` List the resulting archives: ```bash ls -lh ~/Backups/openclaw ``` You can separately verify an archive later: ```bash openclaw backup verify ~/Backups/openclaw/YOUR_BACKUP_FILE.tar.gz ``` The full backup can contain state, configuration, model/channel credentials, sessions, and workspaces. Treat it like a credential-bearing secret archive: restrict permissions, encrypt/protect remote copies, and do not upload it to a public repository. Raff [Data Protection](/products/data-protection) can add infrastructure-level recovery; the OpenClaw application backup remains valuable before application updates and migrations. **Verify:** `openclaw backup create --verify` should complete successfully and produce a protected archive outside the active OpenClaw state directory. ## Step 14 — Update, troubleshoot, audit, and remove OpenClaw safely Preview future updates first: ```bash openclaw update --dry-run openclaw update status --json ``` Before a significant update, create a verified backup. Then update through OpenClaw's supported updater: ```bash openclaw update ``` The updater detects the installation type, updates the package/channel, runs health checks, and restarts the managed Gateway when appropriate. After every update: ```bash openclaw --version openclaw config validate openclaw gateway status openclaw doctor openclaw security audit --deep ``` If Telegram stops responding: ```bash openclaw pairing list telegram openclaw logs --follow ``` If the Gateway is unreachable locally: ```bash openclaw gateway status --deep sudo ss -lntp | grep ':18789' || true ``` If configuration changes fail: ```bash openclaw config validate openclaw doctor --json ``` If you suspect secret leakage: ```bash openclaw secrets audit --check ``` Rotate any exposed provider key or Telegram token at its source; deleting shell history does not revoke a credential that has already been copied elsewhere. For removal, create a final backup first, then preview the uninstall: ```bash openclaw backup create --output ~/Backups/openclaw --verify openclaw uninstall --dry-run ``` To remove service, state, and workspace interactively: ```bash openclaw uninstall --all ``` The OpenClaw CLI itself is removed separately according to its installation method; for an npm-based install, use the supported uninstall guidance rather than deleting random files from `~/.openclaw` while the Gateway is still running. Final audit: ```bash openclaw gateway status openclaw security audit --deep sudo ss -lntp | grep -E ':(22|18789)\b' || true ``` Expected architecture: ```text Telegram | | outbound long polling / Bot API v OpenClaw Gateway 127.0.0.1:18789 | +--> model provider +--> approved messaging tools Admin browser | | SSH tunnel v 127.0.0.1:18789 ``` **Verify:** The Telegram bot should answer only approved users according to policy, the Gateway should remain loopback-only, the security audit should have no unexplained critical findings, and a verified backup should exist before any major update or removal. ## Conclusion You now have OpenClaw installed on Ubuntu 24.04 with its official installer, a managed Gateway service, a supported Node runtime, Telegram pairing, a messaging-first tool posture, private state permissions, remote Control UI access through an SSH tunnel, and a first-party verified backup workflow. The key security boundary is the Gateway. Telegram long polling does not require you to publish port 18789, and the Control UI should stay on localhost unless you deliberately adopt a secure remote-access design such as Tailscale Serve or a tightly controlled authenticated proxy. Every new skill, plugin, channel, browser capability, shell tool, or approved sender expands what the agent can do, so re-run `openclaw security audit --deep` whenever that authority changes. For adjacent procedures, continue with [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), or [Build a Remote Development VM](/learn/tutorials/build-remote-development-vm-code-server-tailscale). ## Sources - [OpenClaw — Getting Started](https://docs.openclaw.ai/start/getting-started) - [OpenClaw — Install](https://docs.openclaw.ai/install) - [OpenClaw — Installer internals](https://docs.openclaw.ai/install/installer) - [OpenClaw — Node.js requirements](https://docs.openclaw.ai/install/node) - [OpenClaw — Telegram](https://docs.openclaw.ai/telegram) - [OpenClaw — Gateway security](https://docs.openclaw.ai/gateway/security) - [OpenClaw — Gateway remote access](https://docs.openclaw.ai/gateway/remote) - [OpenClaw — Dashboard](https://docs.openclaw.ai/cli/dashboard) - [OpenClaw — Backup](https://docs.openclaw.ai/cli/backup) - [OpenClaw — Updating](https://docs.openclaw.ai/install/updating) - [OpenClaw npm package](https://www.npmjs.com/package/openclaw) - Guidance and current release re-verified: 2026-09-05 --- ### How to Install Coolify on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-coolify-ubuntu-24-04 Description: Install Coolify on Ubuntu 24.04 with the official installer, secure direct-access ports, configure HTTPS domains, deploy an app, and plan backups and updates. Coolify is a self-hosted deployment platform for running applications, databases, and services on infrastructure you control. On Ubuntu 24.04, the supported quick-install path is the official Coolify installer, which prepares Docker, creates the Coolify control-plane files under `/data/coolify`, configures server-management SSH keys, and starts the platform. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 4 GB RAM Linux VM; installer, networking, backup, and update guidance reviewed against Coolify documentation in July 2026`. This revision re-verifies the workflow against current Coolify documentation on September 5, 2026 without claiming a new end-to-end machine test. The current documented minimum is 2 CPU cores, 2 GB RAM, and 30 GB of free storage. Treat that as an installation floor, not a production sizing guarantee. Builds, databases, image layers, application memory, persistent volumes, and deployment overlap can require substantially more resources. Coolify also needs several direct-access ports during initial setup; once a custom dashboard domain is working through Coolify's proxy, the direct dashboard/realtime/terminal ports can be closed according to the official firewall guidance. Prerequisites: - A fresh Ubuntu 24.04 LTS VM with at least 2 CPU cores, 2 GB RAM, and 30 GB free storage - SSH access and a tested recovery path - A domain or subdomain you control - Public TCP 80 and 443 available for Coolify's proxy - DNS access for the dashboard and application hostnames ## Step 1 — Verify Ubuntu, resources, storage, and existing listeners Confirm the operating system: ```bash cat /etc/os-release uname -m ``` Coolify's automatic installer supports Ubuntu LTS releases including 24.04 and 64-bit AMD64/ARM64 systems. Check CPU, memory, and free disk space: ```bash nproc free -h df -h / ``` Check filesystem usage under `/data` if it already exists: ```bash df -h /data 2>/dev/null || true ``` Inspect listeners before installing Coolify: ```bash sudo ss -tulpn ``` Pay particular attention to ports 80, 443, 8000, 6001, and 6002. Existing reverse proxies, web servers, Docker stacks, or manually managed applications can conflict with Coolify. Use a fresh server where practical. Coolify's own documentation recommends this to reduce conflicts with existing services and networking rules. **Verify:** Ubuntu should report 24.04 LTS on a supported 64-bit architecture, the server should meet the minimum resource floor, and you should know whether any process already occupies Coolify-related ports. ## Step 2 — Confirm SSH access and update Ubuntu safely Coolify manages its local and remote servers through SSH, so server access is part of the platform's control plane. Open a second SSH session before making firewall changes: ```bash ssh your_user@your_server_ip ``` Update package metadata and review upgrades: ```bash sudo apt update apt list --upgradable 2>/dev/null ``` Apply updates according to your maintenance policy: ```bash sudo apt upgrade ``` Check whether Ubuntu requests a reboot: ```bash if [ -f /var/run/reboot-required ]; then cat /var/run/reboot-required else echo "No reboot required" fi ``` Current Coolify quick-install documentation recommends running installation as root; it also documents `sudo` for users who are not logged in as root. Do not assume every non-root setup is fully supported simply because `sudo` can launch the installer. For general SSH hardening, see [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). **Verify:** A second SSH connection should work, `sudo` should be functional if you are not root, updates should complete without repository errors, and any required reboot should be handled before installation. ## Step 3 — Review Coolify's required ports before enabling or changing a firewall For a self-hosted Coolify server, current official firewall documentation lists these inbound ports when using direct IP access: ```text 22/tcp SSH, or your custom SSH port 80/tcp HTTP and certificate generation through the proxy 443/tcp HTTPS through the proxy 8000/tcp Direct Coolify dashboard access 6001/tcp Realtime dashboard communication for direct IP access 6002/tcp Coolify web terminal for direct IP access ``` Check them locally: ```bash sudo ss -lntp | grep -E ':(22|80|443|8000|6001|6002)\b' || true ``` If UFW is already active, confirm the real SSH port is allowed **before** adding Coolify rules. For initial setup, a straightforward rule set is: ```bash sudo ufw allow 80/tcp comment 'Coolify HTTP' sudo ufw allow 443/tcp comment 'Coolify HTTPS' sudo ufw allow 8000/tcp comment 'Coolify initial dashboard' sudo ufw allow 6001/tcp comment 'Coolify realtime direct access' sudo ufw allow 6002/tcp comment 'Coolify web terminal direct access' ``` Do not blindly enable UFW over SSH if it is currently inactive. Use the lockout-safe flow in [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). Docker creates its own firewall/NAT rules. Treat Docker-published application ports separately from ordinary UFW host rules; do not assume UFW alone will block every Docker-published port. **Verify:** The active SSH path must remain reachable, ports required for initial Coolify setup should be intentionally available, and no unrelated process should be unexpectedly bound to those ports. ## Step 4 — Run the official Coolify stable installer Install `curl` if needed: ```bash sudo apt update sudo apt install -y curl ``` Run the official stable installer documented by Coolify: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash ``` If you are already root, the documented command can run without `sudo`: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` The installer: - installs required command-line tools; - installs Docker Engine when needed; - configures Docker for Coolify; - creates files under `/data/coolify`; - creates SSH keys used by Coolify for server management; - starts the Coolify control plane. Docker installed through Snap is not supported. If the installer detects Snap Docker, remove that package and follow the supported Docker path before retrying. For production, use the normal stable installer/CDN path rather than forcing a GitHub release simply because it is newer. Coolify intentionally may delay CDN availability after a GitHub release for additional testing. **Verify:** The installer should complete without an unsupported-OS/Docker error and should print the initial Coolify URL, normally using TCP 8000. ## Step 5 — Verify the Coolify containers and initial dashboard listener Inspect the running containers: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' ``` Check port 8000: ```bash sudo ss -lntp | grep ':8000' || true ``` If installation failed or the dashboard does not load, inspect all containers: ```bash sudo docker ps -a ``` Then inspect relevant logs using the actual container names returned by Docker, for example: ```bash sudo docker logs --tail=200 coolify 2>/dev/null || true ``` Coolify's troubleshooting documentation notes that an occupied TCP 8000 can cause installation problems, so re-check that port if the initial web UI is unavailable. **Verify:** Coolify control-plane containers should remain running rather than restart-looping, and the initial dashboard should answer at the URL printed by the installer. ## Step 6 — Create the first administrator account immediately Open the initial registration page: ```text http://your_server_ip:8000 ``` Create the first administrator account immediately. Coolify's installation documentation explicitly warns that if another person reaches the registration page before you, they may create the first account and gain control of the server. Use: - a unique administrator email; - a long password stored in a password manager; - an administrator identity that is not shared between multiple people; - a documented recovery path outside the VM. Sign out and back in before changing network access so you know the administrator credentials work. :::cta Deploy Your Coolify Server Launch an Ubuntu 24.04 VM and build a self-hosted Coolify deployment with your own applications, domains, and recovery plan. ::: **Verify:** The first admin account should exist, login should succeed in a fresh browser session, and the public registration flow should no longer offer unrestricted first-user creation. ## Step 7 — Configure a custom dashboard domain and HTTPS Create a DNS record such as: ```text coolify.example.com -> your_server_ip ``` Use an `A` record for IPv4. Add an `AAAA` record only when IPv6 really reaches this VM and is protected consistently. Check DNS from another network when possible: ```bash dig +short A coolify.example.com dig +short AAAA coolify.example.com ``` In Coolify's instance settings, configure the dashboard URL: ```text https://coolify.example.com ``` Coolify's integrated proxy then handles routing and TLS for the hostname. Verify HTTPS externally: ```bash curl -I https://coolify.example.com ``` Do not close the direct setup ports until the custom hostname is proven from a separate browser/network path and you retain SSH/recovery access. **Verify:** The dashboard should load over the custom HTTPS hostname with a trusted certificate, and administrator login should work through that hostname. ## Step 8 — Close direct dashboard, realtime, and terminal ports after the custom domain works Current Coolify firewall guidance states that when you use a custom domain through the integrated proxy, you can safely close direct-access ports **8000, 6001, and 6002**. Remove the broad UFW rules you added for initial setup: ```bash sudo ufw delete allow 8000/tcp sudo ufw delete allow 6001/tcp sudo ufw delete allow 6002/tcp ``` Review the final rules: ```bash sudo ufw status numbered ``` Keep: - the real SSH administration path; - 80/tcp when required for HTTP/certificate handling; - 443/tcp for HTTPS applications and the Coolify dashboard. If you deliberately need direct IP dashboard or web-terminal access, restrict the relevant port to a trusted source instead of leaving it open to `Anywhere`. Remember that Docker can publish application ports outside ordinary UFW expectations. Audit deployed application bindings with: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' ``` **Verify:** The custom HTTPS dashboard should continue working after 8000/6001/6002 are closed, SSH should remain available, and no application should expose an unintended host port. ## Step 9 — Create a project and deploy an application through the proxy In Coolify: 1. Create a **Project**. 2. Create or select an **Environment**. 3. Add an **Application**. 4. Choose a public repository, connected Git provider, Docker image, or another supported source. 5. Set the branch/build method. 6. Add required environment variables through Coolify. 7. Configure the application's internal listening port. For private repositories, grant the minimum repository access required by the integration. Remove stale source integrations when repositories or team ownership changes. Do not commit production secrets into Git merely because Coolify can deploy from the repository. Application credentials belong in protected environment/secret configuration and should have an owner and rotation process. **Verify:** Coolify should detect/build the source successfully, required variables should be configured outside the repository, and the deployed container should reach a healthy/running state. ## Step 10 — Attach an application domain and verify the deployment end to end Create another DNS record: ```text app.example.com -> your_server_ip ``` Configure that domain on the application in Coolify and route it through the platform proxy. Prefer domain-based proxy routing over manually publishing random host ports. Direct host-port publication increases attack surface and can bypass assumptions in your host firewall design. Test from outside the server: ```bash curl -I https://app.example.com ``` Inspect containers and host utilization: ```bash sudo docker ps sudo docker stats --no-stream free -h df -h / ``` There is no reliable fixed number of apps a Coolify VM can host. Capacity depends on application memory, build load, databases, background workers, traffic, image/cache growth, and the overlap between deployments. **Verify:** The application should respond through its HTTPS domain, there should be no unintended public database/admin ports, and CPU/memory/disk should retain enough headroom for future deployments. ## Step 11 — Configure Coolify instance backups and save the APP_KEY separately A Coolify **instance backup** protects Coolify's own database: projects, resources, settings, credentials metadata, and deployment history. It does **not** back up data inside your applications, databases, or persistent volumes. Open **Settings → Backup** in Coolify. Configure the instance backup if it is not already enabled, then trigger **Backup Now**. Current documentation supports local backup storage and S3-compatible copies. Do not leave the only usable backup on the same VM. Coolify encrypts stored secrets using `APP_KEY`, which is not part of the database backup. Save it separately: ```bash sudo grep '^APP_KEY=' /data/coolify/source/.env ``` Store the complete value in a password manager or another protected location outside the VM. Do not paste it into tickets, chat, screenshots, or public documentation. Also preserve the Coolify management keys on replacement-server migrations: ```bash sudo find /data/coolify/ssh/keys -maxdepth 1 -type f -ls ``` Raff [Object Storage](/products/object-storage) can be used as an off-server destination where Coolify's S3-compatible backup configuration is suitable. **Verify:** The instance backup execution should report success, at least one copy should exist outside the Coolify VM, and the `APP_KEY` should be stored securely and separately from the backup file. ## Step 12 — Back up application databases and persistent data separately Coolify instance backups do not contain your workload data. For supported database resources, current Coolify backup tooling can schedule engine-aware backups for PostgreSQL, MySQL, MariaDB, MongoDB, and ClickHouse and optionally copy them to S3-compatible storage. Create a separate plan for every stateful resource: - relational/document databases: scheduled database-aware backups; - uploaded files: filesystem/volume backups; - object storage: provider-specific backup/replication policy; - Redis/Dragonfly/KeyDB: their own persistence/backup method rather than assuming Coolify's scheduled database-backup workflow supports them; - external SaaS/managed databases: the external provider's recovery procedure. A successful backup file is not a restore test. Periodically restore a copy into a disposable environment and verify the application can read it. Raff [Data Protection](/products/data-protection) can add VM-level recovery, but do not rely on a VM recovery point as the only consistency mechanism for active databases. **Verify:** Every stateful workload should have a documented backup owner, schedule, off-server copy, retention policy, and at least one tested restore path. ## Step 13 — Update Coolify through the stable channel with a recovery point first Before updating Coolify: 1. Create a successful Coolify instance backup. 2. Confirm the separate `APP_KEY` copy is accessible. 3. Back up stateful application data. 4. Check free storage for replacement images and build cache. 5. Read the release notes/changelog for the target stable update. Coolify can update from the dashboard. The documented stable installer can also be re-run to update to the version currently made available through Coolify's CDN: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash ``` Do not assume the newest GitHub release is immediately the recommended CDN release. Coolify's release documentation states that CDN promotion may be delayed for testing and hotfixes. After an update, verify the control plane and workloads: ```bash sudo docker ps sudo docker stats --no-stream curl -I https://coolify.example.com curl -I https://app.example.com ``` Review a representative deployment path before declaring the upgrade complete. **Verify:** The dashboard should load, administrator login should work, proxy/TLS should function, existing applications should remain healthy, and at least one test deployment should complete successfully. ## Step 14 — Run the final security, capacity, and recovery audit Audit listening ports: ```bash sudo ss -tulpn ``` Audit Docker publications: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' ``` Audit UFW if you use it: ```bash sudo ufw status numbered ``` Audit resource headroom: ```bash free -h df -h / sudo docker system df ``` Confirm: - the custom Coolify dashboard uses HTTPS; - 8000/6001/6002 are not broadly public unless intentionally required; - SSH access remains restricted and recoverable; - public application traffic uses expected proxy routes; - databases/admin interfaces are not exposed without an explicit design; - Coolify's instance backup exists outside the VM; - the matching `APP_KEY` is stored safely; - application databases and volumes have separate backups; - at least one restore has been tested; - sufficient CPU, RAM, and disk headroom remains for builds and updates. A single Coolify server is still a single failure domain for its control plane and any workloads placed on it. Adding remote deployment servers can distribute workloads, but each stateful component still needs its own availability and recovery design. **Verify:** There should be no unexplained listener, public Docker port, missing off-server backup, lost encryption key, or capacity condition that would make the next deployment/update unsafe. ## Troubleshooting ### The installer finishes but port 8000 does not respond Check whether another service occupied the port or Coolify is restart-looping: ```bash sudo ss -tulpn | grep ':8000' || true sudo docker ps -a ``` Then inspect the actual Coolify container logs: ```bash sudo docker logs --tail=200 coolify 2>/dev/null || true ``` ### The custom dashboard domain returns a certificate or proxy error Check DNS and public ports: ```bash dig +short A coolify.example.com dig +short AAAA coolify.example.com sudo ss -lntp | grep -E ':(80|443)\b' || true sudo ufw status numbered ``` An incorrect `AAAA` record can break IPv6 clients even when IPv4 works. ### The dashboard works on 8000 but realtime updates or the web terminal fail When using **direct IP access**, current Coolify firewall guidance also requires 6001 for realtime communication and 6002 for web-terminal access. If you have already moved the dashboard behind a custom domain/proxy, use that architecture and close the direct ports instead of leaving all three public indefinitely. ### UFW says a Docker application port is blocked but it is still reachable Docker's own NAT/firewall rules can bypass ordinary UFW host `INPUT` assumptions. Check Docker publications: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' ``` Prefer routing public web applications through Coolify's proxy and avoid unnecessary direct host-port publishing. ### A Coolify instance backup succeeds but restore cannot decrypt credentials The database backup is not enough by itself. You need the matching `APP_KEY` from `/data/coolify/source/.env`. Without it, encrypted stored credentials cannot be recovered correctly. ### The new Coolify version is on GitHub but the dashboard does not offer it That can be expected. Coolify's release process intentionally separates GitHub release publication from CDN promotion. Wait for the stable CDN channel unless you have a tested reason to force a specific version. ## Conclusion You now have a current Coolify deployment workflow for Ubuntu 24.04: supported resource checks, the official installer, immediate administrator registration, correct direct-access firewall ports, a custom HTTPS dashboard domain, reduced exposure after proxy setup, an application deployment path, separate instance/workload backups, and a controlled stable-channel update process. The most important operational distinction is between the **Coolify control plane** and the **workloads Coolify manages**. Backing up Coolify does not back up application databases or volumes, and securing port 8000 does not automatically secure Docker-published application ports. Treat the control plane, Docker networking, every stateful service, and recovery credentials as separate layers that must all be verified. For adjacent procedures, use [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Coolify — Installation](https://coolify.io/docs/get-started/installation) - [Coolify — Firewall](https://coolify.io/docs/knowledge-base/server/firewall) - [Coolify — Backup and Restore](https://coolify.io/docs/knowledge-base/how-to/backup-restore-coolify) - [Coolify — Instance Backup](https://next.coolify.io/docs/core/backup-and-recovery/instance-backup) - [Coolify — Instance Restore](https://next.coolify.io/docs/core/backup-and-recovery/instance-restore) - [Coolify — Database Backups](https://next.coolify.io/docs/databases/backups) - [Coolify — Release Guide](https://github.com/coollabsio/coolify/blob/v4.x/RELEASE.md) - Guidance re-verified: 2026-09-05 --- ### How to Install Ghost CMS on Ubuntu 24.04 with Nginx URL: https://rafftechnologies.com/learn/tutorials/deploy-ghost-cms-ubuntu-24-04-nginx Description: Install Ghost CMS on Ubuntu 24.04 with Nginx, Node.js 22, MySQL 8, Ghost-CLI, HTTPS, backups, rollback, and current Ghost 6 deployment guidance. Ghost is a publishing platform for websites, newsletters, memberships, subscriptions, and social-web publishing. For a conventional production VPS deployment, Ghost's current official guide supports Ubuntu 24.04 with Nginx, Node.js 22 LTS, MySQL 8.0 or 8.4, systemd, and Ghost-CLI. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 2 GB RAM Linux VM; Ghost 6 stack requirements, Node.js 22, MySQL 8, Ghost-CLI, Nginx, and backup guidance reviewed in July 2026`. This revision re-verifies the workflow against current Ghost documentation on September 5, 2026. Ghost **6.61.0** is the latest upstream release observed at verification time; the commands below intentionally install the current supported Ghost 6 release through Ghost-CLI rather than claiming a fresh 6.61.0 machine retest. One important Ghost 6 deployment boundary has changed since older tutorials were written. Ghost-CLI remains an officially documented production install path for Ghost 6.x, but CLI installs do not self-host Ghost's native web analytics service. Social Web support uses Ghost's hosted ActivityPub service in this model. Ghost is moving toward an official Docker Compose deployment for the additional Ghost 6 services, and the Ghost platform team has announced that Ghost-CLI will be deprecated with Ghost 7. If you specifically need fully self-hosted analytics or ActivityPub, review the Docker Compose path instead of assuming this classic Nginx/MySQL/systemd layout includes those services. Prerequisites: - An Ubuntu 24.04 server with at least 1 GB RAM; 2 GB or more gives more operational headroom - A registered domain with DNS pointed to the server - SSH access and a non-root sudo user that is not named `ghost` - Public TCP 80 and 443 available for Nginx and Let's Encrypt - A protected place for database, mail, and recovery credentials ## Step 1 — Verify Ubuntu, DNS, resources, and existing listeners Confirm the OS and architecture: ```bash cat /etc/os-release uname -m ``` Check memory and free storage: ```bash free -h df -h / ``` Check the publication hostname: ```bash dig +short A blog.example.com dig +short AAAA blog.example.com ``` Publish an `AAAA` record only when IPv6 actually reaches this VM and is protected consistently. Inspect current listeners: ```bash sudo ss -tulpn ``` Ghost's official Ubuntu install expects a registered domain. Do not plan to use a raw IP address as the final Ghost URL; the Ghost-CLI install flow can error when an IP address is used as the site URL. **Verify:** Ubuntu should report 24.04, the server should meet the memory/storage floor, DNS should resolve to this server, and ports 80/443 should not be unexpectedly occupied by another production proxy. ## Step 2 — Create or verify a non-root sudo administrator Ghost-CLI must not be run as root. Also do not name the Linux administrator `ghost`, because that conflicts with Ghost-CLI's service-management model. If you are starting as root, create an administrative account such as `ghost-mgr`: ```bash adduser ghost-mgr usermod -aG sudo ghost-mgr su - ghost-mgr ``` Verify sudo: ```bash sudo whoami ``` Expected output: ```text root ``` Open a second SSH session with this account before firewall changes: ```bash ssh ghost-mgr@your_server_ip ``` For broader host hardening, use [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). **Verify:** The non-root user should be able to log in independently, run sudo, and keep a second recovery-capable SSH session open. ## Step 3 — Update Ubuntu and prepare the firewall without risking SSH lockout Update package metadata and review upgrades: ```bash sudo apt update apt list --upgradable 2>/dev/null ``` Apply updates according to your maintenance policy: ```bash sudo apt upgrade ``` Install the base packages used by the stack: ```bash sudo apt install -y ca-certificates curl gnupg ``` If UFW is already active, confirm your actual SSH port is allowed, then allow web traffic: ```bash sudo ufw allow 'Nginx Full' sudo ufw status numbered ``` If UFW is currently inactive, do not blindly enable it over a remote session. Use the lockout-safe process in [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). Check whether Ubuntu requests a reboot: ```bash if [ -f /var/run/reboot-required ]; then cat /var/run/reboot-required else echo "No reboot required" fi ``` **Verify:** Package operations should complete without repository errors, SSH should remain reachable from the second session, and public TCP 80/443 should be permitted when the firewall is active. ## Step 4 — Install Nginx and MySQL 8 Install the officially recommended web/database stack from Ubuntu's repositories: ```bash sudo apt install -y nginx mysql-server ``` Enable and start both services: ```bash sudo systemctl enable --now nginx mysql ``` Check them: ```bash systemctl is-active nginx mysql nginx -v mysql --version ``` Current Ghost production documentation supports **MySQL 8.0 or 8.4**. Do not substitute MariaDB or SQLite in this documented production Ghost-CLI layout simply because the application may run in other unsupported configurations. Do not expose MySQL port 3306 publicly on this single-server setup. **Verify:** Nginx and MySQL should both be active, MySQL should be an 8.x release supported by current Ghost documentation, and port 3306 should not be intentionally opened to the internet. ## Step 5 — Configure MySQL root authentication for Ghost-CLI setup Ubuntu commonly installs the local MySQL root account with socket authentication. Ghost's official production setup needs a MySQL username/password during installation so Ghost-CLI can create the publication database and a restricted Ghost database user. Open MySQL locally: ```bash sudo mysql ``` Current Ghost documentation uses `caching_sha2_password` for this step: ```sql ALTER USER 'root'@'localhost' IDENTIFIED WITH 'caching_sha2_password' BY 'replace_with_a_long_unique_password'; FLUSH PRIVILEGES; EXIT; ``` Store the new password in a password manager, then test it: ```bash mysql -u root -p ``` Exit after authentication succeeds: ```sql EXIT; ``` Older Ghost tutorials often used `mysql_native_password`. Do not copy that older authentication method into a new Ubuntu 24.04/Ghost 6 deployment when the current Ghost guide explicitly documents `caching_sha2_password`. During `ghost install`, let Ghost-CLI create a dedicated restricted database user. The running publication should not operate as MySQL root. **Verify:** `mysql -u root -p` should authenticate with the new credential, and you should have the credential stored outside the terminal/session before continuing. ## Step 6 — Install the required Node.js 22 LTS runtime system-wide Ghost's current compatibility documentation requires **Node.js 22 LTS**. Node 20 is unsupported for current Ghost 6, and Node 23+ is also unsupported. Install Node.js through the system-wide NodeSource path documented by Ghost: ```bash sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=22 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" \ | sudo tee /etc/apt/sources.list.d/nodesource.list sudo apt-get update sudo apt-get install nodejs -y ``` Verify: ```bash node --version npm --version ``` For this Ghost-CLI production pattern, follow Ghost's documented system-wide Node installation instead of relying on a user-specific `nvm` runtime that may disappear from systemd's environment. **Verify:** `node --version` should report a supported Node 22.x release and should be available to the non-root Ghost administrator without sourcing an interactive version-manager shell. ## Step 7 — Install the current Ghost-CLI and verify its environment checks Install Ghost-CLI globally: ```bash sudo npm install ghost-cli@latest -g ``` Verify the CLI: ```bash ghost --version ghost help ``` Run its diagnostic checks where useful: ```bash ghost doctor ``` Ghost-CLI remains the official tool used by Ghost's classic Ubuntu production installation for Ghost 6.x. However, Ghost's platform team announced in August 2026 that Ghost 6.x will be the last major line usable with Ghost-CLI; Ghost 7 is planned to move the supported deployment model to the official Docker image/Compose environment. That future deprecation does not make this Ghost 6.x installation invalid today, but it should influence long-term migration planning. **Verify:** Ghost-CLI should run as the non-root administrator and should not report an unresolved Node/system compatibility error. ## Step 8 — Create the Ghost installation directory with correct ownership Create a dedicated directory: ```bash sudo mkdir -p /var/www/blog.example.com sudo chown ghost-mgr:ghost-mgr /var/www/blog.example.com sudo chmod 775 /var/www/blog.example.com cd /var/www/blog.example.com ``` Replace `ghost-mgr` and `blog.example.com` with your real account and hostname. Check ownership: ```bash pwd ls -ld . ``` Do not pre-create random `ghost` service users or manually chown internal Ghost paths before Ghost-CLI has performed its own Linux-user/service setup. **Verify:** The installation directory should be owned by the non-root administrator and should be the current working directory before you run `ghost install`. ## Step 9 — Install Ghost 6 through Ghost-CLI Run the production installer from the Ghost directory: ```bash ghost install ``` At the time this guide was re-verified, upstream's latest release was Ghost **6.61.0**. `ghost install` intentionally follows the current supported release instead of hard-coding that patch version into a long-lived install command. Use the interactive answers appropriate to your site: ```text Blog URL: https://blog.example.com MySQL hostname: localhost MySQL username: root MySQL password: the administrative password created earlier Ghost database name: ghost_prod Set up a Ghost MySQL user: Yes Set up NGINX: Yes Set up SSL: Yes Set up systemd: Yes Start Ghost: Yes ``` Ghost-CLI uses MySQL administrative access during setup, then can create a database account restricted to the Ghost database. If the setup is interrupted, use: ```bash ghost setup ``` If installation needs to be removed, prefer: ```bash ghost uninstall ``` over deleting directories manually, because the CLI can remove related artifacts cleanly. **Verify:** The install should complete without stack-check failures and should report a running Ghost instance using Nginx, SSL, systemd, and a restricted Ghost database user. ## Step 10 — Verify Ghost, systemd, Nginx, HTTP redirect, and HTTPS From the installation directory: ```bash cd /var/www/blog.example.com ghost status ghost doctor ghost version ``` Inspect the Ghost instances known to the CLI: ```bash ghost ls ``` Check Nginx: ```bash sudo nginx -t systemctl is-active nginx ``` Inspect Ghost's generated systemd unit(s): ```bash systemctl list-units 'ghost_*' --all ``` Test the public endpoints: ```bash curl -I http://blog.example.com curl -I https://blog.example.com ``` HTTP should redirect to HTTPS, and the HTTPS endpoint should return a valid Ghost response with a trusted certificate. **Verify:** `ghost status` should show the site running, `ghost doctor` should pass its critical checks, Nginx syntax should be valid, and the publication should load over HTTPS. ## Step 11 — Create the publication owner and understand the Ghost 6 service boundary Open: ```text https://blog.example.com/ghost ``` Create the publication owner account with a unique email address and strong password. Then configure the site title, design, staff, membership, and integrations. For newsletters, Ghost's native bulk email delivery is designed around Mailgun rather than ordinary SMTP. Treat newsletter provider configuration as a separate production dependency and keep its credentials out of screenshots/repos. For Ghost 6 specifically, understand what this **Ghost-CLI** deployment does and does not self-host: - The primary Ghost application runs on this VM. - Nginx, MySQL, Node.js, and systemd run on this VM. - Social Web features can use Ghost's hosted ActivityPub service. - Native web analytics is **not** self-hosted by this Ghost-CLI install. - Fully self-hosting the newer analytics/ActivityPub service set requires Ghost's Docker Compose deployment, which is still described as a developer-preview path for Ghost 6 and is planned to become the default with Ghost 7. **Verify:** The owner should be able to sign in, core publishing should work, and your team should understand whether the classic CLI architecture satisfies the specific Ghost 6 features you need. ## Step 12 — Protect Ghost configuration and inspect runtime state without exposing secrets Ghost's production config lives at: ```text /var/www/blog.example.com/config.production.json ``` Inspect metadata without printing its contents: ```bash stat -c '%a %U:%G %n' /var/www/blog.example.com/config.production.json ``` This file can contain database, mail, storage, and other sensitive configuration. Do not paste it into tickets, public repositories, or chat. Use Ghost-CLI for routine runtime inspection: ```bash ghost status ghost log ghost doctor ``` If Ghost fails under systemd and ordinary logs are insufficient, Ghost-CLI documents `ghost run` as a direct foreground debugging method: ```bash ghost run ``` Stop that foreground process after diagnosis and return to the managed service. **Verify:** `config.production.json` should not be broadly readable, normal administration should work through Ghost-CLI, and no secret-bearing configuration should have been copied into public logs or documentation. ## Step 13 — Create and verify an off-server Ghost backup From the Ghost installation directory: ```bash cd /var/www/blog.example.com ghost backup ``` Current Ghost-CLI documentation says this creates a zip backup containing: - content in JSON format; - a full members CSV export; - installed themes, including the active theme; - images, files, video, and audio media; - `routes.yaml`; - `redirects.yaml` or `redirects.json`. List the generated archive and inspect it without extracting over the live site: ```bash find . -maxdepth 2 -type f -name '*.zip' -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort -r | head unzip -l /path/to/ghost-backup.zip | head -n 40 ``` Move or copy a protected backup **off the VM**. Do not keep the only recovery copy on the same filesystem as the publication. Also preserve infrastructure recovery information separately: DNS ownership, mail provider access, SSH/recovery keys, and any secret-bearing server config required to rebuild the exact environment. The Ghost backup is a publication-data backup, not a substitute for every server credential and infrastructure setting. Raff [Data Protection](/products/data-protection) can provide a separate VM-level recovery layer, and Raff [Object Storage](/products/object-storage) can serve as an off-server location when your backup transfer tooling supports S3-compatible storage. **Verify:** A current Ghost backup archive should exist, its contents should be readable, and at least one protected copy should exist outside the live VM. ## Step 14 — Update Ghost and Node.js in the correct order with rollback available Check available Ghost updates: ```bash cd /var/www/blog.example.com ghost check-update ``` Create a backup before changing the application: ```bash ghost backup ``` For normal updates within Ghost 6.x: ```bash ghost update ``` Ghost-CLI supports rollback when an update goes wrong: ```bash ghost update --rollback ``` Do not update Node.js and Ghost in one uncontrolled step. Ghost's current Node documentation says to update Node first, then reinstall the **current Ghost version's dependencies** before attempting a Ghost version upgrade, because Ghost has binary dependencies compiled for the active Node version. When a supported Node change is required: ```bash ghost version ``` Update Node through the documented NodeSource repo, then reinstall the same Ghost version to rebuild dependencies: ```bash ghost update YOUR_CURRENT_GHOST_VERSION --force ``` Only after the current Ghost version is healthy on the new supported Node runtime should you perform the intended Ghost update. After any update: ```bash ghost doctor ghost status ghost version sudo nginx -t curl -I https://blog.example.com ``` **Verify:** The site should remain healthy on a supported Node version, the active Ghost version should be known, HTTPS should work, and a pre-update backup/rollback path should exist. ## Step 15 — Run the final security, maintenance, and migration-readiness audit Check Ghost and the host: ```bash cd /var/www/blog.example.com ghost status ghost doctor ghost ls systemctl --failed df -h / sudo ss -tulpn ``` Check the public site and Admin: ```bash curl -I https://blog.example.com curl -I https://blog.example.com/ghost/ ``` Confirm: - Ghost runs as a managed systemd service rather than an ad-hoc terminal process; - Node.js is still a supported 22.x runtime for the current Ghost 6 line; - MySQL is 8.0/8.4 and is not publicly exposed; - Nginx and TLS are healthy; - the owner/staff list contains only expected users; - `config.production.json` is treated as secret-bearing configuration; - a recent Ghost backup exists off-server; - mail/provider credentials have owners and rotation paths; - disk growth from images, media, logs, backups, and MySQL is monitored; - your team has explicitly chosen classic Ghost-CLI vs the newer Docker Compose architecture based on the Ghost 6 features you need; - migration planning acknowledges that Ghost-CLI is scheduled for deprecation with Ghost 7. Do not assume a classic single-instance Ghost-CLI VPS deployment automatically becomes a multi-node/high-availability design. Ghost's documented classic architecture is a single Ghost application with its supporting services; availability and recovery require a separate architecture decision. **Verify:** There should be no unsupported runtime, public MySQL listener, broken HTTPS path, missing off-server backup, unexplained failed service, or unplanned Ghost 7 migration dependency. ## Troubleshooting ### `ERROR: Unsupported version of Node` or exit status 231 Ghost requires Node.js 22 LTS for the current Ghost 6 production stack. Check: ```bash node --version ``` If necessary, replace the unsupported runtime with Node 22 through the documented NodeSource repository, then reinstall the current Ghost version's dependencies with `ghost update CURRENT_VERSION --force`. ### Ghost-CLI cannot authenticate to MySQL root Check whether the root account still uses socket-only auth: ```bash sudo mysql ``` For the current official Ghost Ubuntu setup, configure a password-backed `caching_sha2_password` root login for the setup step, test `mysql -u root -p`, then rerun `ghost setup` or `ghost install` as appropriate. ### SSL setup fails Verify DNS and public access: ```bash dig +short A blog.example.com dig +short AAAA blog.example.com sudo ss -lntp | grep -E ':(80|443)\b' || true sudo ufw status numbered ``` Then run from the Ghost install directory: ```bash ghost setup ssl ``` ### Ghost fails after a Node.js upgrade Ghost documents that Node upgrades require Ghost's binary dependencies to be reinstalled. Get the current Ghost version and force-reinstall that same version: ```bash ghost version ghost update YOUR_CURRENT_GHOST_VERSION --force ``` ### A Ghost update fails Run diagnostics/logs: ```bash ghost doctor ghost log ghost run ``` If the update changed the installed version and rollback is appropriate: ```bash ghost update --rollback ``` ### Native Ghost 6 web analytics is missing on the CLI install That is an architecture limitation, not necessarily a broken install. Current Ghost documentation says Ghost-CLI deployments do not support the self-hosted web analytics service. Review Ghost's newer Docker Compose deployment if that feature is a requirement. ## Conclusion You now have Ghost CMS running on Ubuntu 24.04 with the current supported classic production stack: Nginx, Node.js 22 LTS, MySQL 8.0/8.4, systemd, Ghost-CLI, HTTPS, application-level backups, and a controlled update/rollback workflow. The most important 2026 distinction is architectural. Ghost-CLI remains valid for Ghost 6.x, but it is no longer the long-term deployment direction for the project. The newer Ghost 6 services such as fully self-hosted web analytics require the Docker Compose architecture, and the Ghost platform team plans to deprecate Ghost-CLI with Ghost 7. Build new deployments with that migration boundary in mind rather than treating today's CLI stack as permanent. For adjacent procedures, use [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Secure Nginx with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04). ## Sources - [Ghost — How to Install Ghost on Ubuntu](https://docs.ghost.org/install/ubuntu) - [Ghost — Supported Node Versions](https://docs.ghost.org/faq/node-versions) - [Ghost — Ghost CLI](https://docs.ghost.org/ghost-cli) - [Ghost — How to Update Ghost](https://docs.ghost.org/update) - [Ghost 6.0 release](https://ghost.org/changelog/6/) - [Ghost releases](https://github.com/TryGhost/Ghost/releases) - [Ghost Platform Team — Deprecating Ghost-CLI](https://forum.ghost.org/t/deprecating-ghost-cli-other-platform-updates/63595) - Guidance and current release re-verified: 2026-09-05 --- ### Deploy Vaultwarden on Ubuntu 24.04 with Docker Compose URL: https://rafftechnologies.com/learn/tutorials/deploy-vaultwarden-docker-ubuntu-24-04 Description: Deploy Vaultwarden on Ubuntu 24.04 with Docker Compose, Caddy HTTPS, locked-down signup/admin access, consistent backups, restores, and safe updates. Vaultwarden is a lightweight, Bitwarden-compatible password manager that you can self-host on your own server. On Ubuntu 24.04, a practical deployment is Docker Compose with Vaultwarden on a private Docker network and Caddy as the only public-facing container for HTTPS. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Raff VM with 2 vCPU, 4 GB DDR5 RAM, 40 GB NVMe storage, Ubuntu 24.04 LTS, kernel 6.8.x`. This revision re-verifies the deployment guidance against current Vaultwarden documentation and releases on September 5, 2026 without claiming a new end-to-end machine test. This guide pins **Vaultwarden 1.37.2**, the current stable release at verification time. Vaultwarden's release notes specifically require 1.37.2 for compatibility with Bitwarden clients version 2026.8.0 and newer. The deployment also uses the modern integrated WebSocket path: notifications share Vaultwarden's normal HTTP port, so the old dedicated `3012` WebSocket port and `WEBSOCKET_ENABLED` setting are no longer part of the recommended setup. A password manager is security-critical infrastructure. Do not put real credentials into the vault until HTTPS works, the first account can sign in, public registration is disabled, the admin page is disabled unless intentionally required, and you have created an off-server backup. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A domain such as `vault.example.com` pointing to the VM - Public TCP 80 and 443 available for HTTPS - A tested recovery path before firewall changes - A secure off-server destination for Vaultwarden backups ## Step 1 — Verify Ubuntu, DNS, resources, and existing listeners Confirm the operating system and architecture: ```bash cat /etc/os-release uname -m ``` Check memory and free storage: ```bash free -h df -h / ``` Set the hostname you plan to use and verify DNS: ```bash export DOMAIN=vault.example.com dig +short A "$DOMAIN" dig +short AAAA "$DOMAIN" ``` Publish an `AAAA` record only when IPv6 really reaches this VM and is protected consistently. Inspect current listeners: ```bash sudo ss -tulpn ``` Ports 80 and 443 should be available for the Caddy reverse proxy. Vaultwarden itself will not publish a host port in this deployment. **Verify:** Ubuntu should report 24.04, DNS should point to this server, available memory/disk should be understood, and no unexpected service should already own TCP 80 or 443. ## Step 2 — Update Ubuntu and install Docker Engine with Compose v2 Update package metadata and review upgrades: ```bash sudo apt update apt list --upgradable 2>/dev/null ``` Apply updates according to your maintenance policy: ```bash sudo apt upgrade ``` Install the Docker repository prerequisites: ```bash sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc ``` Add Docker's official repository: ```bash sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null < .env <<'EOF' DOMAIN=vault.example.com ACME_EMAIL=admin@example.com EOF chmod 600 .env ``` Replace both values with your real domain and certificate contact email. This main deployment intentionally does **not** define `ADMIN_TOKEN`; that keeps `/admin` disabled. If you later need the admin interface, use Vaultwarden's Argon2-hashed-token procedure rather than a plaintext token. **Verify:** `/opt/vaultwarden` should exist, `vw-data` and `backups` should not be group/world accessible, and `.env` should have mode 600. ## Step 5 — Create a pinned Vaultwarden 1.37.2 Docker Compose stack Create `compose.yaml`: ```bash cat > compose.yaml <<'EOF' services: vaultwarden: image: vaultwarden/server:1.37.2 container_name: vaultwarden restart: unless-stopped environment: DOMAIN: "https://${DOMAIN}" SIGNUPS_ALLOWED: "true" SHOW_PASSWORD_HINT: "false" IP_HEADER: "X-Real-IP" LOG_LEVEL: "warn" TZ: "Etc/UTC" volumes: - ./vw-data:/data networks: - vaultwarden_net caddy: image: caddy:2 container_name: vaultwarden-caddy restart: unless-stopped depends_on: - vaultwarden ports: - "80:80" - "443:443" environment: DOMAIN: "${DOMAIN}" ACME_EMAIL: "${ACME_EMAIL}" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config networks: - vaultwarden_net networks: vaultwarden_net: driver: bridge volumes: caddy_data: caddy_config: EOF ``` Why pin Vaultwarden instead of using `latest`? A password-manager server update can include database migrations and client-compatibility changes. An exact stable tag makes the deployed version auditable and lets you review each future update deliberately. The Vaultwarden service has no `ports:` block, so it is reachable only from the Compose network. **Verify:** `grep -n 'vaultwarden/server' compose.yaml` should show `1.37.2`, and the Vaultwarden service should not publish any host port. ## Step 6 — Configure Caddy HTTPS and the modern WebSocket path Create `Caddyfile`: ```bash cat > Caddyfile <<'EOF' { email {$ACME_EMAIL} } {$DOMAIN} { encode zstd gzip header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" Referrer-Policy "same-origin" -Server } reverse_proxy vaultwarden:80 { header_up X-Real-IP {remote_host} } } EOF ``` Modern Vaultwarden WebSocket notifications are integrated into the normal HTTP server. Caddy's `reverse_proxy` supports WebSocket upgrades automatically, so do not add an old rule such as: ```text /notifications/hub -> vaultwarden:3012 ``` and do not add `WEBSOCKET_ENABLED=true`. Those belong to older Vaultwarden deployments. Validate the Compose model before starting it: ```bash sudo docker compose config >/dev/null && echo 'Compose config is valid' ``` **Verify:** The Caddyfile should proxy only to `vaultwarden:80`, Compose validation should pass, and there should be no reference to port 3012. ## Step 7 — Pull, start, and verify Vaultwarden 1.37.2 over HTTPS Pull the pinned images: ```bash cd /opt/vaultwarden sudo docker compose pull ``` Start the stack: ```bash sudo docker compose up -d ``` Inspect status and recent logs: ```bash sudo docker compose ps sudo docker compose logs --tail=100 vaultwarden sudo docker compose logs --tail=100 caddy ``` Verify the running Vaultwarden version: ```bash sudo docker compose exec vaultwarden /vaultwarden --version ``` Expected version: ```text vaultwarden 1.37.2 ``` Test HTTPS: ```bash DOMAIN=$(sed -n 's/^DOMAIN=//p' .env) curl -I "https://$DOMAIN" ``` Vaultwarden 1.37.2 is the current stable release at this revision and upstream specifically calls it required for Bitwarden clients 2026.8.0 and newer. **Verify:** Both containers should stay running, `/vaultwarden --version` should report 1.37.2, Caddy should obtain a trusted certificate, and the HTTPS endpoint should respond successfully. ## Step 8 — Create the first account and verify client login before storing real credentials Open: ```text https://vault.example.com ``` Create the first Vaultwarden account while `SIGNUPS_ALLOWED=true`. Use a unique, high-entropy master password. Do not assume the server can recover a forgotten master password; the password-manager design depends on client-side encryption. Establish your own recovery process before putting irreplaceable credentials in the vault. After account creation: 1. Sign out of the web vault. 2. Sign back in. 3. Connect one Bitwarden-compatible browser extension or desktop/mobile client to your self-hosted server URL. 4. Create a temporary test item. 5. Force/trigger a sync if needed. 6. Confirm the item appears in both the web vault and the client. Current Vaultwarden 1.37.2 release notes mention client compatibility changes around Bitwarden 2026.8.0+, so testing at least one real client is more meaningful than checking the browser page alone. **Verify:** The account should log in through HTTPS, at least one supported client should connect to the self-hosted URL, and a temporary item should synchronize successfully. ## Step 9 — Disable public registration immediately after onboarding Once the intended first account exists, change: ```yaml SIGNUPS_ALLOWED: "true" ``` to: ```yaml SIGNUPS_ALLOWED: "false" ``` using a controlled edit: ```bash cd /opt/vaultwarden sed -i 's/SIGNUPS_ALLOWED: "true"/SIGNUPS_ALLOWED: "false"/' compose.yaml sudo docker compose up -d ``` Verify the running environment: ```bash sudo docker compose exec vaultwarden printenv SIGNUPS_ALLOWED ``` Expected output: ```text false ``` Then open the registration page in a private/incognito browser and confirm an unknown visitor cannot create a new account. Do not repeatedly toggle public signups for routine user onboarding. For multi-user deployments, review Vaultwarden's invitation and organization controls rather than leaving anonymous registration enabled indefinitely. **Verify:** `SIGNUPS_ALLOWED` should report `false`, normal existing-user login should still work, and unauthenticated public signup should no longer be available. ## Step 10 — Keep the Vaultwarden admin page disabled unless you explicitly need it Because `ADMIN_TOKEN` is absent from this stack, the Vaultwarden admin interface should be disabled. Check it: ```bash DOMAIN=$(sed -n 's/^DOMAIN=//p' /opt/vaultwarden/.env) curl -sS "https://$DOMAIN/admin" | head ``` A disabled-admin response is the intended state for this guide. If you genuinely need `/admin`, do not use a plaintext token. Generate an Argon2 PHC hash with the exact Vaultwarden version you run: ```bash sudo docker run --rm -it vaultwarden/server:1.37.2 /vaultwarden hash ``` Vaultwarden's admin documentation recommends storing the resulting Argon2 hash as the `ADMIN_TOKEN` configuration value. How `$` characters must be quoted/escaped depends on whether you place the value directly in Compose YAML, a Compose `.env` file, another environment file, or a stack manager, so follow Vaultwarden's current **Enabling admin page** documentation for your exact configuration method. Also be aware that values saved through `/admin` are written to `/data/config.json` and can override environment variables on later starts. Do not mix GUI-managed configuration and Compose-managed configuration without understanding that precedence. If you no longer need the admin page, remove both the environment token **and** any persisted `admin_token` setting in `config.json` according to the official documentation, then restart Vaultwarden. **Verify:** For this tutorial's default architecture, `/admin` should stay disabled and the container logs should not report a plaintext `ADMIN_TOKEN` warning. ## Step 11 — Create a consistent Vaultwarden backup with the built-in SQLite backup command Vaultwarden's `/data` directory contains more than the database: attachments, Send data, RSA keys, configuration, and other persistent application state may also be present. Back up the full persistent dataset, but do not rely on a raw copy of an actively written SQLite database. First create Vaultwarden's built-in consistent SQLite snapshot: ```bash cd /opt/vaultwarden sudo docker compose exec vaultwarden /vaultwarden backup ``` This creates a timestamped file such as: ```text /data/db_20260905_120000.sqlite3 ``` Then stop Vaultwarden briefly so the non-database files are copied from a quiet state: ```bash sudo docker compose stop vaultwarden ``` Create an archive that includes the generated SQLite snapshot and the rest of `/data`, but excludes the live SQLite database/WAL/SHM files: ```bash BACKUP="backups/vaultwarden-$(date -u +%Y%m%d-%H%M%S).tar.gz" sudo tar \ --exclude='vw-data/db.sqlite3' \ --exclude='vw-data/db.sqlite3-wal' \ --exclude='vw-data/db.sqlite3-shm' \ -czf "$BACKUP" \ vw-data compose.yaml Caddyfile .env ``` Start Vaultwarden again: ```bash sudo docker compose start vaultwarden ``` Inspect the archive: ```bash sudo tar -tzf "$BACKUP" | head -n 40 sudo ls -lh "$BACKUP" ``` Copy the archive to a protected **off-server** location. Treat it as sensitive infrastructure data even though vault contents are encrypted. :::cta Protect Your Vaultwarden VM Run Vaultwarden on a Raff Ubuntu VM and keep a separate recovery copy with Data Protection or an off-server backup workflow. ::: **Verify:** The archive should contain a `db_*.sqlite3` snapshot plus persistent Vaultwarden files, Vaultwarden should be running again, and at least one protected backup copy should exist outside the VM. ## Step 12 — Test the restore procedure before you depend on the backup Do not overwrite production during a routine test. Restore into a disposable VM or isolated test directory first. For an actual recovery, stop the stack before replacing data: ```bash cd /opt/vaultwarden sudo docker compose down ``` Move the current data aside rather than deleting it immediately: ```bash sudo mv vw-data "vw-data.before-restore-$(date +%s)" sudo mkdir vw-data sudo chmod 700 vw-data ``` Extract your backup into a temporary directory and restore the saved `vw-data` contents. The built-in Vaultwarden backup file is named `db_*.sqlite3`; rename the intended snapshot to `db.sqlite3` in the restored data directory. Example after extraction: ```bash sudo cp /restore/vw-data/db_20260905_120000.sqlite3 \ /opt/vaultwarden/vw-data/db.sqlite3 ``` Make sure stale SQLite WAL/SHM files are absent when restoring a database created by Vaultwarden's backup/VACUUM process: ```bash sudo rm -f \ /opt/vaultwarden/vw-data/db.sqlite3-wal \ /opt/vaultwarden/vw-data/db.sqlite3-shm ``` Restore the other persistent files/directories from the archive, then start the stack: ```bash sudo docker compose up -d ``` Validate login, attachments, organization data, Send data if used, and client sync. A database-only restore is not enough when the original vault used attachments or other files under `/data`. Raff [Data Protection](/products/data-protection) can provide VM-level recovery, while [Object Storage](/products/object-storage) can be an off-server target when your backup transfer tooling supports S3-compatible storage. **Verify:** The restored test instance should start with the expected accounts/items, attachments should open when applicable, and a client should synchronize successfully against the restored server. ## Step 13 — Update Vaultwarden deliberately instead of tracking `latest` Before an update: 1. Read the Vaultwarden release notes and open compatibility issues. 2. Run the built-in database backup and create a full off-server archive. 3. Confirm a restore has been tested. 4. Note the exact current image tag. Check the currently running version: ```bash cd /opt/vaultwarden sudo docker compose exec vaultwarden /vaultwarden --version ``` When you decide to move from `1.37.2` to a reviewed newer stable version, change the `image:` tag in `compose.yaml`, then run: ```bash sudo docker compose pull vaultwarden sudo docker compose up -d vaultwarden ``` Verify the new version and logs: ```bash sudo docker compose exec vaultwarden /vaultwarden --version sudo docker compose logs --tail=200 vaultwarden ``` Then test: - web-vault login; - browser extension login/sync; - one mobile/desktop client if you use it; - item creation/edit/sync; - WebSocket/live notifications; - attachments and 2FA methods relevant to your users. If the new version fails and upstream permits rollback across that migration boundary, restore the previous pinned image **and** use the pre-update backup when required. Do not assume every database migration is safely reversible by changing only the Docker tag. **Verify:** The updated server should report the intended exact version and all clients/workflows you rely on should pass before the update is considered complete. ## Step 14 — Run the final security, exposure, and recovery audit Inspect containers and host ports: ```bash cd /opt/vaultwarden sudo docker compose ps sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' sudo ss -tulpn ``` Review UFW if used: ```bash sudo ufw status numbered ``` Verify application settings: ```bash sudo docker compose exec vaultwarden printenv DOMAIN sudo docker compose exec vaultwarden printenv SIGNUPS_ALLOWED sudo docker compose exec vaultwarden /vaultwarden --version ``` Check HTTPS: ```bash DOMAIN=$(sed -n 's/^DOMAIN=//p' .env) curl -I "https://$DOMAIN" ``` Confirm all of the following: - Vaultwarden is the reviewed stable version you intended to run; - only Caddy publishes public 80/443; - no 3012 WebSocket port exists; - HTTPS works with a trusted certificate; - public registration is disabled; - `/admin` is disabled unless intentionally required and protected with an Argon2 token; - `SHOW_PASSWORD_HINT` remains false for a public deployment; - the server's database is not exposed as a public service; - a recent full backup exists off-server; - the restore process has been tested; - client sync works from at least one real Bitwarden-compatible client; - VM disk usage, Docker image growth, and backup retention are monitored. Expected architecture: ```text Internet | | 80/443 v Caddy | | private Docker network v Vaultwarden 1.37.2 :80 | +--> /data (SQLite + attachments + keys + persistent state) ``` **Verify:** There should be no unintended public application port, no anonymous signup path, no plaintext admin token warning, no missing off-server backup, and no unresolved client-sync failure. ## Troubleshooting ### New Bitwarden clients cannot log in or sync Check the server version first: ```bash sudo docker compose exec vaultwarden /vaultwarden --version ``` Vaultwarden 1.37.2 is required by upstream for Bitwarden clients 2026.8.0 and newer. Update to a compatible reviewed stable release before debugging client behavior on an older server. ### WebSocket/live sync is broken Do not add port 3012. Modern Vaultwarden handles WebSockets on the normal HTTP port. Check Caddy and Vaultwarden logs: ```bash sudo docker compose logs --tail=200 caddy sudo docker compose logs --tail=200 vaultwarden ``` Ensure the reverse proxy points to `vaultwarden:80` and supports normal WebSocket upgrades. Caddy's `reverse_proxy` does this automatically. ### `/admin` accepts no token or reports an insecure plaintext token The admin setting is named `ADMIN_TOKEN`. Generate an Argon2 hash using: ```bash sudo docker run --rm -it vaultwarden/server:1.37.2 /vaultwarden hash ``` Then follow Vaultwarden's current admin-page documentation for the correct quoting/escaping in your configuration method. If `data/config.json` exists, remember that GUI-saved settings can override environment variables. ### Backup exists but restored attachments are missing A database backup contains database state, not every file under `/data`. Restore the matching attachments and other persistent directories from the full backup archive as well as the SQLite snapshot. ### HTTPS certificate issuance fails Check DNS, ports, and Caddy logs: ```bash DOMAIN=$(sed -n 's/^DOMAIN=//p' /opt/vaultwarden/.env) dig +short A "$DOMAIN" dig +short AAAA "$DOMAIN" sudo ss -lntp | grep -E ':(80|443)\b' || true sudo docker compose logs --tail=200 caddy ``` An incorrect AAAA record can break IPv6 clients even when IPv4 works. ### Compose changes do not affect Vaultwarden settings Check logs for a message that settings are being overridden by `/data/config.json`. Values saved through the admin UI can take precedence over environment variables. Choose one configuration source deliberately instead of editing both independently. ## Conclusion You now have Vaultwarden running on Ubuntu 24.04 with Docker Compose, a pinned Vaultwarden 1.37.2 image, Caddy HTTPS, modern same-port WebSockets, public registration disabled after onboarding, the admin page disabled by default, and a backup/restore workflow that preserves both SQLite data and non-database files. The important security boundary is broader than the Docker container itself. A usable self-hosted password manager depends on TLS, client/server version compatibility, controlled account creation, protected recovery configuration, consistent backups, and proven restores. Treat every Vaultwarden upgrade as a reviewed change rather than silently following a mutable `latest` tag. For adjacent procedures, continue with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Vaultwarden GitHub repository](https://github.com/dani-garcia/vaultwarden) - [Vaultwarden 1.37.2 release discussion](https://github.com/dani-garcia/vaultwarden/discussions/7615) - [Vaultwarden Wiki — Using Docker Compose](https://github.com/dani-garcia/vaultwarden/wiki/Using-Docker-Compose) - [Vaultwarden Wiki — Proxy examples](https://github.com/dani-garcia/vaultwarden/wiki/Proxy-examples) - [Vaultwarden Wiki — Enabling admin page](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page) - [Vaultwarden Wiki — Backing up your vault](https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault) - [Vaultwarden WebSocket integration change](https://github.com/dani-garcia/vaultwarden/discussions/4023) - Guidance and stable release re-verified: 2026-09-05 --- ### How to Deploy Odoo on Ubuntu 24.04 with Docker Compose URL: https://rafftechnologies.com/learn/tutorials/deploy-odoo-docker-ubuntu-24-04 Description: Deploy Odoo 19 on Ubuntu 24.04 with Docker Compose, PostgreSQL 15, Caddy HTTPS, workers, database lockdown, matched backups, restores, and safe updates. Odoo is an open-source business application suite for CRM, sales, inventory, accounting, websites, manufacturing, and operations. On Ubuntu 24.04, one maintainable self-hosted pattern is Docker Compose with the official Odoo image, PostgreSQL, persistent volumes, and Caddy for HTTPS. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Raff VM with 2 vCPU, 4 GB DDR5 RAM, 50 GB NVMe storage, Ubuntu 24.04 LTS`. This revision re-verifies the deployment guidance against current Odoo documentation and the official Docker image on September 5, 2026 without claiming a new end-to-end machine test. This guide updates the original Odoo 18 deployment to **Odoo 19.0**, the current supported on-premise major release. It pins the official Docker image to `odoo:19.0-20260817`, which is the current dated Odoo 19 image visible on Docker Hub at verification time. Odoo 19 supports PostgreSQL 13 or newer; the official Docker examples continue to use PostgreSQL 15, so this tutorial keeps PostgreSQL 15 as the database major version. The most important upgrade rule is that a same-major Odoo 19 bugfix/image update is not the same as a major database upgrade. Do **not** move an existing Odoo 18 database to Odoo 19 by changing only the Docker tag. Odoo documents major-version upgrades as database transformations that require the official upgrade process and, for customized databases, module migration work. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A domain such as `erp.example.com` pointing to the VM - Public TCP 80 and 443 available for HTTPS - A tested recovery path before firewall changes - A secure off-server destination for Odoo backups ## Step 1 — Verify Ubuntu, DNS, resources, and existing listeners Confirm the operating system and architecture: ```bash cat /etc/os-release uname -m ``` Check CPU, memory, and free disk space: ```bash nproc free -h df -h / ``` Set the Odoo hostname and verify DNS: ```bash export ODOO_DOMAIN=erp.example.com dig +short A "$ODOO_DOMAIN" dig +short AAAA "$ODOO_DOMAIN" ``` Publish an `AAAA` record only when IPv6 really reaches the VM and is protected consistently. Inspect existing listeners: ```bash sudo ss -tulpn ``` Ports 80 and 443 should be available for Caddy. Odoo ports 8069/8072 and PostgreSQL 5432 will remain inside the Docker network rather than being published publicly. **Verify:** Ubuntu should report 24.04, DNS should resolve to this server, resource headroom should be understood, and no unexpected production service should already occupy TCP 80 or 443. ## Step 2 — Install Docker Engine and Docker Compose v2 Update package metadata and install Docker repository prerequisites: ```bash sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc ``` Add Docker's official Ubuntu repository: ```bash sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null < secrets/postgresql_password openssl rand -hex 32 > .odoo_master_password chmod 600 secrets/postgresql_password .odoo_master_password ``` Create the Compose environment file: ```bash cat > .env <<'EOF' ODOO_DOMAIN=erp.example.com ACME_EMAIL=admin@example.com EOF chmod 600 .env ``` Replace the domain and certificate email with your real values. The Odoo `admin_passwd` is not an ordinary user password. It protects database-management operations such as create, delete, dump, and restore. Odoo's own production documentation strongly recommends disabling the Database Manager on internet-facing systems after initial provisioning. **Verify:** Secret files and `.env` should be mode 600, the backup/secrets directories should not be group/world accessible, and you should have stored the generated master password in a password manager before continuing. ## Step 5 — Create the Odoo 19 and PostgreSQL 15 Compose stack Create `compose.yaml`: ```bash cat > compose.yaml <<'EOF' services: db: image: postgres:15 container_name: odoo-db restart: unless-stopped environment: POSTGRES_DB: postgres POSTGRES_USER: odoo POSTGRES_PASSWORD_FILE: /run/secrets/postgresql_password PGDATA: /var/lib/postgresql/data/pgdata secrets: - postgresql_password volumes: - odoo_db_data:/var/lib/postgresql/data/pgdata networks: - odoo_net healthcheck: test: ["CMD-SHELL", "pg_isready -U odoo -d postgres"] interval: 10s timeout: 5s retries: 10 odoo: image: odoo:19.0-20260817 container_name: odoo restart: unless-stopped depends_on: db: condition: service_healthy environment: HOST: db PORT: "5432" USER: odoo PASSWORD_FILE: /run/secrets/postgresql_password secrets: - postgresql_password volumes: - odoo_web_data:/var/lib/odoo - ./config/odoo.conf:/etc/odoo/odoo.conf:ro - ./addons:/mnt/extra-addons networks: - odoo_net caddy: image: caddy:2 container_name: odoo-caddy restart: unless-stopped depends_on: - odoo ports: - "80:80" - "443:443" environment: ODOO_DOMAIN: "${ODOO_DOMAIN}" ACME_EMAIL: "${ACME_EMAIL}" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config networks: - odoo_net secrets: postgresql_password: file: ./secrets/postgresql_password networks: odoo_net: driver: bridge volumes: odoo_web_data: name: odoo_web_data odoo_db_data: name: odoo_db_data caddy_data: caddy_config: EOF ``` The official Odoo 19 image supports `PASSWORD_FILE`, so the PostgreSQL password does not need to be placed directly in Compose YAML. Neither Odoo nor PostgreSQL publishes a host port. **Verify:** `docker compose config` should parse the file, the Odoo image should be pinned to `19.0-20260817`, PostgreSQL should be major 15, and only the Caddy service should contain a `ports:` block. ## Step 6 — Configure Odoo proxy mode, workers, database management, and file permissions Create the initial Odoo configuration using the generated master password: ```bash cd /opt/odoo ODOO_MASTER_PASSWORD="$(cat .odoo_master_password)" cat > config/odoo.conf < /opt/odoo/Caddyfile <<'EOF' { email {$ACME_EMAIL} } {$ODOO_DOMAIN} { encode zstd gzip header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" Referrer-Policy "same-origin" -Server } @websocket path /websocket* reverse_proxy @websocket odoo:8072 { header_up X-Forwarded-Host {host} header_up X-Forwarded-Proto {scheme} header_up X-Real-IP {remote_host} } reverse_proxy odoo:8069 { header_up X-Forwarded-Host {host} header_up X-Forwarded-Proto {scheme} header_up X-Real-IP {remote_host} } } EOF ``` Odoo 19 documents port 8072 as the WebSocket/gevent port when multiprocessing is enabled; it is not used in the default threaded mode. Odoo also requires `proxy_mode` when it is intentionally deployed behind a trusted reverse proxy. Validate the Compose model: ```bash cd /opt/odoo sudo docker compose config >/dev/null && echo 'Compose config is valid' ``` **Verify:** `/websocket` should route to 8072, ordinary requests should route to 8069, and the Compose configuration should validate successfully. ## Step 8 — Start Odoo 19, PostgreSQL, and Caddy and verify the stack Pull the pinned/current images: ```bash cd /opt/odoo sudo docker compose pull ``` Start the stack: ```bash sudo docker compose up -d ``` Check containers and PostgreSQL readiness: ```bash sudo docker compose ps sudo docker compose exec -T db pg_isready -U odoo -d postgres ``` Verify Odoo's major version: ```bash sudo docker compose exec odoo odoo --version ``` Inspect recent logs: ```bash sudo docker compose logs --tail=100 odoo sudo docker compose logs --tail=100 caddy ``` Test HTTPS: ```bash ODOO_DOMAIN=$(sed -n 's/^ODOO_DOMAIN=//p' .env) curl -I "https://$ODOO_DOMAIN" ``` Before the first database exists, the browser should reach Odoo's database setup/selection flow over HTTPS. **Verify:** PostgreSQL should accept connections, Odoo should report version 19.0, all three containers should remain running, and the public domain should answer over trusted HTTPS. ## Step 9 — Create the first Odoo database through the initial setup screen Open: ```text https://erp.example.com ``` Retrieve the database-manager master password only when needed: ```bash sudo grep '^admin_passwd =' /opt/odoo/config/odoo.conf ``` Create the first database with a simple production-safe database name such as: ```text odoo_prod ``` Use a unique administrator email and strong application password. Leave demo data disabled for a production deployment. Preserve the existing tutorial screenshots as visual references for the database creation and Apps dashboard flows: ![odoo_sign_up.png](https://raff-images.s3.raffusercloud.com/odoo_sign_up_7ede2d6ab7.png) ![Odoo Apps dashboard after deployment](https://raff-images.s3.raffusercloud.com/odoo_home_9c87c82043.png) After creation, sign out and back in, then confirm the Apps dashboard loads. :::cta Deploy Your Odoo Server Launch an Ubuntu VM for Odoo and keep the application, PostgreSQL, HTTPS proxy, and recovery workflow under your control. ::: **Verify:** The production database should exist, the first administrator should be able to sign in through HTTPS, and the normal Apps dashboard should load successfully. ## Step 10 — Disable the public Database Manager and restrict Odoo to the production database Odoo explicitly recommends disabling the Database Manager on internet-facing systems. Save the real database name: ```bash cd /opt/odoo read -rp 'Production database name: ' ODOO_DB_NAME if ! [[ "$ODOO_DB_NAME" =~ ^[A-Za-z0-9_]+$ ]]; then echo 'Use only letters, numbers, and underscores.' exit 1 fi printf '%s\n' "$ODOO_DB_NAME" > .odoo_db_name chmod 600 .odoo_db_name ``` Append the production restrictions to the Odoo config: ```bash sudo sed -i 's/^list_db = .*/list_db = False/' config/odoo.conf sudo tee -a config/odoo.conf >/dev/null < Caddyfile <<'EOF' { email {$ACME_EMAIL} } {$ODOO_DOMAIN} { encode zstd gzip header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" Referrer-Policy "same-origin" -Server } @dbmanager path /web/database* respond @dbmanager 404 @websocket path /websocket* reverse_proxy @websocket odoo:8072 { header_up X-Forwarded-Host {host} header_up X-Forwarded-Proto {scheme} header_up X-Real-IP {remote_host} } reverse_proxy odoo:8069 { header_up X-Forwarded-Host {host} header_up X-Forwarded-Proto {scheme} header_up X-Real-IP {remote_host} } } EOF ``` Restart/reload the affected services: ```bash sudo docker compose restart odoo sudo docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile ``` **Verify:** The normal Odoo login should still work, `/web/database/manager` should no longer be publicly accessible, and the config should contain `list_db = False`, an exact `db_name`, and an exact `dbfilter`. ## Step 11 — Verify the complete Odoo 19 application path and worker architecture Check the public application: ```bash cd /opt/odoo ODOO_DOMAIN=$(sed -n 's/^ODOO_DOMAIN=//p' .env) curl -I "https://$ODOO_DOMAIN/web/login" curl -I "https://$ODOO_DOMAIN/web/database/manager" ``` The login endpoint should respond normally. The database-manager request should be blocked by Caddy. Check containers and database readiness: ```bash sudo docker compose ps sudo docker compose exec -T db pg_isready -U odoo -d postgres sudo docker compose exec odoo odoo --version ``` Inspect recent Odoo logs for worker or proxy failures: ```bash sudo docker compose logs --tail=200 odoo ``` Complete an end-to-end browser check: 1. Sign in through `https://erp.example.com`. 2. Open the Apps dashboard. 3. Create a disposable record in a low-risk test area such as a test contact. 4. Refresh and confirm the record persists. 5. Open a second browser session and confirm the application remains responsive. 6. Delete the disposable record. **Verify:** HTTPS, normal login, PostgreSQL, Odoo 19, application writes, database-manager blocking, and the Docker stack should all work together without exposing 8069/8072/5432 publicly. ## Step 12 — Create a consistent PostgreSQL and Odoo filestore backup An Odoo recovery requires the PostgreSQL database **and** the matching filestore. Backing them up at unrelated times can produce a logically inconsistent restore, so briefly stop the Odoo application while taking both copies. ```bash cd /opt/odoo ODOO_DB_NAME="$(cat .odoo_db_name)" STAMP="$(date -u +%Y%m%d-%H%M%S)" sudo docker compose stop odoo ``` Dump PostgreSQL while the application is stopped: ```bash sudo docker compose exec -T db \ pg_dump -U odoo -Fc "$ODOO_DB_NAME" \ > "backups/odoo-db-${ODOO_DB_NAME}-${STAMP}.dump" ``` Archive the Odoo persistent volume, including the filestore: ```bash sudo docker run --rm \ -v odoo_web_data:/data:ro \ -v /opt/odoo/backups:/backup \ alpine:3.20 \ tar -czf "/backup/odoo-web-data-${ODOO_DB_NAME}-${STAMP}.tar.gz" \ -C /data . ``` Start Odoo again: ```bash sudo docker compose start odoo ``` Create a separate sensitive configuration bundle: ```bash sudo tar -czf "backups/odoo-config-${STAMP}.tar.gz" \ compose.yaml Caddyfile .env config secrets .odoo_db_name sudo chmod 600 backups/odoo-*.dump backups/odoo-*.tar.gz ``` Validate the artifacts: ```bash pg_restore -l "backups/odoo-db-${ODOO_DB_NAME}-${STAMP}.dump" | head sudo tar -tzf "backups/odoo-web-data-${ODOO_DB_NAME}-${STAMP}.tar.gz" | head ``` Copy all required recovery artifacts to protected off-server storage. Raff [Data Protection](/products/data-protection) can provide a separate VM recovery layer, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. **Verify:** A readable PostgreSQL custom-format dump, matching Odoo web-data archive, and protected configuration bundle should exist off-server, and Odoo should be running again after the backup window. ## Step 13 — Test an Odoo restore in an isolated environment A backup is not proven until it restores. Do not test by overwriting the live production instance. On a disposable recovery server or isolated Compose project: 1. Start the same Odoo 19 image and a compatible PostgreSQL 15 service. 2. Create an empty target database owned by the Odoo database role. 3. Restore the database dump with `pg_restore`. 4. Restore the matching `odoo_web_data` archive into the Odoo data volume. 5. Apply the matching configuration and database filter. 6. Start Odoo. 7. Sign in and verify business data plus attachments/documents. Example database restore pattern: ```bash createdb -U odoo odoo_prod pg_restore -U odoo -d odoo_prod /backup/odoo-db-odoo_prod-YYYYMMDD-HHMMSS.dump ``` In the Docker layout, run those commands inside the PostgreSQL container or with the appropriate host/network parameters. Do not restore an Odoo 18 database directly into an Odoo 19 runtime. A major-version database requires Odoo's upgrade process first. **Verify:** The isolated restore should start on the intended Odoo major version, the administrator should be able to sign in, attachments should open, representative records should exist, and no production DNS/SMTP/payment/webhook side effects should be triggered from the test environment. ## Step 14 — Update Odoo 19 safely and keep major upgrades separate For a bugfix update **within Odoo 19**, first create the full backup from Step 12 and review the current official Odoo 19 Docker tag. The official image is rebuilt regularly with newer Odoo 19 revisions. Update the pinned dated tag in `compose.yaml`, then pull and recreate only after review: ```bash cd /opt/odoo sudo docker compose pull odoo sudo docker compose up -d odoo ``` After any same-major update, verify: ```bash sudo docker compose exec odoo odoo --version sudo docker compose logs --tail=200 odoo sudo docker compose ps curl -I "https://$(sed -n 's/^ODOO_DOMAIN=//p' .env)/web/login" ``` A **major upgrade** such as Odoo 18 → 19 is different. Odoo describes it as an irreversible database transformation normally performed through the Odoo upgrade service/process. Customized modules may require their own upgrade scripts and rehearsal. Never perform a major upgrade by only changing `image: odoo:18...` to `image: odoo:19...` against the old database. Run the final exposure audit: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' sudo ss -tulpn sudo ufw status numbered ``` Confirm: - the Odoo major version is 19.0; - PostgreSQL is 13+ and this stack uses major 15; - only Caddy publishes public 80/443; - Odoo 8069/8072 and PostgreSQL 5432 are private; - `proxy_mode` is enabled because Odoo is behind Caddy; - `/websocket` routes to 8072 while multiprocessing is enabled; - Database Manager routes are blocked; - `list_db = False`, `db_name`, and `dbfilter` restrict the production database; - PostgreSQL and filestore backups are taken as a matched set; - at least one restore has been rehearsed; - custom addons are version-controlled and included in the upgrade plan; - same-major updates and major database upgrades are treated as different procedures. **Verify:** There should be no unintended public Odoo/PostgreSQL listener, no exposed Database Manager, no missing matched database/filestore backup, and no plan that treats a major Odoo migration as a simple Docker tag change. ## Troubleshooting ### Odoo starts but the browser shows a 502 error Check Odoo and Caddy: ```bash cd /opt/odoo sudo docker compose ps sudo docker compose logs --tail=200 odoo sudo docker compose logs --tail=200 caddy ``` Confirm the normal upstream is `odoo:8069` and the containers share `odoo_net`. ### WebSocket or live features fail after enabling workers Odoo 19 uses the gevent port 8072 for WebSocket traffic in multiprocessing mode. Confirm `workers` is greater than zero and Caddy routes `/websocket*` to `odoo:8072`. ```bash grep '^workers' /opt/odoo/config/odoo.conf grep -n '8072\|websocket' /opt/odoo/Caddyfile sudo docker compose logs --tail=200 odoo ``` ### Database creation returns Access Denied The database-management master password must match `admin_passwd` in the Odoo config: ```bash sudo grep '^admin_passwd =' /opt/odoo/config/odoo.conf ``` Do not confuse this with the PostgreSQL password or the Odoo application administrator password. ### Environment changes do not update the PostgreSQL password Changing `secrets/postgresql_password` does not automatically rotate the password stored inside an already initialized PostgreSQL database. Rotate the PostgreSQL role credential inside PostgreSQL and update the Compose secret as one controlled operation. Do not delete the database volume to solve a credential mismatch. ### The Database Manager is still reachable Check both layers: ```bash grep '^list_db\|^db_name\|^dbfilter' /opt/odoo/config/odoo.conf grep -n 'web/database' /opt/odoo/Caddyfile ``` Odoo recommends disabling database management in production and the reverse proxy can additionally block `/web/database*`. ### An Odoo 18 database fails after changing the image to Odoo 19 Restore the pre-change Odoo 18 runtime and backup. A major database version upgrade requires Odoo's upgrade process; changing the container image alone does not migrate the database schema/data safely. ## Conclusion You now have a current Odoo 19 deployment pattern for Ubuntu 24.04 using Docker Compose, PostgreSQL 15, Caddy HTTPS, multiprocessing workers, WebSocket routing, private application/database ports, production database filtering, matched PostgreSQL/filestore backups, restore testing, and a controlled update process. The main 2026 correction is version and lifecycle discipline: Odoo 19 is the current supported on-premise major, while Odoo 18 remains supported but should not be upgraded by swapping Docker tags. Treat infrastructure updates, Odoo 19 bugfix updates, and major database upgrades as separate change classes with separate recovery plans. For adjacent procedures, use [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Odoo 19 — On-premise system configuration](https://www.odoo.com/documentation/19.0/administration/on_premise/deploy.html) - [Odoo 19 — Source install and PostgreSQL requirements](https://www.odoo.com/documentation/19.0/administration/on_premise/source.html) - [Odoo 19 — CLI reference](https://www.odoo.com/documentation/19.0/developer/reference/cli.html) - [Odoo — Standard and extended support](https://www.odoo.com/documentation/19.0/administration/supported_versions.html) - [Odoo — Bugfix updates vs database upgrades](https://www.odoo.com/documentation/19.0/administration/on_premise/update.html) - [Odoo official Docker image](https://hub.docker.com/_/odoo) - [Odoo 19 Docker entrypoint](https://github.com/odoo/docker/blob/master/19.0/entrypoint.sh) - Guidance and image tags re-verified: 2026-09-05 --- ### Self-Host Invoice Ninja on Ubuntu 24.04 with Docker Compose URL: https://rafftechnologies.com/learn/tutorials/self-host-invoice-ninja-docker-ubuntu-24-04 Description: Self-host Invoice Ninja 5.13.37 on Ubuntu 24.04 with Docker Compose, MySQL, Redis, Caddy HTTPS, built-in queues/scheduler, backups, restores, and safe updates. Invoice Ninja is a self-hosted invoicing and business workflow platform for invoices, quotes, expenses, clients, recurring billing, tasks, and payments. On Ubuntu 24.04, the current official Docker direction is the **Debian-based Invoice Ninja image** with MySQL, Redis, persistent application volumes, and a reverse proxy for HTTPS. Raff Technologies is the VM platform used by the original tutorial. The saved tested environment remains `Raff VM with 2 vCPU, 4 GB DDR5 RAM, 40 GB NVMe storage, Ubuntu 24.04 LTS`. This revision re-verifies the deployment guidance against current Invoice Ninja documentation, Docker files, and image tags on September 5, 2026 without claiming a new end-to-end machine test. This guide pins **Invoice Ninja 5.13.37**, the current Debian-image release at verification time. It also corrects an important operational detail that older tutorials often miss: the current Debian container includes **two Laravel queue workers and the Laravel scheduler under Supervisord**, so you do not need a separate host cron job or queue container when you use the current official Debian image as shown here. The application container remains private. Only Caddy publishes ports 80 and 443. MySQL, Redis, Nginx, PHP-FPM, queue workers, and the scheduler stay inside the Docker network. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A domain such as `billing.example.com` pointing to the VM - Public TCP 80 and 443 available for HTTPS - A tested recovery path before firewall changes - A secure off-server destination for Invoice Ninja backups ## Step 1 — Verify Ubuntu, DNS, resources, and existing listeners Confirm the operating system and architecture: ```bash cat /etc/os-release uname -m ``` Check memory, CPU, and free disk space: ```bash nproc free -h df -h / ``` Set your Invoice Ninja domain and verify DNS: ```bash export INVOICE_NINJA_DOMAIN=billing.example.com dig +short A "$INVOICE_NINJA_DOMAIN" dig +short AAAA "$INVOICE_NINJA_DOMAIN" ``` Only publish an `AAAA` record if IPv6 actually reaches this server and is protected consistently. Inspect current listeners: ```bash sudo ss -tulpn ``` Ports 80 and 443 should be available for Caddy. No Invoice Ninja, MySQL, or Redis port will be published directly on the host. **Verify:** Ubuntu should report 24.04, DNS should resolve to this VM, resource headroom should be understood, and no unexpected production service should already own TCP 80 or 443. ## Step 2 — Install Docker Engine and Docker Compose v2 Install Docker from Docker's official Ubuntu repository: ```bash sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc ``` Add the repository: ```bash sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null < .initial_admin_password chmod 600 .initial_admin_password ``` Prompt for the administrator email: ```bash read -rp 'Initial Invoice Ninja admin email: ' IN_USER_EMAIL read -rp 'Invoice Ninja domain (for example billing.example.com): ' INVOICE_NINJA_DOMAIN read -rp 'ACME certificate email: ' ACME_EMAIL ``` **Verify:** `.initial_admin_password` should exist with mode 600, and the generated application/database secrets should not be written into shell history manually. ## Step 5 — Create a current Invoice Ninja 5.13.37 environment file Create `.env`: ```bash cat > .env < compose.yaml <<'EOF' services: app: image: invoiceninja/invoiceninja-debian:5.13.37 container_name: invoice-ninja-app restart: unless-stopped env_file: - ./.env volumes: - invoice_ninja_app_public:/var/www/html/public - invoice_ninja_app_storage:/var/www/html/storage depends_on: mysql: condition: service_healthy redis: condition: service_healthy networks: - invoice_ninja_net nginx: image: nginx:alpine container_name: invoice-ninja-nginx restart: unless-stopped volumes: - ./nginx:/etc/nginx/conf.d:ro - invoice_ninja_app_public:/var/www/html/public:ro - invoice_ninja_app_storage:/var/www/html/storage:ro depends_on: app: condition: service_healthy networks: - invoice_ninja_net mysql: image: mysql:8.4 container_name: invoice-ninja-mysql restart: unless-stopped environment: MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} volumes: - invoice_ninja_mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u${MYSQL_USER}", "-p${MYSQL_PASSWORD}"] interval: 10s timeout: 5s retries: 10 networks: - invoice_ninja_net redis: image: redis:7.4-alpine container_name: invoice-ninja-redis restart: unless-stopped volumes: - invoice_ninja_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 10 networks: - invoice_ninja_net caddy: image: caddy:2 container_name: invoice-ninja-caddy restart: unless-stopped depends_on: - nginx ports: - "80:80" - "443:443" environment: INVOICE_NINJA_DOMAIN: ${INVOICE_NINJA_DOMAIN} ACME_EMAIL: ${ACME_EMAIL} volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - invoice_ninja_caddy_data:/data - invoice_ninja_caddy_config:/config networks: - invoice_ninja_net networks: invoice_ninja_net: driver: bridge volumes: invoice_ninja_app_public: name: invoice_ninja_app_public invoice_ninja_app_storage: name: invoice_ninja_app_storage invoice_ninja_mysql_data: name: invoice_ninja_mysql_data invoice_ninja_redis_data: name: invoice_ninja_redis_data invoice_ninja_caddy_data: name: invoice_ninja_caddy_data invoice_ninja_caddy_config: name: invoice_ninja_caddy_config EOF ``` Invoice Ninja's older `invoiceninja/invoiceninja` image now carries a deprecation notice directing users to the Debian-based image. This guide therefore pins the current Debian release rather than using the mutable `latest` tag. **Verify:** The app image should be exactly `invoiceninja/invoiceninja-debian:5.13.37`, MySQL/Redis should have no `ports:` block, and only Caddy should publish ports 80/443. ## Step 7 — Create the internal Nginx and public Caddy reverse-proxy configuration Create the Nginx snippets used by the official Debian layout: ```bash cat > nginx/invoiceninja.conf <<'EOF' client_max_body_size 20M; client_body_buffer_size 20M; server_tokens off; fastcgi_buffers 32 16K; gzip on; gzip_comp_level 2; gzip_min_length 1M; gzip_proxied any; gzip_types *; EOF ``` Create the Laravel Nginx virtual host: ```bash cat > nginx/laravel.conf <<'EOF' server { listen 80 default_server; server_name _; root /var/www/html/public; index index.php; charset utf-8; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass app:9000; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } EOF ``` Create `Caddyfile`: ```bash cat > Caddyfile <<'EOF' { email {$ACME_EMAIL} } {$INVOICE_NINJA_DOMAIN} { encode zstd gzip header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" Referrer-Policy "same-origin" -Server } reverse_proxy nginx:80 } EOF ``` Validate the Compose model: ```bash sudo docker compose config >/dev/null && echo 'Compose config is valid' ``` **Verify:** The Compose file should validate, Caddy should proxy only to the private Nginx service, and neither Nginx nor PHP-FPM should be directly exposed on the host. ## Step 8 — Start Invoice Ninja and verify the built-in health check Pull all images first: ```bash cd /opt/invoice-ninja sudo docker compose pull ``` Start the stack: ```bash sudo docker compose up -d ``` Inspect service state: ```bash sudo docker compose ps ``` The current Debian Invoice Ninja image includes an application health check that calls the internal `/health` route through PHP-FPM. Inspect the app health status: ```bash sudo docker inspect \ --format '{{.State.Health.Status}}' \ invoice-ninja-app ``` Check MySQL and Redis: ```bash DB_PASSWORD="$(sed -n 's/^DB_PASSWORD=//p' .env)" sudo docker compose exec -T mysql \ mysqladmin ping -h localhost -uninja -p"$DB_PASSWORD" sudo docker compose exec -T redis redis-cli ping ``` Test HTTPS: ```bash INVOICE_NINJA_DOMAIN="$(sed -n 's/^INVOICE_NINJA_DOMAIN=//p' .env)" curl -I "https://$INVOICE_NINJA_DOMAIN" ``` **Verify:** The app container should become `healthy`, MySQL should report alive, Redis should return `PONG`, Caddy should obtain a trusted certificate, and the public domain should respond over HTTPS. ## Step 9 — Verify the queue workers and scheduler managed by Supervisord The current Debian image starts three application-side process groups automatically: - PHP-FPM; - two `queue:work` processes; - one `schedule:work` process. Check Supervisord from inside the app container: ```bash sudo docker compose exec app supervisorctl status ``` Expected process names include: ```text php-fpm queue-worker_00 queue-worker_01 scheduler ``` You can also inspect the process list: ```bash sudo docker compose exec app ps aux | grep -E \ 'php-fpm|queue:work|schedule:work' | grep -v grep ``` This is why this Docker deployment does not need the host cron line commonly used by manual Invoice Ninja installations: ```text * * * * * php artisan schedule:run ``` Do not run a duplicate host scheduler unless you intentionally redesign the process model. **Verify:** PHP-FPM, both queue workers, and the scheduler should all report `RUNNING`. Recurring invoices and scheduled notifications depend on this scheduler/queue path, so do not consider the deployment production-ready if these processes are missing. ## Step 10 — Log in, rotate the bootstrap password, and remove bootstrap credentials Display the bootstrap email and temporary password only when needed: ```bash grep '^IN_USER_EMAIL=' /opt/invoice-ninja/.env sudo cat /opt/invoice-ninja/.initial_admin_password ``` Open: ```text https://billing.example.com ``` Use the existing tutorial screenshots as visual references: ![Invoice Ninja login page](https://raff-images.s3.raffusercloud.com/invoice_ninja_login_ubuntu_24_04_webp_d831aa8ccc.png) ![Invoice Ninja dashboard](https://raff-images.s3.raffusercloud.com/invoice_ninja_dashboard_ubuntu_24_04_webp_12a621bb7e.png) After the first successful login: 1. Change the administrator password in Invoice Ninja. 2. Sign out and sign back in with the new password. 3. Create one disposable test client. 4. Confirm the client persists after refresh. 5. Delete the disposable test client after verification. Remove the bootstrap variables from `.env`: ```bash cd /opt/invoice-ninja sed -i '/^IN_USER_EMAIL=/d;/^IN_PASSWORD=/d' .env rm -f .initial_admin_password sudo docker compose up -d app nginx ``` The official Debian image warns that if those variables are not explicitly set on first initialization, defaults can be used. They are useful for first-run bootstrap only and should not remain in the long-lived production configuration. :::cta Deploy Your Invoice Ninja Server Launch an Ubuntu VM and run Invoice Ninja with private database/cache services, HTTPS, persistent storage, and your own recovery workflow. ::: **Verify:** The rotated administrator credentials should work, bootstrap variables should be absent from `.env`, the temporary password file should be gone, and Invoice Ninja should remain healthy after the app container is recreated. ## Step 11 — Verify PDF generation, scheduler health, and outbound-email readiness Invoice Ninja's current Debian image includes Chrome/Chromium for Snappdf PDF generation. Create a disposable draft invoice or quote in the UI and preview/download its PDF. Do not send it to a real client during this test. Check application logs if PDF generation fails: ```bash sudo docker compose logs --tail=200 app ``` Verify scheduler and queue processes again: ```bash sudo docker compose exec app supervisorctl status ``` For the initial deployment, outbound mail intentionally remains logged rather than sent: ```bash grep '^MAIL_' /opt/invoice-ninja/.env ``` When you are ready to send real invoices and reminders, replace the mail settings with your SMTP provider's values and recreate the app container: ```bash sudo docker compose up -d app ``` Then send a test message to an address you control and confirm delivery before enabling real recurring workflows. **Verify:** A test PDF should render successfully, queue/scheduler processes should remain running, and SMTP should either remain intentionally disabled via `MAIL_MAILER=log` or be tested successfully with a real provider. ## Step 12 — Create a matched database, application-data, and configuration backup A recoverable Invoice Ninja deployment requires more than MySQL. Preserve: - the MySQL database; - the persistent `/var/www/html/storage` volume; - the persistent `/var/www/html/public` volume; - `.env`, Compose, Nginx, and Caddy configuration. To keep the application files and database closely aligned, stop the web/application path briefly while leaving MySQL available: ```bash cd /opt/invoice-ninja STAMP="$(date -u +%Y%m%d-%H%M%S)" DB_NAME="$(sed -n 's/^DB_DATABASE=//p' .env)" DB_USER="$(sed -n 's/^DB_USERNAME=//p' .env)" DB_PASSWORD="$(sed -n 's/^DB_PASSWORD=//p' .env)" sudo docker compose stop caddy nginx app ``` Create a consistent InnoDB dump: ```bash sudo docker compose exec -T mysql \ mysqldump \ --single-transaction \ --quick \ --routines \ --triggers \ -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" \ | gzip > "backups/invoice-ninja-db-${STAMP}.sql.gz" ``` Archive the persistent app volumes: ```bash sudo docker run --rm \ -v invoice_ninja_app_public:/app_public:ro \ -v invoice_ninja_app_storage:/app_storage:ro \ -v /opt/invoice-ninja/backups:/backup \ alpine:3.20 \ tar -czf "/backup/invoice-ninja-files-${STAMP}.tar.gz" \ -C / app_public app_storage ``` Create a sensitive configuration bundle: ```bash sudo tar -czf "backups/invoice-ninja-config-${STAMP}.tar.gz" \ compose.yaml Caddyfile nginx .env sudo chmod 600 backups/invoice-ninja-*.sql.gz backups/invoice-ninja-*.tar.gz ``` Start the application path again: ```bash sudo docker compose start app nginx caddy ``` Validate the archives: ```bash gzip -t "backups/invoice-ninja-db-${STAMP}.sql.gz" sudo tar -tzf "backups/invoice-ninja-files-${STAMP}.tar.gz" | head sudo tar -tzf "backups/invoice-ninja-config-${STAMP}.tar.gz" | head ``` Copy the backup set to protected **off-server** storage. Raff [Data Protection](/products/data-protection) can provide a VM-level recovery layer, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. **Verify:** The database dump, app-data archive, and configuration bundle should all be readable, Invoice Ninja should return to `healthy`, and at least one complete backup set should exist outside the VM. ## Step 13 — Test a restore in an isolated environment Do not prove backups by overwriting production. Restore into a disposable VM or isolated Compose project. A recovery test should use the same Invoice Ninja image tag first: ```text invoiceninja/invoiceninja-debian:5.13.37 ``` Restore sequence: 1. Start a clean MySQL-compatible service. 2. Restore `.env` and the Compose/proxy configuration. 3. Restore the `app_public` and `app_storage` volume contents. 4. Import the MySQL dump into the `ninja` database. 5. Start Redis and the Invoice Ninja app. 6. Allow the app entrypoint to perform its normal startup checks/migrations for that same version. 7. Start Nginx/Caddy on isolated test DNS. 8. Sign in and verify clients, invoices, attachments, PDFs, queue workers, and scheduler state. Example database import pattern: ```bash gunzip -c invoice-ninja-db-YYYYMMDD-HHMMSS.sql.gz \ | mysql -uninja -p ninja ``` Use the equivalent command inside the recovery MySQL container with the matching credentials. Disable or redirect SMTP, payment webhooks, and any external automation before starting a restored test copy so it cannot send real invoices or trigger real integrations. **Verify:** The restored instance should log in successfully, representative invoices/clients/files should exist, PDF generation should work, queue/scheduler processes should be running, and the test environment should not contact production customers or payment endpoints. ## Step 14 — Update Invoice Ninja safely and run the final exposure audit The current official Docker update guidance is to pull the new image and recreate the containers. For a **pinned** production deployment, first review the new release, change the app tag deliberately, and create a full backup from Step 12. Check the currently configured tag: ```bash grep 'invoiceninja/invoiceninja-debian' /opt/invoice-ninja/compose.yaml ``` When moving from `5.13.37` to a reviewed newer release, edit the exact image tag, then run: ```bash cd /opt/invoice-ninja sudo docker compose pull app sudo docker compose up -d app nginx caddy ``` The current Debian image entrypoint runs production migrations and cache/design update steps during startup. That is convenient, but it also means a database migration may happen when a new image starts. Do not assume that changing the image tag back is a complete rollback after a migration; keep the pre-update database/files backup until the new version is fully verified. After the update, check: ```bash sudo docker compose ps sudo docker inspect --format '{{.State.Health.Status}}' invoice-ninja-app sudo docker compose exec app supervisorctl status sudo docker compose logs --tail=200 app ``` Run the final host exposure audit: ```bash sudo docker ps --format 'table {{.Names}}\t{{.Ports}}' sudo ss -tulpn sudo ufw status numbered ``` Confirm all of the following: - Invoice Ninja uses the reviewed Debian image version; - only Caddy publishes public TCP 80/443; - Nginx, PHP-FPM, MySQL, and Redis remain private; - `APP_ENV=production`, `APP_DEBUG=false`, and `REQUIRE_HTTPS=true`; - bootstrap admin variables are removed; - the app health check reports `healthy`; - two queue workers are running; - the Laravel scheduler is running; - PDFs render with Snappdf; - SMTP is either intentionally disabled or tested; - a complete database/files/configuration backup exists off-server; - restore testing has been completed; - updates are backed up before the new image starts and runs migrations. **Verify:** There should be no unintended public database/cache/application listener, no leftover bootstrap password, no stopped scheduler/queue process, no untested PDF path, and no update plan that relies only on changing Docker tags for rollback. ## Troubleshooting ### The app container never becomes healthy Inspect the app and database logs: ```bash cd /opt/invoice-ninja sudo docker compose logs --tail=200 app sudo docker compose logs --tail=200 mysql sudo docker compose ps ``` The Debian image health check expects the internal `/health` route to return the Invoice Ninja API health response through PHP-FPM. ### Recurring invoices or reminders do not run Check the scheduler and queue workers first: ```bash sudo docker compose exec app supervisorctl status ``` The current Debian image should show two queue workers plus a scheduler. Do not add another host cron before confirming the built-in scheduler has actually failed. ### Invoice Ninja shows a 502 error Check the proxy/application chain: ```bash sudo docker compose ps sudo docker compose logs --tail=200 caddy sudo docker compose logs --tail=200 nginx sudo docker compose logs --tail=200 app ``` The expected path is Caddy → private Nginx → app PHP-FPM on port 9000. ### MySQL is unhealthy after changing `.env` Changing the password in `.env` does not automatically change the password stored inside an existing MySQL data volume. Rotate the MySQL account credential and `.env` together as one controlled operation. Do not delete the MySQL volume to fix a password mismatch unless you intentionally want to erase the database. ### PDF generation fails The current Debian image includes Chrome on amd64 and Chromium on arm64 and sets the Snappdf browser path automatically at container startup. Check app logs first: ```bash sudo docker compose logs --tail=200 app ``` Also verify `PDF_GENERATOR=snappdf` and that the application URL is reachable from the container. ### The app fails after an image update Stop the new application container and use the pre-update recovery set. Because the production entrypoint can run database migrations automatically, do not assume that simply restoring the old image tag is enough. Restore the pre-update database and matching app-data files when required. ## Conclusion You now have a current Invoice Ninja self-hosting pattern for Ubuntu 24.04 using the official Debian-based **5.13.37** image, MySQL, Redis, Nginx, Caddy HTTPS, built-in queue workers and scheduler, persistent application data, verified health checks, matched backups, restore testing, and a controlled update process. The major 2026 corrections are operational rather than cosmetic: avoid the deprecated older Docker image, avoid a mutable `latest` tag for production, understand that the Debian image already supervises queues and scheduling, and treat every image update as a potential database migration event that requires a proven pre-update recovery point. For adjacent procedures, continue with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Invoice Ninja — Self Host Installation](https://invoiceninja.github.io/docs/self-host/self-host-installation) - [Invoice Ninja — Environment Variables](https://invoiceninja.github.io/docs/self-host/env-variables) - [Invoice Ninja — Self Host Updating](https://invoiceninja.github.io/docs/self-host/self-host-updating) - [Invoice Ninja — Self Host Troubleshooting](https://invoiceninja.github.io/docs/self-host/self-host-troubleshooting) - [Invoice Ninja official Debian Docker files](https://github.com/invoiceninja/dockerfiles/tree/debian/debian) - [Invoice Ninja Debian Docker image](https://hub.docker.com/r/invoiceninja/invoiceninja-debian) - Version and Docker process model re-verified: 2026-09-05 --- ### How to Install MySQL on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-mysql-ubuntu-24-04 Description: Install MySQL 8.0 on Ubuntu 24.04, secure accounts and port 3306, verify CRUD and TLS, create backups, test restores, and apply updates safely. MySQL is a relational database server commonly used by WordPress, Laravel, PHP applications, e-commerce systems, and other transactional workloads. On Ubuntu 24.04, the simplest supported installation path is Ubuntu's own `mysql-server` package, which currently tracks **MySQL 8.0**. As of September 5, 2026, Ubuntu's Noble updates repository provides **MySQL 8.0.46** for the current amd64 package path. Raff Technologies is the VM platform used by the original tutorial. The saved test note remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 4 GB RAM VM; package, account, and network guidance reviewed in July 2026`. This revision re-verifies the installation, authentication, network, TLS, backup, restore, and update guidance against current Ubuntu and MySQL documentation without claiming a new end-to-end machine test. This tutorial intentionally stays on Ubuntu's supported MySQL 8.0 packages. Oracle's separate MySQL APT repository offers newer release tracks, including newer LTS branches, but switching repositories changes the upgrade and support model and is outside this installation path. By default, the database stays local to the VM. Port 3306 is not exposed publicly. A separate optional step shows how to permit one private application server with an exact source IP and encrypted transport. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A tested recovery path before firewall or database changes - Enough disk space for both the live database and at least one backup - An off-server destination for production backup copies ## Step 1 — Verify Ubuntu 24.04 and the MySQL package candidate Confirm the operating system: ```bash cat /etc/os-release uname -m ``` Refresh package metadata: ```bash sudo apt update ``` Inspect the MySQL package candidate before installing: ```bash apt-cache policy mysql-server mysql-server-8.0 ``` On current Ubuntu 24.04 amd64 repositories, the `mysql-server` metapackage resolves to the MySQL 8.0 line; at this revision the current package is 8.0.46. Check CPU, memory, and disk headroom: ```bash nproc free -h df -h / ``` Do not copy a fixed VM size blindly. MySQL memory usage depends on the buffer pool, connection count, per-session buffers, temporary tables, workload shape, and what else runs on the VM. **Verify:** Ubuntu should report 24.04, APT should show a MySQL 8.0 candidate from the Ubuntu repositories, and the VM should have enough free storage for the database plus backup growth. ## Step 2 — Install MySQL Server from Ubuntu's repository Install MySQL Server and basic administration utilities: ```bash sudo apt install -y mysql-server ufw ``` Verify the installed client and server versions: ```bash mysql --version sudo mysql -NBe 'SELECT VERSION();' ``` The exact Ubuntu patch suffix changes as security and maintenance updates are published. Inspect package ownership so you know which repository is managing this installation: ```bash apt-cache policy mysql-server-8.0 ``` Do not add Oracle's MySQL APT repository after installation unless you have a planned repository migration and tested rollback procedure. **Verify:** `mysql-server` should be installed successfully, `SELECT VERSION()` should return MySQL 8.0.x, and APT should show Ubuntu's repository as the installed package source. ## Step 3 — Verify the MySQL service, Unix socket, and listeners Confirm that MySQL is active and starts at boot: ```bash systemctl is-active mysql systemctl is-enabled mysql sudo systemctl status mysql --no-pager ``` Check the server through the local Unix socket: ```bash sudo mysqladmin ping ``` Expected result: ```text mysqld is alive ``` Inspect MySQL listeners: ```bash sudo ss -lntp | grep ':3306' || true ``` Ubuntu's packaged configuration is intended to keep a normal single-host installation on a restricted listener rather than exposing MySQL to the public internet. Inspect the runtime address and port from MySQL itself: ```bash sudo mysql -NBe 'SELECT @@bind_address, @@port;' ``` **Verify:** The service should be active/enabled, `mysqladmin ping` should succeed, and no unexpected public listener should exist on port 3306. ## Step 4 — Verify local root administration and the authentication plugin Open the administrative client through sudo: ```bash sudo mysql ``` Inspect the root account: ```sql SELECT user, host, plugin FROM mysql.user WHERE user = 'root'; ``` Ubuntu normally configures `root@localhost` for local socket-based administration. Keep that local administrative path unless you have a documented reason to redesign it. Exit: ```sql EXIT; ``` Do not convert the root database account to a password-authenticated remote account just to connect an application, GUI, or automation tool. Create a separate least-privileged account instead. **Verify:** `sudo mysql` should provide local administrative access, the root account should remain restricted to localhost, and no remote root account should be required for normal application operation. ## Step 5 — Run `mysql_secure_installation` and verify the resulting state Run MySQL's hardening utility: ```bash sudo mysql_secure_installation ``` The prompts can vary with package revision and the current account state. For a fresh server, the useful outcomes are: - no anonymous MySQL users; - no remotely accessible root account; - no `test` database; - optional password-strength validation when appropriate for your environment. Verify the resulting state directly instead of relying only on the interactive prompts: ```bash sudo mysql -NBe \ "SELECT user, host FROM mysql.user WHERE user = '';" sudo mysql -NBe \ "SELECT user, host FROM mysql.user WHERE user = 'root';" sudo mysql -NBe \ "SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'test';" ``` The anonymous-user and test-database queries should return no rows. Root should remain local. **Verify:** Anonymous users and the test database should be absent, and there should be no root account intended for remote application access. ## Step 6 — Create a dedicated application database and user Open MySQL as the local administrator: ```bash sudo mysql ``` Create a dedicated database: ```sql CREATE DATABASE raffapp CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; ``` Create a local application account with a generated password: ```sql CREATE USER 'raffappuser'@'localhost' IDENTIFIED WITH caching_sha2_password BY RANDOM PASSWORD; ``` Store the generated password immediately in your secrets manager. It cannot be recovered later in plain text. Grant privileges only on the application database: ```sql GRANT ALL PRIVILEGES ON raffapp.* TO 'raffappuser'@'localhost'; ``` Inspect the account and grants: ```sql SHOW CREATE USER 'raffappuser'@'localhost'; SHOW GRANTS FOR 'raffappuser'@'localhost'; EXIT; ``` `caching_sha2_password` is MySQL's preferred authentication plugin. Do not downgrade an account to `mysql_native_password` merely to support an obsolete connector; that plugin is deprecated in MySQL 8.0, disabled by default in MySQL 8.4, and removed in MySQL 9.0. **Verify:** The application user should authenticate with `caching_sha2_password` and should have privileges only on `raffapp.*`, not global administrative privileges. ## Step 7 — Complete an authenticated CRUD test Connect as the application user: ```bash mysql -u raffappuser -p raffapp ``` Create a disposable table: ```sql CREATE TABLE tutorial_check ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, status VARCHAR(32) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY unique_name (name) ) ENGINE=InnoDB; ``` Insert, read, update, and delete a row: ```sql INSERT INTO tutorial_check (name, status) VALUES ('mysql-tutorial-test', 'created'); SELECT name, status FROM tutorial_check WHERE name = 'mysql-tutorial-test'; UPDATE tutorial_check SET status = 'verified' WHERE name = 'mysql-tutorial-test'; SELECT name, status FROM tutorial_check WHERE name = 'mysql-tutorial-test'; DELETE FROM tutorial_check WHERE name = 'mysql-tutorial-test'; DROP TABLE tutorial_check; EXIT; ``` The second `SELECT` should show `verified`. **Verify:** The non-root application account should be able to create, read, update, and delete data inside its own database without requiring root privileges. ## Step 8 — Keep MySQL local and protect port 3306 Inspect the configured bind address: ```bash sudo mysql -NBe 'SELECT @@bind_address, @@port;' sudo ss -lntp | grep ':3306' || true ``` For an application running on the same VM, keep MySQL local. Do not switch to `0.0.0.0` simply because a tutorial or GUI expects TCP access. Before enabling or changing UFW, open a second SSH session and verify the current SSH rule: ```bash sudo ufw status numbered ``` If UFW is already active, add a defense-in-depth deny rule for MySQL only if it does not conflict with an intentional private-network rule: ```bash sudo ufw deny 3306/tcp ``` If UFW is inactive, follow the lockout-safe procedure in [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) instead of blindly running `ufw enable` from one remote shell. **Verify:** MySQL should not listen on a public interface for a single-VM application, and there should be no public allow rule for TCP 3306. ## Step 9 — Optionally allow one private application server with TLS Use this step only when the application is on a separate VM connected through a private network. The example addresses below are placeholders: ```text Database private IP: 10.0.0.5 Application private IP: 10.0.0.10 ``` Back up the MySQL server configuration: ```bash sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf \ /etc/mysql/mysql.conf.d/mysqld.cnf.before-private-access ``` Edit the MySQL configuration: ```bash sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf ``` Bind MySQL only to loopback plus the database VM's exact private IP: ```ini bind-address = 127.0.0.1,10.0.0.5 ``` Validate the configuration before restart: ```bash sudo mysqld --validate-config sudo systemctl restart mysql systemctl is-active mysql ``` Create a separate account restricted to the application's exact private IP and require encrypted transport: ```bash sudo mysql ``` ```sql CREATE USER 'raffappuser'@'10.0.0.10' IDENTIFIED WITH caching_sha2_password BY RANDOM PASSWORD REQUIRE SSL; GRANT ALL PRIVILEGES ON raffapp.* TO 'raffappuser'@'10.0.0.10'; SHOW GRANTS FOR 'raffappuser'@'10.0.0.10'; EXIT; ``` Store the generated password securely. If UFW is active, allow only the application VM's private source IP to the database VM's private address: ```bash sudo ufw allow from 10.0.0.10 to 10.0.0.5 port 3306 proto tcp sudo ufw status numbered ``` From the application VM, require TLS: ```bash mysql \ --host=10.0.0.5 \ --user=raffappuser \ --password \ --ssl-mode=REQUIRED \ raffapp ``` Inside that remote session, verify encryption: ```sql SHOW STATUS LIKE 'Ssl_cipher'; ``` The value should be non-empty. For stronger certificate identity validation, deploy a CA/certificate model your application can verify and use `VERIFY_CA` or `VERIFY_IDENTITY` instead of only `REQUIRED`. **Verify:** MySQL should listen only on loopback plus the intended private address, UFW should permit only the application VM, the account host should match that exact private source IP, and the remote session should report an active TLS cipher. ## Step 10 — Create a consistent logical backup with `mysqldump` Create a protected backup directory: ```bash sudo install -d -m 700 /var/backups/mysql ``` For a single InnoDB application database, create a logical backup using a consistent transaction snapshot: ```bash STAMP="$(date -u +%Y%m%d-%H%M%S)" sudo mysqldump \ --single-transaction \ --quick \ --routines \ --triggers \ --events \ --databases raffapp \ | gzip > "/var/backups/mysql/raffapp-${STAMP}.sql.gz" ``` `--single-transaction` is appropriate for transactional tables such as InnoDB because it avoids a long global read lock while producing a consistent snapshot. It does not make non-transactional tables magically consistent, so inspect the storage engines used by your application if you inherit an older database. Restrict the backup: ```bash sudo chmod 600 "/var/backups/mysql/raffapp-${STAMP}.sql.gz" ``` Validate the gzip archive and inspect its beginning without extracting it permanently: ```bash gzip -t "/var/backups/mysql/raffapp-${STAMP}.sql.gz" zcat "/var/backups/mysql/raffapp-${STAMP}.sql.gz" | head ``` Copy production backups off-server. Raff [Data Protection](/products/data-protection) can provide a VM-level recovery layer, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. :::cta Protect Your MySQL Server Run MySQL on a Raff Ubuntu VM and keep a separate recovery copy with Data Protection or an off-server backup workflow. ::: **Verify:** A compressed logical dump should exist with restrictive permissions, `gzip -t` should succeed, and at least one production backup copy should be stored outside the database VM. ## Step 11 — Test the backup by restoring into a disposable database Do not test restores by overwriting production. Create a disposable restore database: ```bash sudo mysql -e \ "CREATE DATABASE raffapp_restore_test CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;" ``` Because the dump from Step 10 includes `CREATE DATABASE raffapp` statements via `--databases`, the safest isolated test is to rewrite the target database name in a disposable copy of the SQL stream rather than importing it into production. Create a temporary SQL file: ```bash LATEST_BACKUP="$(ls -1t /var/backups/mysql/raffapp-*.sql.gz | head -n 1)" TMP_SQL="$(mktemp)" zcat "$LATEST_BACKUP" \ | sed 's/`raffapp`/`raffapp_restore_test`/g' \ > "$TMP_SQL" sudo mysql < "$TMP_SQL" rm -f "$TMP_SQL" ``` Inspect the restored database: ```bash sudo mysql -e \ "SHOW TABLES FROM raffapp_restore_test;" ``` For a production recovery runbook, prefer a dedicated recovery VM or isolated MySQL instance so the restore test cannot affect production users, scheduled jobs, or integrations. Remove the disposable database after verification: ```bash sudo mysql -e 'DROP DATABASE raffapp_restore_test;' ``` **Verify:** The backup should import into an isolated target, expected tables should appear, representative row counts or application checks should pass, and the production `raffapp` database should remain untouched. ## Step 12 — Apply MySQL updates safely through APT Check for available package updates: ```bash apt list --upgradable 2>/dev/null | grep -E '^mysql|^libmysql' || true ``` Before a MySQL package update: 1. create a fresh database backup; 2. confirm the backup is off-server; 3. review the Ubuntu package changelog and MySQL release notes for the target patch; 4. verify adequate disk space; 5. schedule downtime or a maintenance window when the workload requires it. Apply normal Ubuntu updates: ```bash sudo apt update sudo apt upgrade ``` After any MySQL package change, verify: ```bash systemctl is-active mysql sudo mysql -NBe 'SELECT VERSION();' sudo mysqladmin ping sudo journalctl -u mysql --no-pager -n 100 ``` Do not change from Ubuntu's MySQL 8.0 packages to Oracle's separate APT repository as part of a routine patch update. Repository changes and major-version migrations deserve their own tested migration plan. **Verify:** MySQL should restart cleanly on the expected package branch, the server should answer locally, and application authentication/CRUD checks should still pass after patching. ## Step 13 — Review configuration, logs, storage engines, and recovery readiness Validate the active server configuration: ```bash sudo mysqld --validate-config ``` Inspect key runtime settings: ```bash sudo mysql -NBe \ "SELECT @@version, @@bind_address, @@port, @@require_secure_transport;" ``` List application tables and their storage engines: ```bash sudo mysql -NBe \ "SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA='raffapp';" ``` Review recent server logs: ```bash sudo journalctl -u mysql --no-pager -n 100 sudo tail -n 100 /var/log/mysql/error.log ``` Check disk growth: ```bash df -h / sudo du -sh /var/lib/mysql /var/backups/mysql ``` Do not tune `innodb_buffer_pool_size`, `max_connections`, per-session buffers, or durability settings from a generic copy-paste value. Measure the workload first and change one documented setting at a time. **Verify:** The configuration should validate, application tables should use the expected storage engine, logs should contain no unresolved startup/storage errors, and backup growth should not threaten the live data filesystem. ## Step 14 — Run the final MySQL security and recovery audit Run the final service, account, network, and backup checks: ```bash echo 'Service:' systemctl is-active mysql systemctl is-enabled mysql echo 'Version:' sudo mysql -NBe 'SELECT VERSION();' echo 'Root account:' sudo mysql -NBe \ "SELECT user, host, plugin FROM mysql.user WHERE user='root';" echo 'Application accounts:' sudo mysql -NBe \ "SELECT user, host, plugin, ssl_type FROM mysql.user WHERE user='raffappuser';" echo 'Listener:' sudo ss -lntp | grep ':3306' || true echo 'Firewall:' sudo ufw status numbered echo 'Recent backups:' sudo ls -lh /var/backups/mysql/raffapp-*.sql.gz | tail ``` Confirm all of the following: - Ubuntu 24.04 manages this installation through its MySQL 8.0 packages; - the service is active and enabled; - local root administration remains local-only; - anonymous users and the test database are absent; - the application uses its own `caching_sha2_password` account; - the application account has database-scoped privileges rather than global admin rights; - public port 3306 is not exposed; - any private remote account is restricted to an exact source IP and requires TLS; - a logical backup exists off-server; - at least one restore has been rehearsed in isolation; - package updates are backed up and verified instead of being treated as blind restarts. **Verify:** There should be no unintended public MySQL listener, no remote root path, no weak legacy authentication workaround, and no backup strategy that has never been restored. ## Troubleshooting ### `sudo mysql` returns access denied Check the service and error log first: ```bash sudo systemctl status mysql --no-pager sudo tail -n 100 /var/log/mysql/error.log ``` Do not immediately follow a random root-password reset procedure intended for another package source or MySQL major version. Confirm the installed Ubuntu package and account state first. ### MySQL does not start after editing `mysqld.cnf` Validate the configuration and inspect the journal: ```bash sudo mysqld --validate-config sudo journalctl -u mysql --no-pager -n 100 sudo tail -n 100 /var/log/mysql/error.log ``` Restore the pre-change configuration if validation fails. ### An application cannot authenticate with `caching_sha2_password` Upgrade the application's MySQL connector or runtime. MySQL 8.0 uses `caching_sha2_password` as the preferred authentication plugin. Avoid switching to deprecated `mysql_native_password` simply to support an obsolete client. ### A private remote connection times out Check all four layers: ```bash sudo mysql -NBe 'SELECT @@bind_address, @@port;' sudo ss -lntp | grep ':3306' sudo ufw status numbered sudo mysql -NBe \ "SELECT user, host, plugin, ssl_type FROM mysql.user WHERE user='raffappuser';" ``` The application VM's source IP must match the account host and UFW rule. ### A private remote connection works but is not encrypted Connect with `--ssl-mode=REQUIRED` or stronger and inspect the session: ```sql SHOW STATUS LIKE 'Ssl_cipher'; ``` A non-empty cipher confirms TLS. Use `VERIFY_CA` or `VERIFY_IDENTITY` when you have deployed a CA/certificate model the client can validate. ### `mysqldump` fails or the restore test is incomplete Confirm the database exists, inspect storage engines, and ensure sufficient disk space: ```bash sudo mysql -e 'SHOW DATABASES;' sudo mysql -e \ "SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA='raffapp';" df -h / ``` For larger databases or stricter recovery objectives, logical dumps may not be sufficient by themselves; combine database-aware backups with VM/data-protection procedures and a documented restore runbook. ## Conclusion You now have MySQL 8.0 installed on Ubuntu 24.04 from Ubuntu's supported repository, with local-only root administration, a dedicated `caching_sha2_password` application account, verified CRUD operations, private-by-default networking, optional TLS-protected private access, logical backups, restore testing, and a controlled APT update workflow. The key 2026 distinction is repository discipline: Ubuntu 24.04's default MySQL path remains the 8.0 branch, while Oracle's separate MySQL APT repository offers newer release tracks. Do not mix those two support and upgrade models casually on a production database. For adjacent procedures, continue with [Set Up a LEMP Stack on Ubuntu 24.04](/learn/tutorials/set-up-lemp-stack-ubuntu-24-04), [Install PostgreSQL on Ubuntu 24.04](/learn/tutorials/install-postgresql-ubuntu-24-04), and [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). ## Sources - [Ubuntu 24.04 mysql-server package](https://packages.ubuntu.com/noble-updates/mysql-server-8.0) - [MySQL 8.0 — mysql_secure_installation](https://dev.mysql.com/doc/refman/8.0/en/mysql-secure-installation.html) - [MySQL 8.0 — Securing the initial account](https://dev.mysql.com/doc/refman/8.0/en/default-privileges.html) - [MySQL 8.0 — mysqldump](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html) - [MySQL 8.4 — caching_sha2_password](https://dev.mysql.com/doc/refman/8.4/en/caching-sha2-pluggable-authentication.html) - [MySQL 8.4 — encrypted connections](https://dev.mysql.com/doc/refman/8.4/en/using-encrypted-connections.html) - [MySQL APT Repository](https://dev.mysql.com/downloads/repo/apt/) - Package and security guidance re-verified: 2026-09-05 --- ### How to Install MariaDB on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-mariadb-ubuntu-24-04 Description: Install MariaDB 10.11 on Ubuntu 24.04, secure accounts and port 3306, add private TLS access, back up, restore-test, and update safely. MariaDB is an open-source relational database server used by PHP applications, WordPress, e-commerce systems, internal tools, and other transactional workloads. Ubuntu 24.04 provides the **MariaDB 10.11 long-term maintenance series** through its own repositories. As of September 5, 2026, Ubuntu's Noble package path currently provides **MariaDB 10.11.13**, while upstream MariaDB has newer maintenance releases and a newer **12.3 LTS** series. This tutorial intentionally stays on Ubuntu's distro-managed 10.11 branch instead of silently changing repository and major-version strategy. Raff Technologies is the VM platform used by the original tutorial. The saved test note remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 4 GB RAM VM; package, authentication, account, and network guidance reviewed in July 2026`. This revision re-verifies package selection, socket authentication, network exposure, TLS requirements, backup/restore, and upgrade behavior against current Ubuntu and MariaDB documentation without claiming a new end-to-end machine test. MariaDB and MySQL share historical roots and client-protocol compatibility, but they are separate database systems with different release cycles, authentication behavior, features, and upgrade rules. Treat a MySQL-to-MariaDB move as a migration, not as a package rename. The default design in this guide keeps TCP 3306 private. A separate optional path shows how to allow one application VM over a private address with TLS and an exact source-account restriction. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A tested recovery path before firewall or database changes - Enough free disk for live data and at least one backup - An off-server destination for production backup copies ## Step 1 — Verify Ubuntu 24.04 and the MariaDB package candidate Confirm the OS and architecture: ```bash cat /etc/os-release uname -m ``` Refresh package metadata: ```bash sudo apt update ``` Inspect the MariaDB candidate before installing: ```bash apt-cache policy mariadb-server mariadb-server-10.11 ``` Ubuntu 24.04 currently ships the MariaDB 10.11 branch through its Noble repositories. At this revision the Ubuntu package line is 10.11.13. Check resource and disk headroom: ```bash nproc free -h df -h / ``` Do not copy a fixed VM size from a tutorial. Database memory and I/O requirements depend on active data, buffer-pool needs, connection count, temporary tables, query shape, and other services on the same VM. **Verify:** Ubuntu should report 24.04, APT should show a 10.11 candidate from Ubuntu repositories, and free disk should be sufficient for both the live database and backup growth. ## Step 2 — Install MariaDB Server from Ubuntu's repository Install MariaDB Server, the client, OpenSSL, and UFW: ```bash sudo apt install -y mariadb-server mariadb-client openssl ufw ``` Verify the client and server versions: ```bash mariadb --version sudo mariadb -NBe 'SELECT VERSION();' ``` Inspect package ownership: ```bash apt-cache policy mariadb-server-10.11 ``` The exact Ubuntu patch revision can change with maintenance and security updates. Do not add MariaDB's upstream repository after installation as an incidental update step. Moving from Ubuntu's 10.11 packages to an upstream 11.x or 12.3 LTS branch changes the package source and major-version upgrade path. **Verify:** MariaDB should install successfully, `SELECT VERSION()` should report 10.11.x on this Ubuntu path, and APT should show Ubuntu as the package source. ## Step 3 — Verify the service, Unix socket, and network listeners Confirm the service is active and enabled: ```bash systemctl is-active mariadb systemctl is-enabled mariadb sudo systemctl status mariadb --no-pager ``` Check the local server through the Unix socket: ```bash sudo mariadb-admin ping ``` Expected result: ```text mysqld is alive ``` Inspect TCP listeners: ```bash sudo ss -lntp | grep ':3306' || true ``` Read the runtime bind address and port: ```bash sudo mariadb -NBe 'SELECT @@bind_address, @@port;' ``` Ubuntu/Debian packages commonly restrict MariaDB to loopback by default. Do not assume that a firewall alone makes a public listener safe. **Verify:** MariaDB should be active and enabled, socket administration should work, and there should be no unexpected public TCP 3306 listener. ## Step 4 — Verify local root administration with `unix_socket` Open the administrative client: ```bash sudo mariadb ``` Inspect the root account definition: ```sql SHOW CREATE USER 'root'@'localhost'; ``` Modern MariaDB installations normally use `unix_socket` authentication for local root administration. MariaDB documents that this has been the default model since MariaDB 10.4, so a separate database root password is usually unnecessary for a locally administered Linux server. Confirm root is local-only: ```sql SELECT User, Host FROM mysql.user WHERE User = 'root'; EXIT; ``` Keep local root administration tied to the OS/sudo trust boundary unless you have a documented reason to redesign it. Applications must use separate database accounts. **Verify:** `sudo mariadb` should work, `SHOW CREATE USER` should show the local authentication model, and there should be no root account intended for remote application traffic. ## Step 5 — Run `mariadb-secure-installation` and verify the outcome Run the current MariaDB hardening utility: ```bash sudo mariadb-secure-installation ``` MariaDB renamed the utility from `mysql_secure_installation` in MariaDB 10.5, although a compatibility command may still exist. The exact prompts depend on package state. For a fresh server, focus on outcomes rather than memorizing prompt answers: - preserve socket-based local root administration; - remove anonymous users; - remove remote root access; - remove the `test` database; - reload privileges when prompted. Verify directly: ```bash sudo mariadb -NBe \ "SELECT User, Host FROM mysql.user WHERE User = '';" sudo mariadb -NBe \ "SELECT User, Host FROM mysql.user WHERE User = 'root';" sudo mariadb -NBe \ "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'test';" ``` The anonymous-user and test-database queries should return no rows. Root should remain local. **Verify:** Anonymous accounts and the test database should be absent, and root should not be available as a remote application account. ## Step 6 — Create a dedicated application database and local user Generate an application password without typing it into shell history: ```bash DB_PASSWORD="$(openssl rand -hex 32)" printf 'Store this MariaDB password securely: %s\n' "$DB_PASSWORD" ``` Save the value in a secrets manager, then create the database and local account: ```bash sudo mariadb </dev/null <<'EOF' [mariadb] bind-address = 127.0.0.1,10.0.0.5 EOF ``` Before enabling TLS, create or obtain a real CA, server certificate, and private key. For production, use your organization's PKI or another controlled CA. Do not assume MariaDB automatically enables TLS just because the binary supports it. Place the files at: ```text /etc/mysql/tls/ca-cert.pem /etc/mysql/tls/server-cert.pem /etc/mysql/tls/server-key.pem ``` Protect the directory and private key: ```bash sudo chown -R root:mysql /etc/mysql/tls sudo chmod 750 /etc/mysql/tls sudo chmod 640 /etc/mysql/tls/server-key.pem sudo chmod 644 /etc/mysql/tls/ca-cert.pem /etc/mysql/tls/server-cert.pem ``` Add TLS settings to the custom file: ```bash sudo tee -a /etc/mysql/mariadb.conf.d/z-raff-private.cnf >/dev/null <<'EOF' ssl_ca = /etc/mysql/tls/ca-cert.pem ssl_cert = /etc/mysql/tls/server-cert.pem ssl_key = /etc/mysql/tls/server-key.pem require_secure_transport = ON EOF ``` MariaDB 10.11 does not have the newer `--validate-config` switch introduced in MariaDB 13.0. Instead, inspect the effective startup options before restarting: ```bash mariadbd --print-defaults mariadbd --help --verbose >/dev/null ``` Restart and verify TLS: ```bash sudo systemctl restart mariadb systemctl is-active mariadb sudo mariadb -e "SHOW GLOBAL VARIABLES LIKE 'have_ssl';" ``` `have_ssl` must be `YES` before you create a TLS-required remote account. Create the exact-source application account: ```bash REMOTE_DB_PASSWORD="$(openssl rand -hex 32)" printf 'Store this remote MariaDB password securely: %s\n' "$REMOTE_DB_PASSWORD" sudo mariadb < "/var/backups/mariadb/raffapp-${STAMP}.sql.gz" ``` `--single-transaction` gives a consistent snapshot for transactional tables such as InnoDB without holding a long global read lock. It does not make non-transactional MyISAM/Aria tables consistent with concurrent writes, so inspect inherited databases before assuming the same recovery behavior. Restrict and validate the backup: ```bash sudo chmod 600 "/var/backups/mariadb/raffapp-${STAMP}.sql.gz" gzip -t "/var/backups/mariadb/raffapp-${STAMP}.sql.gz" zcat "/var/backups/mariadb/raffapp-${STAMP}.sql.gz" | head ``` Keep account/grant definitions in configuration management or another protected recovery record; application data alone is not the whole recovery plan. Copy production backup sets off-server. Raff [Data Protection](/products/data-protection) can add a VM-level recovery layer, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. :::cta Protect Your MariaDB Server Run MariaDB on an Ubuntu VM and keep a separate off-server recovery copy for the database and its configuration. ::: **Verify:** The dump should pass `gzip -t`, permissions should restrict access, and a production copy should exist outside the MariaDB VM. ## Step 11 — Test the backup in a disposable restore database Never prove a backup by overwriting production. Create a disposable target: ```bash sudo mariadb -e \ "CREATE DATABASE raffapp_restore_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" ``` Restore the most recent dump into that database: ```bash LATEST_BACKUP="$(ls -1t /var/backups/mariadb/raffapp-*.sql.gz | head -n 1)" zcat "$LATEST_BACKUP" \ | sudo mariadb raffapp_restore_test ``` Inspect the restored tables: ```bash sudo mariadb -e \ "SHOW TABLES FROM raffapp_restore_test;" ``` For production systems, verify representative row counts and application-level records as part of the recovery runbook. Remove the test database after verification: ```bash sudo mariadb -e 'DROP DATABASE raffapp_restore_test;' ``` **Verify:** The dump should import into an isolated target, expected tables/data should be readable, and production `raffapp` should remain untouched. ## Step 12 — Apply Ubuntu MariaDB 10.11 patch updates safely Check for pending MariaDB updates: ```bash apt list --upgradable 2>/dev/null | grep -E '^mariadb|^galera' || true ``` Before updating: 1. create a fresh logical backup; 2. confirm an off-server copy exists; 3. review the Ubuntu package changelog and relevant MariaDB 10.11 release notes; 4. check free disk space; 5. choose an appropriate maintenance window. Apply normal distro updates: ```bash sudo apt update sudo apt upgrade ``` Verify afterward: ```bash systemctl is-active mariadb sudo mariadb -NBe 'SELECT VERSION();' sudo mariadb-admin ping sudo journalctl -u mariadb --no-pager -n 100 ``` For a normal 10.11.x → 10.11.y package update, remain on the same Ubuntu branch. Do not convert a patch cycle into an upstream repository or major-version migration. **Verify:** MariaDB should start cleanly on the expected 10.11 branch, answer through the local socket, and pass the application login/CRUD checks after patching. ## Step 13 — Treat an upstream 12.3 LTS move as a major-version migration MariaDB's current upstream LTS is **12.3**, with 12.3.3 released in August 2026. Ubuntu 24.04's default package path is still 10.11. These are not interchangeable update labels. Before considering a 10.11 → newer upstream LTS move: - read the target-version upgrade notes; - inventory storage engines and plugins; - test application queries and connectors; - create and restore a full backup in staging; - make a clean shutdown plan; - review removed/changed configuration options; - plan `mariadb-upgrade` after the new major version starts. MariaDB recommends a database backup before major upgrades and documents `mariadb-upgrade` as the tool that updates system tables and checks tables after a major-version change. Check whether the tool sees an upgrade requirement: ```bash sudo mariadb-upgrade --check-if-upgrade-is-needed; echo $? ``` Do not run a major upgrade directly on the only production copy. MariaDB explicitly does **not** treat major-version downgrade as a normal supported rollback; the reliable rollback path is a pre-upgrade backup restored onto the old version. **Verify:** A major upgrade should have a tested staging rehearsal, a verified pre-upgrade backup, target-version compatibility notes, and a restore-based rollback plan before repository or binaries are changed. ## Step 14 — Run the final MariaDB security and recovery audit Check service, version, users, listeners, TLS state, firewall, and backups: ```bash echo 'Service:' systemctl is-active mariadb systemctl is-enabled mariadb echo 'Version:' sudo mariadb -NBe 'SELECT VERSION();' echo 'Root accounts:' sudo mariadb -NBe \ "SELECT User, Host FROM mysql.user WHERE User='root';" echo 'Application accounts:' sudo mariadb -NBe \ "SELECT User, Host FROM mysql.user WHERE User='raffappuser';" echo 'Listener:' sudo ss -lntp | grep ':3306' || true echo 'TLS:' sudo mariadb -NBe \ "SHOW GLOBAL VARIABLES LIKE 'have_ssl'; SHOW GLOBAL VARIABLES LIKE 'require_secure_transport';" echo 'Firewall:' sudo ufw status numbered echo 'Recent backups:' sudo ls -lh /var/backups/mariadb/raffapp-*.sql.gz | tail ``` Confirm all of the following: - Ubuntu 24.04 is managing the expected MariaDB 10.11 package branch; - the service is active and enabled; - root administration remains local-only through the intended socket model; - anonymous users and the test database are gone; - the application uses a separate database-scoped account; - public TCP 3306 is not exposed; - any private remote connection is restricted to an exact source IP; - remote TCP access uses a configured and verified TLS certificate path; - a logical backup exists off-server; - restore testing has succeeded; - normal patch updates stay on the distro package branch; - any move to MariaDB 12.3 LTS is handled as a tested major-version migration. **Verify:** There should be no public MariaDB listener, no remote root account, no remote plaintext database path, and no backup or major-upgrade plan that has never been rehearsed. ## Troubleshooting ### `sudo mariadb` returns access denied Inspect the service and account state before trying password-reset procedures: ```bash sudo systemctl status mariadb --no-pager sudo journalctl -u mariadb --no-pager -n 100 sudo tail -n 100 /var/log/mysql/error.log ``` Confirm you are following MariaDB 10.11/Ubuntu guidance rather than a MySQL-specific root recovery procedure. ### MariaDB does not start after a configuration change Inspect the effective options and logs: ```bash mariadbd --print-defaults mariadbd --help --verbose >/dev/null sudo journalctl -u mariadb --no-pager -n 100 sudo tail -n 100 /var/log/mysql/error.log ``` If the failure followed the custom private/TLS file, move that override out of `/etc/mysql/mariadb.conf.d/` and restart with the prior known-good configuration. ### `mariadb-secure-installation` shows different prompts Prompt text varies with package state. Verify the resulting users and schemas instead: no anonymous users, no test database, and no remote root path. ### A local application receives `Access denied` Inspect the exact account host and grants: ```bash sudo mariadb -e \ "SHOW CREATE USER 'raffappuser'@'localhost';" sudo mariadb -e \ "SHOW GRANTS FOR 'raffappuser'@'localhost';" ``` Then retry: ```bash mariadb -u raffappuser -p raffapp ``` ### A private remote connection times out Check bind address, listener, firewall, and account host: ```bash sudo mariadb -NBe 'SELECT @@bind_address, @@port;' sudo ss -lntp | grep ':3306' sudo ufw status numbered sudo mariadb -NBe \ "SELECT User, Host FROM mysql.user WHERE User='raffappuser';" ``` The client source address must match the MariaDB account host and firewall rule. ### TLS is configured but `have_ssl` is `DISABLED` MariaDB supports TLS only after the server is configured with a readable CA, server certificate, and private key. Check file paths, ownership, permissions, and the error log: ```bash sudo ls -l /etc/mysql/tls sudo journalctl -u mariadb --no-pager -n 100 sudo tail -n 100 /var/log/mysql/error.log ``` Do not create a `REQUIRE SSL` remote account until `have_ssl` reports `YES`. ### `mariadb-dump` succeeds but you have never restored it A dump is not a proven backup until it has been restored and checked. Use the disposable restore procedure in Step 11 or a separate recovery VM for production rehearsals. ## Conclusion You now have MariaDB 10.11 installed on Ubuntu 24.04 through Ubuntu's supported package path, with local socket-based administration, a dedicated application account, verified CRUD operations, private-by-default networking, an optional certificate-verified private TLS path, logical backups, restore testing, and a controlled update strategy. The key 2026 distinction is release-track discipline: Ubuntu 24.04 still packages MariaDB 10.11, while upstream MariaDB's newest LTS is 12.3. Keep routine Ubuntu patching separate from a deliberate major-version and repository migration. Continue with [Install MySQL on Ubuntu 24.04](/learn/tutorials/install-mysql-ubuntu-24-04), [Install PostgreSQL on Ubuntu 24.04](/learn/tutorials/install-postgresql-ubuntu-24-04), and [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). ## Sources - [Ubuntu 24.04 MariaDB package](https://packages.ubuntu.com/noble/database/mariadb-server) - [MariaDB — mariadb-secure-installation](https://mariadb.com/docs/server/clients-and-utilities/deployment-tools/mariadb-secure-installation) - [MariaDB — unix_socket authentication](https://mariadb.com/docs/server/reference/plugins/authentication-plugins/authentication-plugin-unix-socket) - [MariaDB — remote client access](https://mariadb.com/docs/server/server-usage/connecting/mariadb-remote-connection-guide-1) - [MariaDB — enabling TLS](https://mariadb.com/docs/server/security/encryption/data-in-transit-encryption/data-in-transit-encryption-enabling-tls-on-mariadb-server) - [MariaDB — mariadb-upgrade](https://mariadb.com/docs/server/clients-and-utilities/deployment-tools/mariadb-upgrade) - [MariaDB — upgrading between major versions](https://mariadb.com/docs/server/server-management/install-and-upgrade-mariadb/upgrading/upgrading-between-major-mariadb-versions) - [MariaDB Foundation — current releases](https://mariadb.org/mariadb/all-releases/) - Package, release, and security guidance re-verified: 2026-09-05 --- ### How to Install Redis on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-redis-ubuntu-24-04 Description: Install Redis 7.0 on Ubuntu 24.04, configure ACL users, persistence and maxmemory, secure private access, back up, and restore-test Redis safely. Redis is an in-memory data store commonly used for caches, sessions, queues, rate limiting, Pub/Sub, and short-lived application state. On Ubuntu 24.04, the simplest distro-managed installation path is Ubuntu's own `redis-server` package. As of September 5, 2026, Ubuntu Noble provides **Redis 7.0.15-1ubuntu0.24.04.4**, including current Ubuntu security fixes. Upstream Redis Open Source has moved much further ahead and released **Redis 8.10.0** in July 2026, so the package source matters when you discuss “the current Redis version.” Raff Technologies is the VM platform used by the original tutorial. The saved test note remains `Ubuntu 24.04 LTS on Raff 1 vCPU / 2 GB RAM VM; package, authentication, persistence, and memory guidance reviewed in July 2026`. This revision re-verifies package selection, ACL authentication, network exposure, persistence, backups, restore testing, memory policy, TLS, and update guidance against current Ubuntu and Redis documentation without claiming a new end-to-end machine test. This tutorial intentionally stays on Ubuntu's patched Redis 7.0 package line. Redis maintains its own APT repository for newer releases, but changing repository and major version is a separate upgrade decision, not a normal Ubuntu patch. Redis should not be exposed directly to untrusted networks. The default path here keeps port 6379 on loopback, uses named ACL users instead of relying only on legacy `requirepass`, and treats persistence and backup as separate concerns. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A tested recovery path before firewall or Redis configuration changes - A defined Redis role: disposable cache, sessions, queues, or other state - Enough RAM for the working set plus Redis/system overhead - An off-server destination if Redis data or configuration matters ## Step 1 — Verify Ubuntu 24.04 and the Redis package candidate Confirm the OS and architecture: ```bash cat /etc/os-release uname -m ``` Refresh APT metadata: ```bash sudo apt update ``` Inspect the Redis package candidate: ```bash apt-cache policy redis redis-server redis-tools ``` On current Ubuntu 24.04 repositories, the distro-managed Redis branch is 7.0. At this revision, the current Noble security/update package is `5:7.0.15-1ubuntu0.24.04.4`. Check RAM and disk headroom: ```bash free -h df -h / ``` Do not size Redis from a generic VM recommendation. The working set, key/value overhead, client buffers, persistence, replication, fork operations, and operating system all consume memory. **Verify:** Ubuntu should report 24.04, APT should show Redis 7.0.15 from Ubuntu repositories, and the VM should have enough memory/disk headroom for the chosen Redis role. ## Step 2 — Install Redis Server from Ubuntu's repository Install Redis, its CLI tools, OpenSSL, and UFW: ```bash sudo apt install -y redis-server redis-tools openssl ufw ``` Verify the installed package and binary versions: ```bash redis-server --version redis-cli --version apt-cache policy redis-server ``` The Ubuntu package revision can change as security updates are published while the upstream Redis 7.0 version string remains 7.0.15. Do not add `packages.redis.io` after installation unless you have intentionally decided to move away from Ubuntu's distro-managed release track. **Verify:** `redis-server` and `redis-cli` should be installed, and APT should show Ubuntu's repository as the installed package source. ## Step 3 — Verify the Redis service, configuration path, and listener Confirm Redis is active and enabled: ```bash systemctl is-active redis-server systemctl is-enabled redis-server sudo systemctl status redis-server --no-pager ``` Test the default local connection before enabling authentication: ```bash redis-cli PING ``` Expected result: ```text PONG ``` Inspect the service command and configuration path: ```bash systemctl cat redis-server | grep -E 'ExecStart|redis.conf' ``` Ubuntu normally uses: ```text /etc/redis/redis.conf ``` Inspect listeners: ```bash sudo ss -lntp | grep ':6379' || true ``` A normal single-VM installation should not expose Redis on the VM's public address. **Verify:** Redis should be active/enabled, `PING` should work locally before authentication is enabled, and port 6379 should not have an unexpected public listener. ## Step 4 — Back up the configuration and keep Redis local Create a timestamped configuration backup: ```bash sudo cp -a /etc/redis/redis.conf \ "/etc/redis/redis.conf.$(date -u +%Y%m%dT%H%M%SZ).backup" ``` Inspect the network settings: ```bash grep -nE '^[[:space:]]*(bind|protected-mode|port)[[:space:]]' \ /etc/redis/redis.conf ``` For a same-VM application, keep settings equivalent to: ```conf bind 127.0.0.1 -::1 protected-mode yes port 6379 ``` Do not replace the bind line with `0.0.0.0`. Redis's own security documentation recommends restricting the port to trusted clients and specifically warns against direct internet exposure. Restart after any configuration change: ```bash sudo systemctl restart redis-server systemctl is-active redis-server ``` Recheck the listener: ```bash sudo ss -lntp | grep ':6379' || true ``` **Verify:** Redis should remain bound to loopback for the default deployment, protected mode should remain enabled, and the service should restart cleanly. ## Step 5 — Configure persistent named ACL users Redis 6 and later supports Access Control Lists. Redis documentation recommends ACLs as the modern authentication model; `requirepass` is the legacy single-password method and effectively sets a password on the `default` user. Create a dedicated ACL file with the current permissive default user temporarily preserved so you can transition without locking yourself out: ```bash sudo install -o redis -g redis -m 600 /dev/null /etc/redis/users.acl echo 'user default on nopass ~* &* +@all' \ | sudo tee /etc/redis/users.acl >/dev/null sudo chown redis:redis /etc/redis/users.acl sudo chmod 600 /etc/redis/users.acl ``` Open the main configuration: ```bash sudo nano /etc/redis/redis.conf ``` Add or enable: ```conf aclfile /etc/redis/users.acl ``` Do not define the same users in both `redis.conf` and the external ACL file. Restart and confirm Redis still responds locally: ```bash sudo systemctl restart redis-server redis-cli PING ``` Generate separate administrator and application passwords: ```bash ADMIN_PASSWORD="$(openssl rand -hex 32)" APP_PASSWORD="$(openssl rand -hex 32)" printf 'Redis admin password: %s\n' "$ADMIN_PASSWORD" printf 'Redis app password: %s\n' "$APP_PASSWORD" ``` Store both values in a secrets manager before continuing. Create a full administrative user and a restricted application user. The application account is limited to keys beginning with `raffapp:` and has dangerous commands removed: ```bash redis-cli ACL SETUSER redisadmin \ reset on ">${ADMIN_PASSWORD}" '~*' '&*' +@all redis-cli ACL SETUSER raffapp \ reset on ">${APP_PASSWORD}" '~raffapp:*' \ resetchannels +@read +@write +ping -@dangerous redis-cli ACL SAVE ``` Now authenticate as the new administrator, disable the unauthenticated default user, and persist that state: ```bash export REDISCLI_AUTH="$ADMIN_PASSWORD" redis-cli --user redisadmin PING redis-cli --user redisadmin ACL SETUSER default off redis-cli --user redisadmin ACL SAVE redis-cli --user redisadmin ACL LIST ``` Unauthenticated access should now fail: ```bash unset REDISCLI_AUTH redis-cli PING ``` Expected result includes: ```text NOAUTH Authentication required ``` Clear generated values after they are safely stored: ```bash unset ADMIN_PASSWORD APP_PASSWORD ``` If an application needs Pub/Sub, grant only the required channel pattern and Pub/Sub commands instead of `allchannels` by default. **Verify:** The `default` user should be off, `redisadmin` should authenticate with administrative rights, `raffapp` should exist with a key namespace restriction, and `ACL SAVE` should persist the users in `/etc/redis/users.acl`. ## Step 6 — Verify the application ACL with key and command restrictions Read the application password without putting it on the command line: ```bash read -rsp "Redis application password: " REDISCLI_AUTH echo export REDISCLI_AUTH ``` Authenticate as the application user and create a namespaced key: ```bash redis-cli --user raffapp PING redis-cli --user raffapp SET raffapp:health verified EX 300 redis-cli --user raffapp GET raffapp:health redis-cli --user raffapp TTL raffapp:health ``` Expected results include `PONG`, `OK`, `verified`, and a positive TTL. A key outside the permitted namespace should fail: ```bash redis-cli --user raffapp SET other:health blocked ``` A dangerous administrative command should also fail: ```bash redis-cli --user raffapp FLUSHALL ``` Remove the test key: ```bash redis-cli --user raffapp DEL raffapp:health unset REDISCLI_AUTH ``` Do not replace a working ACL model with `requirepass` just because an older tutorial or client expects password-only `AUTH`. Modern clients support `AUTH username password` or Redis URLs containing a username. **Verify:** The application user should work inside `raffapp:*`, fail outside that key pattern, and be unable to run dangerous administrative commands. ## Step 7 — Configure `maxmemory` and an eviction policy for the workload Redis can continue allocating dataset memory when `maxmemory` is zero, so production cache deployments should deliberately choose a memory limit. Redis also needs RAM outside the dataset limit for the OS, allocator overhead, client buffers, persistence/replication buffers, and fork/copy-on-write activity. Inspect current memory state: ```bash free -h ``` Authenticate as the administrator: ```bash read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli --user redisadmin INFO memory | \ grep -E 'used_memory_human|maxmemory_human|maxmemory_policy|mem_not_counted_for_evict' ``` Open the configuration: ```bash sudo nano /etc/redis/redis.conf ``` For the original 2 GB tutorial VM used purely as a cache, this is an example—not a universal value: ```conf maxmemory 1gb maxmemory-policy allkeys-lru ``` Choose policy by behavior: - `allkeys-lru`: common cache starting point when any key can be evicted; - `allkeys-lfu`: useful when frequently accessed keys should survive; - `volatile-lru` / `volatile-lfu`: only keys with expirations are candidates; - `noeviction`: writes that would exceed the limit fail instead of evicting data. Restart and verify: ```bash sudo systemctl restart redis-server redis-cli --user redisadmin CONFIG GET maxmemory redis-cli --user redisadmin CONFIG GET maxmemory-policy unset REDISCLI_AUTH ``` Do not use `CONFIG SET` alone for permanent production changes unless you also persist the configuration; runtime changes disappear at restart unless written back. **Verify:** `maxmemory` should leave system/persistence headroom, the eviction policy should match the workload, and the values should survive a service restart. ## Step 8 — Choose and verify a persistence model Redis supports four broad persistence choices: RDB snapshots, AOF, RDB + AOF, or no persistence. The correct choice depends on whether Redis contains disposable cache copies or state that must survive process/server failure. A practical starting model is: | Workload | Starting persistence choice | |---|---| | Rebuildable cache | RDB or no persistence | | Sessions with application fallback | RDB with tested recovery | | Queue / important short-lived state | AOF, commonly `appendfsync everysec` | | Data treated as primary durable system of record | Re-evaluate architecture, replication, backups, and failure semantics explicitly | Inspect current persistence configuration as the administrator: ```bash read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli --user redisadmin CONFIG GET save redis-cli --user redisadmin CONFIG GET appendonly redis-cli --user redisadmin CONFIG GET appendfsync ``` If the workload requires AOF, edit `/etc/redis/redis.conf` and use: ```conf appendonly yes appendfsync everysec ``` Restart and verify: ```bash sudo systemctl restart redis-server redis-cli --user redisadmin CONFIG GET appendonly redis-cli --user redisadmin CONFIG GET appendfsync redis-cli --user redisadmin INFO persistence unset REDISCLI_AUTH ``` With `appendfsync everysec`, Redis documents that roughly up to about one second of writes can be lost in a failure. Persistence improves local recoverability but is not an off-server backup. **Verify:** Persistence settings should match the durability requirement, `INFO persistence` should report healthy RDB/AOF state, and the chosen values should survive restart. ## Step 9 — Create a recoverable RDB backup and include Redis configuration Redis 8.10 introduced a newer `BACKUP` command family, but Ubuntu 24.04's distro Redis 7.0 does not have those commands. For this tutorial's package line, create a fresh RDB snapshot and copy the completed snapshot together with the Redis configuration and ACL file. Create a protected backup directory: ```bash sudo install -d -m 700 /var/backups/redis ``` Authenticate as the administrator and inspect the RDB location: ```bash read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH REDIS_DIR="$(redis-cli --user redisadmin --raw CONFIG GET dir | tail -n 1)" RDB_FILE="$(redis-cli --user redisadmin --raw CONFIG GET dbfilename | tail -n 1)" printf 'RDB path: %s/%s\n' "$REDIS_DIR" "$RDB_FILE" ``` Trigger a background snapshot: ```bash redis-cli --user redisadmin BGSAVE ``` Wait until the background save finishes: ```bash while redis-cli --user redisadmin --raw INFO persistence \ | grep -q '^rdb_bgsave_in_progress:1'; do sleep 1 done redis-cli --user redisadmin INFO persistence | \ grep -E 'rdb_last_bgsave_status|rdb_last_save_time' ``` `rdb_last_bgsave_status` must be `ok`. Copy the completed RDB and protected configuration files: ```bash STAMP="$(date -u +%Y%m%d-%H%M%S)" sudo cp "$REDIS_DIR/$RDB_FILE" \ "/var/backups/redis/dump-${STAMP}.rdb" sudo tar -czf "/var/backups/redis/config-${STAMP}.tar.gz" \ /etc/redis/redis.conf \ /etc/redis/users.acl sudo chmod 600 \ "/var/backups/redis/dump-${STAMP}.rdb" \ "/var/backups/redis/config-${STAMP}.tar.gz" ``` Validate the RDB file with the installed Redis tool: ```bash sudo redis-check-rdb "/var/backups/redis/dump-${STAMP}.rdb" ``` Clear the credential: ```bash unset REDISCLI_AUTH ``` Copy the complete backup set off-server. Raff [Data Protection](/products/data-protection) can add VM-level recovery, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. :::cta Protect Your Redis Server Run Redis on an Ubuntu VM and keep the dataset, configuration, and ACL recovery copies outside the Redis host. ::: **Verify:** The RDB background save should report `ok`, `redis-check-rdb` should validate the copied snapshot, Redis configuration/ACL files should be included, and at least one production copy should exist off-server. ## Step 10 — Restore-test the RDB in an isolated Redis instance A backup is not proven until it has been loaded successfully. Prefer a disposable recovery VM. If you test on the same server, use a different loopback-only port and confirm it is unused first: ```bash sudo ss -lntp | grep ':6380' || true ``` Choose the RDB backup you want to test: ```bash BACKUP_RDB="$(ls -1t /var/backups/redis/dump-*.rdb | head -n 1)" RESTORE_DIR="$(mktemp -d)" cp "$BACKUP_RDB" "$RESTORE_DIR/dump.rdb" ``` Start a disposable Redis process that only listens on loopback and does not write new persistence files: ```bash redis-server \ --port 6380 \ --bind 127.0.0.1 \ --protected-mode yes \ --dir "$RESTORE_DIR" \ --dbfilename dump.rdb \ --appendonly no \ --save "" \ --daemonize yes \ --pidfile "$RESTORE_DIR/redis.pid" \ --logfile "$RESTORE_DIR/redis.log" ``` Verify the restored instance: ```bash redis-cli -p 6380 PING redis-cli -p 6380 DBSIZE redis-cli -p 6380 INFO keyspace ``` For production recovery, compare expected key counts and representative application keys rather than relying only on `PING`. Shut down and remove the disposable instance: ```bash redis-cli -p 6380 SHUTDOWN NOSAVE rm -rf "$RESTORE_DIR" ``` This temporary restore instance intentionally has no ACL because it is loopback-only and disposable. A real recovery server must restore the protected Redis configuration and ACL model before serving application traffic. **Verify:** The isolated instance should load the RDB, answer on loopback port 6380, expose the expected keyspace, shut down cleanly, and leave the production Redis process untouched. ## Step 11 — Protect Redis with UFW without risking SSH lockout Redis's own security guidance says untrusted clients should not directly reach the Redis TCP port. The bind address is the first control; the firewall is defense in depth. Before enabling or changing UFW, open a second SSH session and inspect current rules: ```bash sudo ufw status numbered ``` If UFW is already active and Redis is local-only, add a deny rule if one does not already exist: ```bash sudo ufw deny 6379/tcp ``` If UFW is inactive, do not blindly run `ufw enable` from one remote session. Follow [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), which verifies SSH access before activation. Recheck the listener and firewall: ```bash sudo ss -lntp | grep ':6379' || true sudo ufw status numbered ``` **Verify:** Port 6379 should not be reachable through the public interface, and SSH administration should remain available after any firewall change. ## Step 12 — Optionally allow one private application VM over TLS Use this only when Redis and the application run on separate VMs. Redis ACLs restrict commands/keys, but unlike MySQL-style accounts they do not restrict a user to a source IP. Enforce source-IP restrictions with the private network and firewall. Example addresses: ```text Redis private IP: 10.0.0.5 Application private IP: 10.0.0.10 ``` Use certificates issued by a CA you control. The server certificate should contain the private hostname or address the application will verify. Place the server certificate material at protected paths such as: ```text /etc/redis/tls/ca.crt /etc/redis/tls/redis.crt /etc/redis/tls/redis.key ``` Protect it: ```bash sudo chown -R root:redis /etc/redis/tls sudo chmod 750 /etc/redis/tls sudo chmod 640 /etc/redis/tls/redis.key sudo chmod 644 /etc/redis/tls/ca.crt /etc/redis/tls/redis.crt ``` Edit `/etc/redis/redis.conf`: ```conf bind 127.0.0.1 -::1 10.0.0.5 protected-mode yes # Keep local plaintext Redis on 6379; firewall it from the network. port 6379 # Private TLS listener for the application VM. tls-port 6380 tls-cert-file /etc/redis/tls/redis.crt tls-key-file /etc/redis/tls/redis.key tls-ca-cert-file /etc/redis/tls/ca.crt tls-auth-clients no ``` `tls-auth-clients no` means the application authenticates with its Redis ACL username/password while the client still verifies the Redis server certificate. If you require mutual TLS, keep client-certificate authentication enabled and provision client certificates instead. Restart and verify listeners: ```bash sudo systemctl restart redis-server systemctl is-active redis-server sudo ss -lntp | grep -E ':6379|:6380' ``` If UFW is active, allow only the application VM to the TLS listener and keep plaintext 6379 blocked from network clients: ```bash sudo ufw allow from 10.0.0.10 to 10.0.0.5 port 6380 proto tcp sudo ufw status numbered ``` Copy only the CA certificate to the application VM. Connect with the existing restricted ACL user: ```bash read -rsp "Redis application password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli \ --tls \ --cacert /path/to/ca.crt \ --host 10.0.0.5 \ --port 6380 \ --user raffapp \ PING unset REDISCLI_AUTH ``` Do not create a public UFW allow rule for 6379 or 6380. **Verify:** The private Redis address should expose the TLS listener only to the approved application source, the client should validate the CA and authenticate as `raffapp`, and public Redis access should remain blocked. ## Step 13 — Apply Ubuntu Redis patches safely and separate them from major upgrades Check for Ubuntu Redis updates: ```bash apt list --upgradable 2>/dev/null | grep -E '^redis' || true ``` Before patching Redis that contains important state: 1. trigger and validate a fresh backup; 2. copy the backup off-server; 3. review the Ubuntu security/changelog entry; 4. verify persistence health and free disk; 5. choose a maintenance window appropriate for the workload. Apply normal Ubuntu updates: ```bash sudo apt update sudo apt upgrade ``` Verify the service and package afterward: ```bash systemctl is-active redis-server redis-server --version apt-cache policy redis-server ``` Authenticate and verify state: ```bash read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli --user redisadmin PING redis-cli --user redisadmin INFO persistence | \ grep -E 'rdb_last_bgsave_status|aof_enabled|aof_last_write_status' redis-cli --user redisadmin ACL LIST unset REDISCLI_AUTH ``` Upstream Redis Open Source 8.10.0 is a different release line from Ubuntu's Redis 7.0.15 package. Redis's own APT repository can install newer releases, but moving package source and major version should be tested separately for client compatibility, ACL/config changes, persistence-file compatibility, and rollback. **Verify:** Routine Ubuntu patching should keep the intended distro package source, Redis should restart cleanly, authentication should work, and persistence should remain healthy. ## Step 14 — Run the final Redis security, memory, persistence, and recovery audit Check service and network state: ```bash echo 'Service:' systemctl is-active redis-server systemctl is-enabled redis-server echo 'Listeners:' sudo ss -lntp | grep -E ':6379|:6380' || true echo 'Firewall:' sudo ufw status numbered echo 'Package:' apt-cache policy redis-server | sed -n '1,8p' ``` Authenticate as the administrator: ```bash read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH ``` Run the Redis checks: ```bash redis-cli --user redisadmin PING redis-cli --user redisadmin ACL LIST redis-cli --user redisadmin CONFIG GET protected-mode redis-cli --user redisadmin CONFIG GET maxmemory redis-cli --user redisadmin CONFIG GET maxmemory-policy redis-cli --user redisadmin CONFIG GET appendonly redis-cli --user redisadmin INFO persistence | \ grep -E 'rdb_last_bgsave_status|aof_enabled|aof_last_write_status' redis-cli --user redisadmin INFO memory | \ grep -E 'used_memory_human|maxmemory_human|mem_not_counted_for_evict' unset REDISCLI_AUTH ``` Confirm all of the following: - Ubuntu 24.04 manages the expected Redis 7.0 package branch; - the service is active and enabled; - public Redis access is blocked; - protected mode is enabled; - the unauthenticated `default` user is disabled; - an administrative ACL user is separate from the restricted application user; - the application user is limited by key pattern and command permissions; - `maxmemory` and eviction behavior match the Redis role; - persistence matches the durability requirement; - the latest RDB backup validates with `redis-check-rdb`; - Redis configuration and ACL files are included in recovery copies; - an isolated restore test has succeeded; - any separate application VM uses an exact firewall source rule and TLS; - moving to upstream Redis 8.x is treated as a planned upgrade rather than an Ubuntu patch. **Verify:** There should be no public unauthenticated Redis path, no application account with unnecessary administrative commands, no unbounded memory plan for a production cache, and no backup that has never been restore-tested. ## Troubleshooting ### Redis does not start after editing `redis.conf` Inspect systemd and Redis logs first: ```bash sudo systemctl status redis-server --no-pager sudo journalctl -u redis-server --no-pager -n 100 ``` A quick memory-test invocation also forces Redis to parse the configuration before the test, which can expose many syntax/configuration errors without binding the normal port: ```bash sudo redis-server /etc/redis/redis.conf --test-memory 2 ``` This is not a complete substitute for a real service restart and end-to-end verification. Restore the timestamped config backup if the failure began after an edit. ### `NOAUTH Authentication required` appears Authentication is enabled. Use the correct named ACL user: ```bash read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli --user redisadmin PING unset REDISCLI_AUTH ``` ### The application receives `NOPERM` Inspect the application ACL as the administrator: ```bash redis-cli --user redisadmin ACL GETUSER raffapp ``` Grant only the key patterns, channels, and command categories the application actually needs. Do not solve ACL errors by giving an application `+@all`. ### Redis uses more memory than expected Check dataset memory, RSS, maxmemory, and non-eviction buffers: ```bash redis-cli --user redisadmin INFO memory redis-cli --user redisadmin CONFIG GET maxmemory redis-cli --user redisadmin CONFIG GET maxmemory-policy redis-cli --user redisadmin --bigkeys ``` `maxmemory` limits the dataset used for eviction decisions; it is not a guarantee that total process RSS can never exceed that value. ### Redis cannot create an RDB snapshot Inspect persistence state, disk space, permissions, and logs: ```bash df -h / redis-cli --user redisadmin INFO persistence sudo journalctl -u redis-server --no-pager -n 100 ``` Do not assume an AOF file removes the need for backup and recovery testing. ### TLS connections fail Check the private listener, certificate paths, key permissions, and service log: ```bash sudo ss -lntp | grep ':6380' || true sudo ls -l /etc/redis/tls sudo journalctl -u redis-server --no-pager -n 100 ``` Verify that the server certificate is issued by the CA copied to the application VM and that its identity matches the hostname/address the client uses. ## Conclusion You now have Redis 7.0 on Ubuntu 24.04 through Ubuntu's distro-managed package path, with named ACL users, a restricted application namespace, private-by-default networking, deliberate memory and eviction settings, workload-appropriate persistence, validated RDB backups, isolated restore testing, and an optional private TLS path. The most important 2026 distinction is release-track discipline: Ubuntu 24.04 currently maintains Redis 7.0.15 with security patches, while upstream Redis Open Source has reached 8.10.0. Keep normal Ubuntu security updates separate from a deliberate upstream repository or major-version migration. Continue with [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), [Install MySQL on Ubuntu 24.04](/learn/tutorials/install-mysql-ubuntu-24-04), and [Install MariaDB on Ubuntu 24.04](/learn/tutorials/install-mariadb-ubuntu-24-04). ## Sources - [Ubuntu 24.04 redis-server package](https://packages.ubuntu.com/noble/misc/redis-server) - [Ubuntu Redis security update USN-8169-1](https://ubuntu.com/security/notices/USN-8169-1) - [Redis Open Source release notes](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/release-notes/redisce/) - [Redis Open Source APT installation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/apt/) - [Redis security](https://redis.io/docs/latest/operate/oss_and_stack/management/security/) - [Redis ACL](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/) - [Redis TLS](https://redis.io/docs/latest/operate/oss_and_stack/management/security/encryption/) - [Redis persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/) - [Redis key eviction](https://redis.io/docs/latest/develop/reference/eviction/) - Package and security guidance re-verified: 2026-09-05 --- ### How to Install MongoDB on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-mongodb-ubuntu-24-04 Description: Install MongoDB 8.3 on Ubuntu 24.04, enable RBAC, secure port 27017, add private TLS, back up with mongodump, and restore-test safely. MongoDB is a document database that stores records as BSON documents and is commonly used for APIs, catalogs, content-heavy applications, event data, and workloads that benefit from flexible document structures. On Ubuntu 24.04, MongoDB Inc. provides official Community Edition packages through its own APT repository rather than Ubuntu's default repository. As of September 5, 2026, **MongoDB 8.3 is the current self-managed minor release** in MongoDB's documentation. MongoDB 8.0 remains a major release line, but this tutorial now follows the current 8.3 Community repository for a new Ubuntu 24.04 installation. MongoDB explicitly separates normal patch upgrades from major/minor release upgrades, so an existing 8.0 deployment should use the documented 8.0 → 8.3 upgrade procedure instead of simply replacing its repository file. citeturn127307view0turn137205search0 Raff Technologies is the VM platform used by the original tutorial. The saved test note remains `Ubuntu 24.04 LTS on Raff 2 vCPU / 4 GB RAM VM; installation and security guidance reviewed in July 2026`. This revision re-verifies the package path, localhost authentication bootstrap, RBAC, network exposure, TLS, logical backup/restore, and upgrade guidance against current MongoDB documentation without claiming a new end-to-end machine test. The default design keeps MongoDB on loopback, enables authorization before the first user is created, and uses MongoDB's localhost exception only for the initial administrator bootstrap. Port `27017` is never opened publicly. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A 64-bit x86_64 system or a MongoDB-supported ARM64 platform - A tested recovery path before database or firewall changes - Enough disk for the live dataset plus backup growth - An off-server destination for production backup copies ## Step 1 — Verify Ubuntu 24.04, architecture, and conflicting packages Confirm the operating system and architecture: ```bash . /etc/os-release printf '%s | codename=%s | arch=%s\n' \ "$PRETTY_NAME" "$VERSION_CODENAME" "$(dpkg --print-architecture)" ``` MongoDB Community supports Ubuntu 24.04 on x86_64 and supported ARM64 platforms. citeturn137205search4 Refresh APT metadata and install repository prerequisites: ```bash sudo apt update sudo apt install -y gnupg curl ca-certificates ufw ``` Check for old or conflicting MongoDB packages before adding the official repository: ```bash dpkg -l | grep -E '^ii[[:space:]]+(mongodb|mongodb-server|mongodb-server-core|mongodb-org)' || true ``` The official MongoDB package family is `mongodb-org`. MongoDB's troubleshooting documentation warns that Ubuntu-provided `mongodb`/`mongodb-server*` packages can conflict with the official packages. Do not remove an existing database package until its data, configuration, version, and recovery path are understood. citeturn160945search0 **Verify:** The host should report Ubuntu 24.04/Noble, use a supported architecture, and have no unexplained conflicting MongoDB package or existing data directory that could be overwritten. ## Step 2 — Add the official MongoDB 8.3 Community APT repository Import MongoDB's current release signing key: ```bash curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \ sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \ --dearmor ``` Create the Ubuntu 24.04 Noble Community repository for MongoDB 8.3: ```bash echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.3 multiverse" | \ sudo tee /etc/apt/sources.list.d/mongodb-org-8.3.list >/dev/null ``` Refresh APT and inspect the package source: ```bash sudo apt update apt-cache policy mongodb-org | sed -n '1,20p' ``` MongoDB's current Community troubleshooting documentation references the `mongodb-org/8.3` repository path, while the current manual identifies 8.3 as the latest minor release. citeturn160945search0turn127307view0 Do not hard-code a patch version in deployment automation unless you intentionally pin it. Let `apt-cache policy` show the current candidate available from the 8.3 repository. **Verify:** `apt-cache policy mongodb-org` should show a non-empty candidate from `repo.mongodb.org` under the Noble `mongodb-org/8.3` path. ## Step 3 — Install MongoDB Community Edition and verify package ownership Install the official MongoDB Community metapackage: ```bash sudo apt install -y mongodb-org ``` Verify the installed components: ```bash mongod --version | sed -n '1,8p' mongosh --version mongodump --version | sed -n '1,5p' mongorestore --version | sed -n '1,5p' ``` Confirm package origin: ```bash apt-cache policy mongodb-org mongodb-org-server mongodb-mongosh mongodb-database-tools | \ sed -n '1,40p' ``` MongoDB's package-manager guidance recommends using the package manager for maintenance because it installs dependencies, configuration, and service integration consistently. citeturn137205search11 **Verify:** `mongod` should report an 8.3-series server, `mongosh` and Database Tools should be installed, and package policy should point to MongoDB's official repository. ## Step 4 — Start MongoDB and verify the local listener Start MongoDB and enable it at boot: ```bash sudo systemctl enable --now mongod ``` Verify service state: ```bash systemctl is-active mongod systemctl is-enabled mongod sudo systemctl status mongod --no-pager ``` Before authorization is enabled, confirm the fresh server responds locally: ```bash mongosh --quiet --eval 'db.runCommand({ ping: 1 })' ``` Inspect the network listener: ```bash sudo ss -lntp | grep ':27017' || true sudo grep -nE '^[[:space:]]*(port|bindIp):' /etc/mongod.conf ``` MongoDB binds to localhost by default. Keep the instance on loopback while bootstrapping authentication. citeturn453062search2 **Verify:** `mongod` should be active and enabled, local `ping` should return `{ ok: 1 }`, and the service should not listen on a public interface. ## Step 5 — Enable authorization while MongoDB is still local-only Back up the configuration before editing it: ```bash sudo cp -a /etc/mongod.conf \ "/etc/mongod.conf.$(date -u +%Y%m%dT%H%M%SZ).backup" ``` Open the configuration: ```bash sudo nano /etc/mongod.conf ``` Keep the local bind and enable authorization: ```yaml net: port: 27017 bindIp: 127.0.0.1 security: authorization: enabled ``` MongoDB documents `security.authorization: enabled` as the setting that turns on role-based access control. citeturn741727search1 Restart MongoDB: ```bash sudo systemctl restart mongod systemctl is-active mongod ``` At this moment there are no users, so MongoDB's **localhost exception** allows a client connected over localhost to create the first user. That exception exists only while there are no users or roles. citeturn453062search0 **Verify:** MongoDB should restart successfully with authorization enabled, remain bound to `127.0.0.1`, and still have no user accounts before the next step. ## Step 6 — Create the first administrator through the localhost exception Generate a strong administrator password and store it securely: ```bash MONGO_ADMIN_PASSWORD="$(openssl rand -hex 32)" printf 'Store this MongoDB admin password securely: %s\n' "$MONGO_ADMIN_PASSWORD" export MONGO_ADMIN_PASSWORD ``` Use the localhost exception to create the first user in the `admin` database: ```bash mongosh --quiet --host 127.0.0.1 --eval ' const adminDb = db.getSiblingDB("admin"); adminDb.createUser({ user: "raffadmin", pwd: process.env.MONGO_ADMIN_PASSWORD, roles: [ { role: "root", db: "admin" } ] }); printjson(adminDb.getUser("raffadmin")); ' ``` Creating the first user closes the localhost exception. MongoDB's documentation requires that this first user have enough privilege to create and manage subsequent users. citeturn453062search0turn453062search1 Remove the password from the shell variable after it has been stored: ```bash unset MONGO_ADMIN_PASSWORD ``` Confirm unauthenticated administrative access is now rejected: ```bash mongosh --quiet --host 127.0.0.1 \ --eval 'db.getSiblingDB("admin").getUsers()' ``` Then authenticate as the administrator; `--password` without a value prompts securely: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval 'printjson(db.runCommand({ connectionStatus: 1 }).authInfo.authenticatedUsers)' ``` **Verify:** Unauthenticated user-management commands should fail, while `raffadmin` should authenticate successfully against the `admin` database. ## Step 7 — Create a database-scoped application user Generate a separate application password: ```bash MONGO_APP_PASSWORD="$(openssl rand -hex 32)" printf 'Store this MongoDB application password securely: %s\n' "$MONGO_APP_PASSWORD" export MONGO_APP_PASSWORD ``` Create `raffappuser` in the application database with only `readWrite` on that database: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval ' const appDb = db.getSiblingDB("raffapp"); appDb.createUser({ user: "raffappuser", pwd: process.env.MONGO_APP_PASSWORD, roles: [ { role: "readWrite", db: "raffapp" } ] }); printjson(appDb.getUser("raffappuser")); ' ``` Remove the password from the environment after storing it: ```bash unset MONGO_APP_PASSWORD ``` Do not put the administrator credential in application configuration. The application should authenticate to the database where its user was created (`raffapp`). **Verify:** `raffappuser` should exist in the `raffapp` database with `readWrite` on `raffapp` only and no administrative role. ## Step 8 — Complete an authenticated CRUD test Connect as the application user and run a disposable CRUD test: ```bash mongosh "mongodb://127.0.0.1:27017/raffapp" \ --quiet \ --username raffappuser \ --authenticationDatabase raffapp \ --password \ --eval ' const c = db.getSiblingDB("raffapp").tutorial_check; c.deleteMany({ name: "raff-mongodb-test" }); const inserted = c.insertOne({ name: "raff-mongodb-test", status: "created", createdAt: new Date() }); const created = c.findOne({ name: "raff-mongodb-test" }); const updated = c.updateOne( { name: "raff-mongodb-test" }, { $set: { status: "verified" } } ); const verified = c.findOne({ name: "raff-mongodb-test" }); const deleted = c.deleteOne({ name: "raff-mongodb-test" }); printjson({ insertedId: inserted.insertedId, createdStatus: created.status, modifiedCount: updated.modifiedCount, verifiedStatus: verified.status, deletedCount: deleted.deletedCount }); ' ``` Expected fields include: ```text createdStatus: 'created' modifiedCount: 1 verifiedStatus: 'verified' deletedCount: 1 ``` **Verify:** The non-admin application user should authenticate and complete create/read/update/delete operations only within its assigned database. ## Step 9 — Keep port 27017 private and make firewall changes safely Confirm the configured bind and active listener: ```bash sudo grep -nE '^[[:space:]]*(port|bindIp):' /etc/mongod.conf sudo ss -lntp | grep ':27017' || true ``` For a same-VM application, keep: ```yaml net: port: 27017 bindIp: 127.0.0.1 ``` Do not change the bind address to `0.0.0.0` to make Compass or another client convenient. Before changing UFW from a remote shell, open a second SSH session and inspect current rules: ```bash sudo ufw status numbered ``` If UFW is already active, add a deny rule if necessary: ```bash sudo ufw deny 27017/tcp ``` If UFW is inactive, follow [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) instead of blindly enabling it from a single SSH session. **Verify:** MongoDB should listen only on loopback for the default deployment, no public `27017` allow rule should exist, and SSH access should remain available. ## Step 10 — Create a logical backup with `mongodump` MongoDB Database Tools provide `mongodump` and `mongorestore` for logical BSON backups. Current Database Tools documentation supports compressed archives with `--archive` and `--gzip`. citeturn741727search3 For a **standalone** server, `mongodump` does not create a transactionally consistent multi-collection point-in-time snapshot while application writes continue. For important standalone data, quiesce application writes or take the backup during a maintenance window. Replica sets can use oplog-aware backup strategies. Create a protected backup directory: ```bash sudo install -d -m 700 /var/backups/mongodb STAMP="$(date -u +%Y%m%d-%H%M%S)" ``` Create a compressed archive of the application database. Omitting a password value keeps it out of command history/process arguments and lets the tool prompt: ```bash mongodump \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --db raffapp \ --archive="/var/backups/mongodb/raffapp-${STAMP}.archive.gz" \ --gzip ``` Restrict the file and verify that it exists: ```bash sudo chmod 600 "/var/backups/mongodb/raffapp-${STAMP}.archive.gz" ls -lh "/var/backups/mongodb/raffapp-${STAMP}.archive.gz" ``` Back up the server configuration separately: ```bash sudo cp /etc/mongod.conf \ "/var/backups/mongodb/mongod.conf-${STAMP}" sudo chmod 600 "/var/backups/mongodb/mongod.conf-${STAMP}" ``` Copy production backup sets off-server. Raff [Data Protection](/products/data-protection) can add VM-level recovery, while [Object Storage](/products/object-storage) can be used by S3-compatible backup tooling. :::cta Protect Your MongoDB Server Run MongoDB on an Ubuntu VM and keep database-aware backups plus configuration copies outside the database host. ::: **Verify:** The archive and configuration backup should exist with restricted permissions, application writes should have been controlled appropriately for a standalone consistency requirement, and a production copy should exist off-server. ## Step 11 — Restore-test the backup into an isolated namespace Do not prove a backup by overwriting `raffapp`. Select the latest archive: ```bash LATEST_BACKUP="$(ls -1t /var/backups/mongodb/raffapp-*.archive.gz | head -n 1)" printf '%s\n' "$LATEST_BACKUP" ``` Restore the `raffapp.*` namespace into a disposable `raffapp_restore_test.*` namespace: ```bash mongorestore \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --archive="$LATEST_BACKUP" \ --gzip \ --nsFrom='raffapp.*' \ --nsTo='raffapp_restore_test.*' ``` MongoDB documents namespace remapping with `--nsFrom` and `--nsTo`, and current `mongorestore` supports compressed archives created by `mongodump`. citeturn741727search0turn741727search4 Inspect the restored collections: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval ' const restoreDb = db.getSiblingDB("raffapp_restore_test"); printjson(restoreDb.getCollectionNames()); ' ``` For production recovery rehearsals, verify representative documents, indexes, and application-level invariants. Remove the disposable restore database: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval 'printjson(db.getSiblingDB("raffapp_restore_test").dropDatabase())' ``` **Verify:** The archive should restore into the renamed test namespace, expected collections/documents should be readable, and the original `raffapp` database should remain untouched. ## Step 12 — Optionally allow one private application VM with TLS Use this only when the application and MongoDB run on separate private-network VMs. Authorization alone does not encrypt traffic. Example network design: ```text MongoDB private IP: 10.0.0.5 Application private IP: 10.0.0.10 Private DNS name in certificate SAN: mongo.internal.example ``` Use a CA you control to issue a MongoDB server certificate. Combine the server certificate and its private key into a PEM file that `mongod` can read, and copy the CA certificate separately: ```text /etc/mongodb/tls/server.pem /etc/mongodb/tls/ca.pem ``` Protect the files: ```bash sudo chown -R root:mongodb /etc/mongodb/tls sudo chmod 750 /etc/mongodb/tls sudo chmod 640 /etc/mongodb/tls/server.pem sudo chmod 644 /etc/mongodb/tls/ca.pem ``` Edit `/etc/mongod.conf`: ```yaml net: port: 27017 bindIp: 127.0.0.1,10.0.0.5 tls: mode: requireTLS certificateKeyFile: /etc/mongodb/tls/server.pem CAFile: /etc/mongodb/tls/ca.pem security: authorization: enabled ``` `net.tls.mode: requireTLS` makes MongoDB accept only TLS-encrypted network connections. citeturn741727search1 Restart and verify the private listener: ```bash sudo systemctl restart mongod systemctl is-active mongod sudo ss -lntp | grep ':27017' ``` If UFW is active, allow only the application VM's exact private source address: ```bash sudo ufw allow from 10.0.0.10 to 10.0.0.5 port 27017 proto tcp sudo ufw status numbered ``` Copy only the CA certificate to the application VM. Test with the private DNS name that matches the server certificate: ```bash mongosh "mongodb://mongo.internal.example:27017/raffapp" \ --tls \ --tlsCAFile /path/to/ca.pem \ --username raffappuser \ --authenticationDatabase raffapp \ --password \ --eval 'db.runCommand({ ping: 1 })' ``` Do not use `--tlsAllowInvalidCertificates` or `--tlsAllowInvalidHostnames` as a production shortcut. After enabling `requireTLS`, local administrative commands must also use TLS and a hostname/address that can be validated by the certificate, or use a correctly issued certificate that covers the local administrative name. **Verify:** MongoDB should listen only on loopback plus the intended private interface, UFW should allow only the application VM, and the client should connect with certificate validation rather than TLS-bypass flags. ## Step 13 — Apply patch updates and treat 8.0 → 8.3 as a release upgrade For the installed 8.3 repository, inspect pending MongoDB updates: ```bash apt list --upgradable 2>/dev/null | grep -E '^mongodb-' || true ``` Before patching an important deployment: 1. create a fresh logical backup; 2. verify an off-server copy; 3. review MongoDB patch release notes; 4. check disk headroom and service health; 5. use an appropriate maintenance window. Apply normal package updates within the configured 8.3 repository: ```bash sudo apt update sudo apt upgrade ``` Verify afterward: ```bash systemctl is-active mongod mongod --version | sed -n '1,8p' apt-cache policy mongodb-org | sed -n '1,14p' ``` MongoDB's installation guidance says package-manager patch updates are normal, but major and minor release changes must follow the corresponding upgrade procedure. citeturn137205search11 For an existing 8.0 deployment, do not silently replace `mongodb-org/8.0` with `mongodb-org/8.3` and call that a patch. MongoDB's current upgrade documentation requires reviewing the 8.0 → 8.3 path and Feature Compatibility Version (FCV). citeturn137205search0turn137205search5 Check the current FCV as an authenticated administrator: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval 'printjson(db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 }))' ``` After a release upgrade, MongoDB recommends a burn-in period before enabling backwards-incompatible features through a higher FCV because doing so can complicate downgrade. citeturn137205search7 **Verify:** Patch updates should remain inside the intended repository line, `mongod` should restart cleanly, and any 8.0 → 8.3 change should have a documented upgrade/FCV/rollback plan rather than an ad-hoc repo edit. ## Step 14 — Run the final MongoDB security and recovery audit Check package, service, listener, and firewall state: ```bash echo 'Package:' apt-cache policy mongodb-org | sed -n '1,14p' echo 'Service:' systemctl is-active mongod systemctl is-enabled mongod echo 'Listener:' sudo ss -lntp | grep ':27017' || true echo 'Firewall:' sudo ufw status numbered ``` Check authorization and authenticated users: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval ' printjson({ admin: db.getSiblingDB("admin").getUser("raffadmin"), app: db.getSiblingDB("raffapp").getUser("raffappuser"), fcv: db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 }) }); ' ``` If Step 12 enabled `requireTLS`, run the same checks with the appropriate `--tls`, `--tlsCAFile`, and certificate-valid hostname. Confirm all of the following: - MongoDB comes from the intended official `mongodb-org/8.3` repository; - `mongod` is active and enabled; - authorization is enabled; - the localhost exception has closed after first-user creation; - the administrator and application accounts are separate; - the application user is scoped to `raffapp`; - public `27017` access is blocked; - any private remote connection uses exact source-IP filtering and validated TLS; - a logical backup exists off-server; - a namespace-remapped restore test has succeeded; - normal patch updates stay within the configured release line; - release upgrades follow MongoDB's documented version/FCV path. **Verify:** There should be no public unauthenticated MongoDB path, no application use of the root administrator, no TLS verification bypass, and no backup or release-upgrade plan that has never been tested. ## Troubleshooting ### `mongodb-org` has no installation candidate Check the release file and repository: ```bash . /etc/os-release echo "$VERSION_CODENAME" cat /etc/apt/sources.list.d/mongodb-org-8.3.list sudo apt update apt-cache policy mongodb-org ``` Expected signals include `noble`, `repo.mongodb.org`, and a non-empty candidate. ### `mongod` does not start Inspect systemd and MongoDB's log: ```bash sudo systemctl status mongod --no-pager sudo journalctl -u mongod --no-pager -n 100 sudo tail -n 100 /var/log/mongodb/mongod.log ``` If the failure followed a configuration edit, compare against the timestamped `/etc/mongod.conf.*.backup` file before changing data files. ### Authentication fails after the first user is created The localhost exception closes immediately after the first user or role is created. Authenticate with the database where the user was created: ```bash mongosh --quiet \ --host 127.0.0.1 \ --username raffadmin \ --authenticationDatabase admin \ --password \ --eval 'printjson(db.runCommand({ connectionStatus: 1 }).authInfo)' ``` For `raffappuser`, use `--authenticationDatabase raffapp`. ### MongoDB listens on a public interface Restore a local-only network configuration: ```yaml net: port: 27017 bindIp: 127.0.0.1 ``` Restart and verify: ```bash sudo systemctl restart mongod sudo ss -lntp | grep ':27017' ``` Do not rely on authorization alone to protect a public database listener. ### `mongodump` succeeds but the backup may be inconsistent On a standalone server, coordinate a maintenance window or pause application writes when a cross-collection consistent logical backup matters. For higher availability and point-in-time recovery requirements, use a replica-set-aware backup design rather than treating a live standalone dump as a transactional snapshot. ### `mongorestore` asks to overwrite production data Stop and verify `--nsFrom`/`--nsTo`. A recovery rehearsal should target `raffapp_restore_test.*`, not `raffapp.*`. Avoid `--drop` against production during a backup test. ### TLS connections fail after enabling `requireTLS` Check the certificate/key permissions, certificate SAN, listener, and logs: ```bash sudo ls -l /etc/mongodb/tls sudo ss -lntp | grep ':27017' sudo journalctl -u mongod --no-pager -n 100 ``` Use the hostname represented in the server certificate and the correct CA file. Do not bypass validation to hide a certificate-name or trust-chain problem. ## Conclusion You now have MongoDB 8.3 Community Edition on Ubuntu 24.04 from MongoDB's official repository, authorization enabled before first-user creation, separate administrator and application identities, authenticated CRUD verification, private-by-default networking, logical backup and isolated restore testing, and an optional validated-TLS path for a separate application VM. The key 2026 maintenance rule is to distinguish patch updates from release upgrades. Routine APT updates inside the configured 8.3 repository are not the same operation as moving an existing 8.0 deployment to 8.3; release upgrades require MongoDB's documented version and FCV procedure. citeturn137205search11turn137205search0 Continue with [Install PostgreSQL on Ubuntu 24.04](/learn/tutorials/install-postgresql-ubuntu-24-04), [Install MySQL on Ubuntu 24.04](/learn/tutorials/install-mysql-ubuntu-24-04), and [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). ## Sources - [MongoDB Community installation](https://www.mongodb.com/docs/manual/administration/install-community/) - [MongoDB Community Ubuntu troubleshooting](https://www.mongodb.com/docs/manual/reference/installation-ubuntu-community-troubleshooting/) - [MongoDB 8.0 Ubuntu installation](https://www.mongodb.com/docs/v8.0/tutorial/install-mongodb-on-ubuntu/) - [MongoDB localhost exception](https://www.mongodb.com/docs/manual/core/localhost-exception/) - [MongoDB SCRAM authentication](https://www.mongodb.com/docs/manual/tutorial/configure-scram-client-authentication/) - [MongoDB configuration options](https://www.mongodb.com/docs/manual/reference/configuration-options/) - [MongoDB 8.0 to 8.3 upgrade](https://www.mongodb.com/docs/manual/release-notes/8.3-upgrade-from-8.0/) - [mongodump examples](https://www.mongodb.com/docs/database-tools/mongodump/mongodump-examples/) - [mongorestore](https://www.mongodb.com/docs/database-tools/mongorestore/) - Package, security, backup, and upgrade guidance re-verified: 2026-09-05 --- ### Sync Files to Raff Object Storage with rclone (Step-by-Step) URL: https://rafftechnologies.com/learn/tutorials/sync-files-raff-object-storage-rclone Description: Use rclone with Raff S3-compatible Object Storage on Ubuntu 24.04. Configure the endpoint, copy and sync safely, verify data, restore-test, encrypt, and automate backups. Raff Object Storage exposes an S3-compatible API, so rclone can use its S3 backend to copy, sync, verify, restore, and automate file transfers against `https://s3.raffusercloud.com`. This tutorial keeps Raff's current compatibility limits in mind: standard object operations, multipart uploads, SigV4, bucket ACLs/policies, and common S3 tooling are supported, while object versioning, lifecycle rules, Object Lock, cross-region replication, and static website hosting are not currently supported. Raff Technologies uses `us-east` as the product-region label, but S3-compatible clients use **`us-east-1` as the signing region**. Those are not interchangeable UI labels. For rclone, use `provider = Other`, endpoint `https://s3.raffusercloud.com`, signing region `us-east-1`, and virtual-hosted-style requests with `force_path_style = false`. This tutorial also separates **file mirroring** from **backup history**. `rclone sync` makes the destination match the source and can delete destination objects. Because Raff Object Storage does not currently provide object versioning, a destructive sync is not a complete backup strategy. Use `copy` to immutable/timestamped backup artifacts when you need historical recovery points. The saved test note remains `Ubuntu 24.04 LTS on Raff 1 vCPU / 2 GB RAM VM`. This revision re-verifies rclone installation, S3 configuration, integrity checking, multipart behavior, sync safety, restore testing, optional client-side encryption, and systemd automation against current rclone documentation and Raff's current Object Storage behavior without claiming a new end-to-end machine test. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A Raff Object Storage bucket - A bucket-scoped read-write access key where possible - The bucket name, access key ID, and secret key stored securely - Enough local space for any restore test you plan to run ## Step 1 — Check the Ubuntu package and current rclone release Inspect the Ubuntu package candidate first: ```bash sudo apt update apt-cache policy rclone ``` Ubuntu 24.04 currently carries the `1.60.1` branch with Ubuntu security/maintenance patches, while the current upstream stable rclone release is newer. For an S3 workflow where current backend fixes and current commands matter, this tutorial uses rclone's official stable installer rather than the older distro feature level. Check whether rclone is already installed: ```bash command -v rclone || true rclone version 2>/dev/null || true ``` If your organization standardizes on Ubuntu packages, the distro package can still perform basic S3 copy/sync operations. Just do not assume an Ubuntu package version exposes every command documented by current rclone. **Verify:** You should know whether the machine already has rclone, which version it runs, and whether you intend to stay on Ubuntu's older package or use current upstream stable. ## Step 2 — Install the current stable rclone release Download the official installer to a local file instead of piping an unseen script directly into a privileged shell: ```bash curl -fsSLo /tmp/rclone-install.sh https://rclone.org/install.sh ``` Review the script before running it: ```bash less /tmp/rclone-install.sh ``` Install the current stable release: ```bash sudo bash /tmp/rclone-install.sh rm -f /tmp/rclone-install.sh ``` Verify the installed version: ```bash rclone version ``` The stable release page should match the major/minor version reported by the binary. **Verify:** `rclone version` should run successfully and report the current stable branch you intentionally installed. ## Step 3 — Create a protected rclone configuration file Because the tutorial later uses systemd, keep one explicit root-owned config path: ```bash sudo install -d -m 700 /etc/rclone sudo touch /etc/rclone/raff-rclone.conf sudo chmod 600 /etc/rclone/raff-rclone.conf ``` Start rclone's interactive configurator: ```bash sudo rclone config --config /etc/rclone/raff-rclone.conf ``` Create a new remote named `raffs3` with these values: ```text Storage type: s3 Provider: Other Use environment credentials: false Access key ID: YOUR_RAFF_ACCESS_KEY Secret access key: YOUR_RAFF_SECRET_KEY Region: us-east-1 Endpoint: https://s3.raffusercloud.com Location constraint: leave empty ACL: private Advanced config: yes force_path_style: false ``` Raff supports virtual-hosted-style S3 URLs, so `force_path_style = false` is intentional. Use bucket names without periods for the cleanest HTTPS virtual-host compatibility. Do not print the full config with `rclone config show`; that command can expose sensitive values. Verify only the remote name: ```bash sudo rclone listremotes --config /etc/rclone/raff-rclone.conf ``` Expected output includes: ```text raffs3: ``` If your installed rclone supports it, inspect a redacted view: ```bash sudo rclone config redacted raffs3 \ --config /etc/rclone/raff-rclone.conf ``` Double-check even redacted output before pasting it into support tickets. **Verify:** `/etc/rclone/raff-rclone.conf` should be mode `600`, `raffs3:` should exist, the endpoint should be Raff's HTTPS endpoint, region should be `us-east-1`, and `force_path_style` should be `false`. ## Step 4 — Test the existing bucket and scoped permissions Set the bucket name for this shell session: ```bash BUCKET="YOUR_BUCKET_NAME" ``` List that bucket directly: ```bash sudo rclone lsf "raffs3:${BUCKET}" \ --config /etc/rclone/raff-rclone.conf \ --max-depth 1 ``` An empty bucket can produce no object lines while still returning successfully. Do not treat a failed global bucket listing as an authentication failure if your key is intentionally bucket-scoped. Test the intended bucket path instead. Create a harmless prefix directory marker only if you need a write test: ```bash sudo rclone mkdir "raffs3:${BUCKET}/rclone-tutorial" \ --config /etc/rclone/raff-rclone.conf ``` **Verify:** The bucket-specific command should complete without signature errors. Permission-denied responses should only occur for operations the scoped key is intentionally not allowed to perform. ## Step 5 — Upload and download one file before using sync Create a small local test file: ```bash mkdir -p ~/raff-rclone-demo printf 'Raff Object Storage rclone verification\n' \ > ~/raff-rclone-demo/verify.txt ``` Upload it with `copyto` so the destination key is explicit: ```bash sudo rclone copyto \ ~/raff-rclone-demo/verify.txt \ "raffs3:${BUCKET}/rclone-tutorial/verify.txt" \ --config /etc/rclone/raff-rclone.conf \ --progress ``` List the object: ```bash sudo rclone lsl "raffs3:${BUCKET}/rclone-tutorial/verify.txt" \ --config /etc/rclone/raff-rclone.conf ``` Download it to a different local file: ```bash sudo rclone copyto \ "raffs3:${BUCKET}/rclone-tutorial/verify.txt" \ ~/raff-rclone-demo/verify-restored.txt \ --config /etc/rclone/raff-rclone.conf ``` Compare the files: ```bash cmp ~/raff-rclone-demo/verify.txt \ ~/raff-rclone-demo/verify-restored.txt \ && echo 'Upload/download verification passed' ``` **Verify:** The uploaded object should be listed, the restored file should download successfully, and `cmp` should report `Upload/download verification passed`. ## Step 6 — Use `rclone check` for integrity verification Rclone's S3 backend validates uploads with HTTP/S3 checksums and object metadata where available. For an additional comparison between local source and remote destination, use `rclone check`: ```bash sudo rclone check \ ~/raff-rclone-demo \ "raffs3:${BUCKET}/rclone-tutorial" \ --config /etc/rclone/raff-rclone.conf \ --one-way ``` The `--one-way` flag requires each local source object to match a remote object but ignores extra objects already present remotely. S3 ETags are not always plain MD5 hashes, especially for multipart uploads or objects written by other tools. If you need a full content verification independent of remote hash metadata, use: ```bash sudo rclone check \ ~/raff-rclone-demo \ "raffs3:${BUCKET}/rclone-tutorial" \ --config /etc/rclone/raff-rclone.conf \ --one-way \ --download ``` `--download` reads object data and can consume network/egress, so use it deliberately on large datasets. **Verify:** A normal `rclone check` should report no differences for files uploaded by this workflow; a targeted `--download` check should also complete without mismatch for the test data. ## Step 7 — Understand multipart uploads before tuning performance Rclone automatically uses multipart upload above its S3 upload cutoff. Multipart is required for large S3 objects and is already supported by Raff Object Storage. Do not blindly increase concurrency. Multipart memory consumption grows approximately with: ```text transfers × s3-upload-concurrency × s3-chunk-size ``` Inspect current S3 defaults supported by your installed rclone: ```bash rclone help backend s3 | \ grep -E 'upload-cutoff|chunk-size|upload-concurrency' -A2 ``` For most backup/file-transfer jobs, start with rclone defaults. Increase `--s3-upload-concurrency` or `--s3-chunk-size` only after measuring a large-file workload and checking memory headroom. Do not set `--s3-disable-checksum` or `--s3-no-head` just to make uploads appear faster; those options reduce integrity verification. **Verify:** The workflow should use default multipart/checksum behavior unless you have measured evidence and enough RAM to justify tuning it. ## Step 8 — Use `copy` for non-destructive uploads Create a small directory tree: ```bash mkdir -p ~/raff-rclone-demo/assets ~/raff-rclone-demo/logs printf 'asset\n' > ~/raff-rclone-demo/assets/app.txt printf 'log line\n' > ~/raff-rclone-demo/logs/app.log ``` Use `copy` when destination-only objects must not be deleted: ```bash sudo rclone copy \ ~/raff-rclone-demo \ "raffs3:${BUCKET}/copy-demo" \ --config /etc/rclone/raff-rclone.conf \ --progress ``` List the result: ```bash sudo rclone lsf "raffs3:${BUCKET}/copy-demo" \ --config /etc/rclone/raff-rclone.conf \ --recursive ``` `copy` uploads new/changed source files but does not remove extra destination objects. That makes it the safer default for one-way upload workflows. **Verify:** All source files should appear under `copy-demo`, and an unrelated destination-only object would remain untouched. ## Step 9 — Preview `sync` and cap destructive deletes `rclone sync` makes the destination match the source, including deleting destination objects that are absent from the source. Rclone's own documentation recommends testing destructive syncs with `--dry-run` or interactive mode first. Create a dedicated mirror source: ```bash mkdir -p ~/raff-rclone-mirror printf 'one\n' > ~/raff-rclone-mirror/one.txt printf 'two\n' > ~/raff-rclone-mirror/two.txt ``` Preview the first sync: ```bash sudo rclone sync \ ~/raff-rclone-mirror \ "raffs3:${BUCKET}/mirror-demo" \ --config /etc/rclone/raff-rclone.conf \ --dry-run \ --combined - ``` If the preview is correct, run the first real sync: ```bash sudo rclone sync \ ~/raff-rclone-mirror \ "raffs3:${BUCKET}/mirror-demo" \ --config /etc/rclone/raff-rclone.conf ``` Now remove one local file and preview again with a delete guard: ```bash rm ~/raff-rclone-mirror/two.txt sudo rclone sync \ ~/raff-rclone-mirror \ "raffs3:${BUCKET}/mirror-demo" \ --config /etc/rclone/raff-rclone.conf \ --dry-run \ --max-delete 10 \ --combined - ``` Only run the real destructive sync when the deletion list is expected. Because Raff Object Storage does not currently support object versioning, a deleted or overwritten destination key does not automatically leave a recoverable prior version. A mirror is therefore not the same thing as a historical backup. **Verify:** The dry run should explicitly show the planned delete, and no real delete should occur until you intentionally remove `--dry-run` after reviewing the output. ## Step 10 — Use immutable or timestamped backup objects for recovery history If your application already creates timestamped backup archives, upload them with `copy` rather than mirroring a mutable directory. Example local backup files: ```bash sudo install -d -m 700 /var/backups/app STAMP="$(date -u +%Y%m%dT%H%M%SZ)" echo 'example backup payload' | \ sudo tee "/var/backups/app/app-${STAMP}.tar" >/dev/null sudo chmod 600 "/var/backups/app/app-${STAMP}.tar" ``` Upload without deleting older remote backups: ```bash sudo rclone copy \ /var/backups/app \ "raffs3:${BUCKET}/backups/app" \ --config /etc/rclone/raff-rclone.conf \ --include 'app-*.tar' ``` List the backup prefix: ```bash sudo rclone lsl "raffs3:${BUCKET}/backups/app" \ --config /etc/rclone/raff-rclone.conf ``` Retention must be an explicit operational decision. Raff Object Storage does not currently support S3 lifecycle expiration, so do not imply that old objects will age out automatically. :::cta Protect Your Files with Object Storage Create a Raff Object Storage bucket and keep recovery copies outside the source VM using the S3-compatible endpoint. ::: **Verify:** The new timestamped backup object should exist remotely without deleting earlier backup objects, and your retention process should be documented separately. ## Step 11 — Restore into a clean directory and verify content Create a disposable restore directory: ```bash rm -rf ~/raff-rclone-restore-test mkdir -p ~/raff-rclone-restore-test ``` Restore the non-destructive copy demo: ```bash sudo rclone copy \ "raffs3:${BUCKET}/copy-demo" \ ~/raff-rclone-restore-test \ --config /etc/rclone/raff-rclone.conf ``` Compare source and restore: ```bash sudo rclone check \ ~/raff-rclone-demo \ ~/raff-rclone-restore-test \ --one-way ``` For recovery-critical data, inspect representative files and application-level validity, not just object counts. **Verify:** The restored directory should contain the expected files and `rclone check` should report no mismatches for the files you intended to recover. ## Step 12 — Optionally add client-side encryption with an rclone crypt remote Raff Object Storage already uses HTTPS in transit. If you also want rclone-managed client-side encryption before upload, wrap a dedicated S3 prefix with an rclone `crypt` remote. Create a dedicated underlying path such as: ```text raffs3:YOUR_BUCKET_NAME/encrypted-backups ``` Start the interactive configurator: ```bash sudo rclone config --config /etc/rclone/raff-rclone.conf ``` Create a new remote named `raffcrypt`: ```text Storage type: crypt Remote to encrypt: raffs3:YOUR_BUCKET_NAME/encrypted-backups Filename encryption: standard Directory name encryption: true Password: generate or enter a strong unique password Password2/salt: generate or enter a different strong value ``` Store the encryption password(s) outside the VM in a password manager or recovery record. Rclone notes that crypt passwords stored in the config are only lightly obscured unless the config itself is encrypted. Losing the crypt credentials can make the encrypted objects unrecoverable. Upload through the crypt remote: ```bash sudo rclone copy \ /var/backups/app \ raffcrypt: \ --config /etc/rclone/raff-rclone.conf ``` Verify encrypted data with `cryptcheck`, not normal checksum comparison against the wrapped S3 objects: ```bash sudo rclone cryptcheck \ /var/backups/app \ raffcrypt: \ --config /etc/rclone/raff-rclone.conf ``` Do not mix plaintext writes directly into the same underlying `encrypted-backups` prefix. **Verify:** `raffcrypt:` should list readable plaintext names through rclone, the raw `raffs3:.../encrypted-backups` path should contain encrypted objects, and the crypt credentials should be stored in a separate recovery location. ## Step 13 — Automate a non-destructive upload with systemd For automation, prefer `copy` of already-created backup artifacts over `sync` unless you truly want mirror semantics. Create the script: ```bash sudo tee /usr/local/sbin/rclone-raff-backup-upload.sh >/dev/null <<'EOF' #!/usr/bin/env bash set -euo pipefail CONFIG=/etc/rclone/raff-rclone.conf SOURCE=/var/backups/app DEST=raffs3:YOUR_BUCKET_NAME/backups/app /usr/bin/rclone copy "$SOURCE" "$DEST" \ --config "$CONFIG" \ --include 'app-*.tar' \ --log-level INFO \ --stats 30s /usr/bin/rclone lsf "$DEST" \ --config "$CONFIG" \ --max-depth 1 EOF sudo chown root:root /usr/local/sbin/rclone-raff-backup-upload.sh sudo chmod 750 /usr/local/sbin/rclone-raff-backup-upload.sh ``` Replace `YOUR_BUCKET_NAME` before running it. Test manually: ```bash sudo /usr/local/sbin/rclone-raff-backup-upload.sh ``` Create a oneshot service: ```bash sudo tee /etc/systemd/system/rclone-raff-backup-upload.service >/dev/null <<'EOF' [Unit] Description=Upload backup artifacts to Raff Object Storage with rclone Wants=network-online.target After=network-online.target [Service] Type=oneshot ExecStart=/usr/local/sbin/rclone-raff-backup-upload.sh EOF ``` Create a daily timer: ```bash sudo tee /etc/systemd/system/rclone-raff-backup-upload.timer >/dev/null <<'EOF' [Unit] Description=Run Raff Object Storage backup upload daily [Timer] OnCalendar=*-*-* 03:15:00 Persistent=true RandomizedDelaySec=15m Unit=rclone-raff-backup-upload.service [Install] WantedBy=timers.target EOF ``` Enable it: ```bash sudo systemctl daemon-reload sudo systemctl enable --now rclone-raff-backup-upload.timer ``` **Verify:** The script should succeed manually, `systemctl list-timers rclone-raff-backup-upload.timer` should show a next run, and the service should use `copy`, not an unreviewed destructive sync. ## Step 14 — Run the final end-to-end verification and clean up only test data Verify the remote, sample object, backup path, and timer: ```bash rclone version sudo rclone listremotes \ --config /etc/rclone/raff-rclone.conf sudo rclone lsl "raffs3:${BUCKET}/rclone-tutorial" \ --config /etc/rclone/raff-rclone.conf sudo rclone lsl "raffs3:${BUCKET}/backups/app" \ --config /etc/rclone/raff-rclone.conf systemctl list-timers rclone-raff-backup-upload.timer ``` Confirm the design: - endpoint is `https://s3.raffusercloud.com`; - signing region is `us-east-1`; - `provider = Other`; - `force_path_style = false`; - the config file is root-only; - `copy` is used for non-destructive backup upload; - `sync` is only used when mirror/delete semantics are intentional; - destructive syncs are previewed first; - recovery is tested into a clean directory; - `rclone check` or a targeted `--download` check is used when integrity assurance matters; - optional crypt credentials are stored independently; - no workflow depends on object versioning or lifecycle rules. Remove only tutorial test prefixes if you are certain they contain no production data: ```bash sudo rclone purge "raffs3:${BUCKET}/rclone-tutorial" \ --config /etc/rclone/raff-rclone.conf \ --dry-run ``` Review the output, then remove `--dry-run` only if the destination is correct. Do not purge `backups/app` unless those backup objects are disposable. **Verify:** The production bucket should retain all intended data, only explicitly reviewed tutorial objects should be removed, and at least one verified recovery path should remain documented. ## Troubleshooting ### `SignatureDoesNotMatch` or authentication errors Confirm the endpoint and signing region in the redacted config: ```bash sudo rclone config redacted raffs3 \ --config /etc/rclone/raff-rclone.conf ``` Expected values include: ```text provider = Other region = us-east-1 endpoint = https://s3.raffusercloud.com force_path_style = false ``` Do not paste unredacted credentials into support channels. ### Bucket access works in one tool but not rclone Check whether the bucket name contains periods and whether rclone is using virtual-hosted requests. For Raff, prefer DNS-safe bucket names without periods and keep `force_path_style = false`. ### `rclone sync` wants to delete unexpected files Stop. Keep `--dry-run` enabled and inspect `--combined -` output. Confirm source/destination direction, filters, and prefix spelling. Use `copy` instead if destination-only objects must survive. ### `rclone check` cannot use a useful remote hash Multipart objects and objects written by other clients may not expose an MD5-compatible ETag. Use a targeted `rclone check --download` when you need content verification independent of remote hash metadata. ### Large uploads consume too much RAM Reduce transfers, S3 upload concurrency, or chunk size. Multipart memory use scales with transfers × upload concurrency × chunk size. Return to defaults before tuning further. ### An interrupted upload leaves multipart data behind Inspect unfinished multipart uploads before deleting anything: ```bash sudo rclone backend list-multipart-uploads \ "raffs3:${BUCKET}" \ --config /etc/rclone/raff-rclone.conf ``` Rclone also supports cleanup of old unfinished multipart uploads. Preview cleanup with `--dry-run` or interactive mode before removing pending uploads. ### Encrypted backups cannot be opened Use the `raffcrypt:` remote and confirm you have the original crypt password and salt. Do not point a newly configured crypt remote with different credentials at existing encrypted objects and expect them to decrypt. ## Conclusion You configured current rclone for Raff S3-compatible Object Storage, kept credentials in a protected config, used the correct endpoint and signing region, verified upload/download integrity, separated `copy` from destructive `sync`, tested restores, accounted for multipart behavior, optionally added client-side crypt encryption, and automated non-destructive backup uploads with systemd. The most important operational rule is that object synchronization and backup history are different. Raff Object Storage does not currently provide object versioning or lifecycle expiration, so use immutable/timestamped backup objects and explicit retention when previous recovery points matter. Continue with [How to Use Raff S3-Compatible Object Storage with AWS CLI](/learn/tutorials/raff-s3-object-storage-aws-cli), [Automate Backups with Cron and Rsync on Ubuntu 24.04](/learn/tutorials/automate-backups-cron-rsync-ubuntu-24-04), and [Back Up PostgreSQL to Raff Object Storage with Restic](/learn/tutorials/back-up-postgresql-raff-object-storage-restic). ## Sources - [rclone downloads](https://rclone.org/downloads/) - [rclone S3 backend](https://rclone.org/s3/) - [rclone sync](https://rclone.org/commands/rclone_sync/) - [rclone check](https://rclone.org/commands/rclone_check/) - [rclone crypt](https://rclone.org/crypt/) - [Ubuntu 24.04 rclone package](https://packages.ubuntu.com/noble-updates/rclone) - [Raff Object Storage](/products/object-storage) - Package, S3, integrity, backup, and automation guidance re-verified: 2026-09-05 --- ### How to Set Up WireGuard VPN on Ubuntu 24.04 for Private Access URL: https://rafftechnologies.com/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04 Description: Set up WireGuard on Ubuntu 24.04 for private split-tunnel access. Configure keys, AllowedIPs, UFW, keepalive, private SSH, peers, and verification. WireGuard can give a laptop or workstation a private route to an Ubuntu 24.04 server without turning that server into a full-tunnel internet gateway. In this tutorial, you will install WireGuard, create a `10.66.66.0/24` tunnel, add one client peer, keep normal client internet traffic outside the VPN, protect the UDP listener, verify the route and handshake, and test private SSH access before changing any public administration path. Raff Technologies is the VM platform used by the saved test environment. The existing test note remains `Ubuntu 24.04 LTS on Raff 1 vCPU / 2 GB RAM VM; Linux client for tunnel verification`. This revision updates the operational guidance against current Ubuntu Server and WireGuard documentation without claiming a new end-to-end test. This is a **split-tunnel** design. The client uses `AllowedIPs = 10.66.66.0/24`, so only traffic for the WireGuard subnet enters the tunnel. There is no IPv4 forwarding, NAT, or masquerading because the goal is private access to services on the WireGuard server itself. If you want all internet traffic to exit through the VM, use the separate full-tunnel tutorial. WireGuard's `AllowedIPs` setting is especially important: on transmit it selects which peer should receive traffic for a destination; on receive it also restricts which source addresses that peer is allowed to use. Ubuntu's current WireGuard documentation describes those routing and access-control roles explicitly. Prerequisites: - Ubuntu 24.04 with SSH and sudo access - A public IPv4 address or reachable DNS name for the WireGuard endpoint - A client with WireGuard support - UDP port `51820` reachable through the firewall protecting the VM - A VPN subnet that does not overlap the client or server networks ## Step 1 — Verify Ubuntu and choose a non-overlapping VPN subnet Confirm the server release and current routes: ```bash cat /etc/os-release ip -4 addr ip -4 route ``` This tutorial uses: ```text WireGuard interface: wg0 VPN subnet: 10.66.66.0/24 Server VPN address: 10.66.66.1/24 Client VPN address: 10.66.66.2/32 UDP listener: 51820 ``` Check whether the proposed subnet already appears in the server routing table: ```bash ip -4 route | grep '10\.66\.66\.0/24' || true ``` Run an equivalent route check on the client. If either side already uses `10.66.66.0/24`, choose a different RFC1918 subnet and use it consistently throughout the configuration. **Verify:** Ubuntu should report 24.04, the public endpoint should be known, and `10.66.66.0/24` should not conflict with an existing route on either peer. ## Step 2 — Install WireGuard from Ubuntu's package repository Install WireGuard: ```bash sudo apt update sudo apt install -y wireguard ``` The official WireGuard installation page uses `sudo apt install wireguard` for Ubuntu, and the standard Ubuntu kernel includes WireGuard support. Verify the userspace tools: ```bash wg --version wg-quick --help 2>&1 | head ``` Load the kernel module explicitly as a diagnostic check: ```bash sudo modprobe wireguard lsmod | grep '^wireguard' || true ``` A missing `lsmod` line after normal use is not by itself proof of failure on every kernel configuration; the functional checks later in the tutorial are what matter. **Verify:** `wg --version` and `wg-quick` should run successfully without installing a third-party VPN package or repository. ## Step 3 — Generate the server key pair without exposing the private key Create the WireGuard directory and a root-only server key: ```bash sudo install -d -m 700 /etc/wireguard sudo sh -c 'umask 077; wg genkey > /etc/wireguard/wg0.key' sudo sh -c 'wg pubkey < /etc/wireguard/wg0.key > /etc/wireguard/wg0.pub' ``` Set explicit permissions: ```bash sudo chown root:root /etc/wireguard/wg0.key /etc/wireguard/wg0.pub sudo chmod 600 /etc/wireguard/wg0.key sudo chmod 644 /etc/wireguard/wg0.pub ``` Display only the public key: ```bash sudo cat /etc/wireguard/wg0.pub ``` WireGuard's official quick start recommends creating private keys under a restrictive umask. Ubuntu's security guidance also recommends keeping private keys out of configuration text that might later be shared for troubleshooting. **Verify:** `/etc/wireguard/wg0.key` should be mode `600`; the public key may be displayed or copied, but the private key should never be printed, pasted into tickets, or committed to source control. ## Step 4 — Create the server configuration for private-only access Create `/etc/wireguard/wg0.conf` without embedding the server private key: ```bash sudo tee /etc/wireguard/wg0.conf >/dev/null <<'EOF' [Interface] Address = 10.66.66.1/24 ListenPort = 51820 PostUp = wg set %i private-key /etc/wireguard/%i.key SaveConfig = false EOF sudo chown root:root /etc/wireguard/wg0.conf sudo chmod 600 /etc/wireguard/wg0.conf ``` This server does **not** need: ```text net.ipv4.ip_forward = 1 MASQUERADE / NAT rules AllowedIPs = 0.0.0.0/0 ``` Those belong to routed or full-tunnel designs. Here, the client only needs to reach `10.66.66.1` and any service intentionally listening on that server address. Inspect only the non-secret configuration: ```bash sudo cat /etc/wireguard/wg0.conf ``` Because the private key is loaded from `/etc/wireguard/wg0.key`, this output does not expose it. **Verify:** The interface should use `10.66.66.1/24`, listen on UDP `51820`, load its private key from the protected key file, and contain no forwarding or NAT rule. ## Step 5 — Allow the WireGuard UDP listener without risking SSH lockout Check UFW state first: ```bash sudo ufw status numbered ``` If UFW is already active, allow WireGuard: ```bash sudo ufw allow 51820/udp comment 'WireGuard VPN' sudo ufw status numbered ``` If UFW is inactive, do **not** blindly enable it from a single remote SSH session. First follow the lockout-safe process in [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), verify your real SSH port is allowed, and keep a second SSH session open while testing. If another firewall protects the VM outside Ubuntu, allow UDP `51820` there as well. WireGuard does not use TCP `51820` in this configuration. **Verify:** UDP `51820` should be reachable through every firewall layer that protects the VM, while the existing SSH administration path should remain working. ## Step 6 — Generate the client key pair on the client device Generate client private keys on the client whenever possible so the private key never has to travel through the server. On an Ubuntu or Debian client: ```bash sudo apt update sudo apt install -y wireguard ``` Create a protected directory and client keys: ```bash mkdir -p ~/.config/wireguard-raff chmod 700 ~/.config/wireguard-raff umask 077 wg genkey > ~/.config/wireguard-raff/client.key wg pubkey < ~/.config/wireguard-raff/client.key \ > ~/.config/wireguard-raff/client.pub ``` Display only the client public key: ```bash cat ~/.config/wireguard-raff/client.pub ``` Check the private-key permissions: ```bash stat -c '%a %n' ~/.config/wireguard-raff/client.key ``` Windows, macOS, iOS, and Android users can generate the peer keys in the official WireGuard application and use the same tunnel addresses shown in this guide. **Verify:** The client private key should remain on the client with restrictive permissions; only the client public key should be copied to the server. ## Step 7 — Add the client peer and understand `AllowedIPs` On the server, paste the **client public key** into a temporary shell variable: ```bash CLIENT_PUBLIC_KEY='PASTE_CLIENT_PUBLIC_KEY_HERE' ``` Append the peer: ```bash sudo tee -a /etc/wireguard/wg0.conf >/dev/null </dev/null < "backups/manual/roles-${STAMP}.sql.gz" docker compose exec -T db \ pg_dump -U postgres -d postgres -Fc \ > "backups/manual/postgres-${STAMP}.dump" ``` If Storage is in use, coordinate a maintenance window or otherwise stop application writes while the database dump and Storage copy are taken so that database metadata and object files do not drift apart. Archive the self-hosted Storage data directory used by the official Docker bundle: ```bash tar -czf "backups/manual/storage-${STAMP}.tar.gz" \ volumes/storage ``` Archive the sensitive configuration and recorded release: ```bash tar -czf "backups/manual/config-${STAMP}.tar.gz" \ .env .supabase-version docker-compose.yml run.sh update.sh volumes/proxy 2>/dev/null || \ tar -czf "backups/manual/config-${STAMP}.tar.gz" \ .env .supabase-version docker-compose.yml run.sh volumes/proxy chmod 600 backups/manual/* ``` Validate the artifacts: ```bash gzip -t "backups/manual/roles-${STAMP}.sql.gz" pg_restore -l "backups/manual/postgres-${STAMP}.dump" | head tar -tzf "backups/manual/storage-${STAMP}.tar.gz" | head tar -tzf "backups/manual/config-${STAMP}.tar.gz" | head ``` Copy the complete recovery set off the VM. [Raff Object Storage](/products/object-storage) can be an off-server target for S3-compatible backup tooling, while [Data Protection](/products/data-protection) can provide an additional VM-level recovery layer. :::cta Protect Your Supabase Server Run Supabase on an Ubuntu VM and keep Postgres, Storage objects, configuration, and signing material in a separate recovery workflow. ::: **Verify:** Roles, database, Storage, and configuration archives should all be readable, protected, and copied to a separate failure domain. ## Step 12 — Rehearse a restore on an isolated test VM Do not prove backups by overwriting production. Use a disposable VM or isolated recovery project. Start from the **same self-hosted release** recorded in the backup's `.supabase-version`. Restore the configuration bundle, then keep application services stopped while you prepare the database. A same-version recovery pattern is: ```bash cd supabase-project docker compose up -d db ``` Restore roles: ```bash gunzip -c /backup/roles-YYYYMMDD-HHMMSS.sql.gz \ | docker compose exec -T db psql -U postgres -d postgres ``` Restore the custom-format database dump into the disposable database service: ```bash docker compose exec -T db \ pg_restore -U postgres -d postgres --clean --if-exists \ < /backup/postgres-YYYYMMDD-HHMMSS.dump ``` Restore the matching Storage archive into the recovery project before starting Storage/API services: ```bash tar -xzf /backup/storage-YYYYMMDD-HHMMSS.tar.gz -C . ``` Then start the stack: ```bash sh run.sh start ``` Validate Studio login, representative database rows, Auth users relevant to the test, and several Storage objects. Keep SMTP, OAuth callbacks, webhooks, and other external integrations disabled or redirected in a recovery rehearsal so the test copy cannot trigger production side effects. A logical database restore can be sensitive to major-version or self-hosted service differences. That is why the first recovery test should use the exact recorded self-hosted snapshot and why upgrades need a fresh backup after successful verification. **Verify:** The isolated instance should boot on the intended self-hosted release, Studio should work, representative data and Storage objects should be present, and no production integration should be triggered from the test environment. ## Step 13 — Update Supabase with the supported version-tracked workflow Check the installed base version: ```bash cd supabase-project cat .supabase-version ``` Create the full recovery set from Step 11 before applying an update. Preview the current update first: ```bash sh update.sh --dry-run ``` The dry run is most useful when `.supabase-version` records the deployment's real base version. Review breaking-change notices, new `.env` keys, and any merge conflicts. Apply the configuration update: ```bash sh update.sh ``` Then pull the tested image set and recreate the containers: ```bash sh run.sh pull sh run.sh recreate ``` Check the new recorded version and service health: ```bash cat .supabase-version docker compose ps ``` Do not assume `update.sh` protects application data: Supabase explicitly separates configuration backup from Postgres and Storage backup responsibilities. **Verify:** The update should complete without unresolved merge conflicts, `.supabase-version` should advance to the intended release, and every required service should return to healthy state. ## Step 14 — Run the final security, recovery, and exposure audit Check service health and the recorded release: ```bash cd supabase-project cat .supabase-version docker compose ps ``` Check public HTTPS: ```bash curl -I https://supabase.example.com/auth/v1/ curl -I https://supabase.example.com/rest/v1/ ``` Inspect host listeners and firewall rules: ```bash sudo ss -tulpn sudo ufw status numbered ``` Confirm all of the following: - Ubuntu meets the resources required by the services you enabled; - the deployment has a non-empty `.supabase-version`; - the self-hosted services are running as one reviewed snapshot rather than arbitrary image versions; - `.env` is mode 600 and protected off-server; - dashboard credentials are non-default; - secret/server-side and service-role keys are not present in frontend code; - HTTPS terminates at the intended reverse proxy; - Realtime traffic can pass through the proxy's WebSocket support; - internal database and API-gateway ports are not unintentionally public; - Postgres and Storage data are backed up separately from the configuration backup created by `update.sh`; - the recovery set includes `.env`, signing material, version metadata, database roles, database contents, and Storage objects; - at least one restore has been rehearsed on an isolated instance; - a new full backup exists after any successful upgrade. **Verify:** There should be no unhealthy service, default credential, exposed secret, accidental public database listener, missing Storage backup, or untested recovery path. ## Troubleshooting ### One or more containers never become healthy Run the bundled diagnostics: ```bash cd supabase-project sh tests/test-container-logs.sh sh run.sh logs storage ``` Also confirm the server still meets the documented CPU, RAM, and disk minimum. ### HTTPS returns certificate or proxy errors Check DNS and Caddy: ```bash dig +short A supabase.example.com docker logs supabase-caddy --tail=200 sudo ss -lntp | grep -E ':(80|443)\b' ``` The domain must resolve to the server and public 80/443 must reach the reverse proxy. ### OAuth redirects use the wrong URL Review the URL roles in `.env`: ```text SUPABASE_PUBLIC_URL=https://supabase.example.com API_EXTERNAL_URL=https://supabase.example.com/auth/v1 SITE_URL=https://app.example.com ``` `SITE_URL` is the application users return to, not automatically the Supabase host. ### Studio works but frontend requests fail Review the generated credentials: ```bash sh run.sh secrets ``` Use a publishable/anon client credential where appropriate and keep secret/service-role credentials on trusted backend systems only. Also check browser/network responses through the public HTTPS gateway rather than testing an internal container URL. ### `update.sh --dry-run` cannot show a meaningful diff Check `.supabase-version`: ```bash cat .supabase-version ``` Supabase documents that update merging needs a recorded base version. Older untracked installations require you to establish the correct base before a full three-way update preview can work safely. ### An update succeeded but data is missing Do not rely on `update.sh` configuration backups as a database recovery mechanism. Restore from the independent Postgres and Storage recovery set created before the update, on an isolated instance first if possible. ### A restore starts but Storage objects are missing The Postgres dump contains Storage metadata but not the object files themselves. Restore the matching `volumes/storage` archive as well as the database and configuration recovery set. ## Conclusion You now have a current Supabase self-hosting workflow for Ubuntu 24.04 using Supabase's version-tracked Docker Compose bundle, generated credentials, Caddy HTTPS, health checks, private database exposure, a real database/API verification, independent Postgres and Storage backups, isolated restore testing, and the supported `update.sh` upgrade path. The most important operational rule is to keep the deployment as a coordinated self-hosted snapshot and to separate **configuration updates** from **data protection**. `.supabase-version` tells the updater what configuration you started from; it does not replace database, Storage, secret, or recovery backups. For adjacent procedures, continue with [Install Docker on Ubuntu 24.04](/learn/tutorials/install-docker-ubuntu-24-04), [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04), and [Harden Ubuntu 24.04](/learn/tutorials/secure-ubuntu-24-04-server). ## Sources - [Supabase — Self-Hosting with Docker](https://supabase.com/docs/guides/self-hosting/docker) - [Supabase — Configure Reverse Proxy and HTTPS](https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https) - [Supabase — Update Your Self-Hosted Deployment](https://supabase.com/docs/guides/self-hosting/updating) - [Supabase — Accessing Postgres](https://supabase.com/docs/guides/self-hosting/accessing-postgres) - [Supabase — Self-Hosting](https://supabase.com/docs/guides/self-hosting) - Guidance re-verified: 2026-09-06 --- ### How to Deploy Laravel 13 on Ubuntu 24.04 with Nginx and PHP-FPM URL: https://rafftechnologies.com/learn/tutorials/deploy-laravel-ubuntu-24-04-nginx Description: Deploy Laravel 13 on Ubuntu 24.04 with Nginx and PHP 8.3-FPM. Configure HTTPS, safe permissions, production caches, queues, scheduler, and health checks. Deploying Laravel 13 on Ubuntu 24.04 with Nginx and PHP-FPM gives you a conventional production stack that matches Laravel's current server guidance while keeping the application code outside the public web root. This tutorial installs PHP 8.3, Composer, Nginx, configures Laravel's environment and permissions, serves only `public/`, enables HTTPS, and verifies Laravel's built-in `/up` health route. Raff Technologies is the VM platform used by the saved test environment. The original `testedOn` record is preserved exactly in the article metadata. This revision re-verifies the deployment procedure against Laravel 13's current deployment, queue, scheduler, and filesystem documentation without claiming a new end-to-end machine test. Laravel 13 was released on March 17, 2026 and supports PHP 8.3 through PHP 8.5. Ubuntu 24.04's PHP 8.3 packages therefore remain a supported baseline. Laravel's current production documentation also recommends caching application configuration with `php artisan optimize`, keeping `APP_DEBUG=false`, serving requests through `public/index.php`, and reloading long-running services after code deployments. Prerequisites: - An Ubuntu 24.04 VM with SSH and sudo access - A public IPv4 address - A Laravel project, or the fresh Laravel 13 application created below - A domain such as `laravel.example.com` for production HTTPS - Database credentials if your real application uses MySQL or PostgreSQL - A backup or rollback point before applying migrations to an existing production database Use these placeholders throughout the tutorial: | Placeholder | Replace with | |---|---| | `your_server_ip` | Your server's public IPv4 address | | `laravel.example.com` | Your Laravel domain | | `/var/www/laravel` | Laravel application directory | ![Architecture diagram showing Laravel on Ubuntu 24.04 with Nginx, PHP-FPM, HTTPS, and a database on a Raff VM](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_architecture_webp_3b10063a5a.png) ![Deployment flow infographic for Laravel on Ubuntu 24.04 with Nginx and PHP-FPM](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_deployment_flow_webp_ed8580dbb0.png) ## Step 1 — Verify Ubuntu 24.04 and define the deployment host Connect to the server: ```bash ssh your-user@your_server_ip ``` Confirm the operating system and architecture: ```bash cat /etc/os-release uname -m ``` Check available resources and disk space: ```bash nproc free -h df -h / ``` Set variables used in later checks: ```bash export APP_DIR=/var/www/laravel export APP_HOST=laravel.example.com ``` If DNS is already configured, verify it: ```bash dig +short A "$APP_HOST" || true ``` ![Terminal showing Ubuntu 24.04 verified on a Raff VM before Laravel deployment](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_01_ubuntu_2404_verified_webp_58b01930eb.png) **Verify:** `/etc/os-release` should identify Ubuntu 24.04, the server should have enough free disk for the application and logs, and SSH should remain available before any firewall change. ## Step 2 — Install Nginx, PHP 8.3-FPM, Composer, and Laravel extensions Laravel 13 requires PHP 8.3 or newer. Install Ubuntu 24.04's PHP 8.3 packages, Nginx, Composer, and common extensions used by Laravel applications: ```bash sudo apt update sudo apt install -y \ nginx composer curl unzip git ca-certificates dnsutils \ php8.3-fpm php8.3-cli php8.3-common \ php8.3-curl php8.3-mbstring php8.3-xml \ php8.3-bcmath php8.3-zip php8.3-sqlite3 php8.3-intl ``` Applications using MySQL or PostgreSQL also need the matching PHP driver, for example: ```bash sudo apt install -y php8.3-mysql # or sudo apt install -y php8.3-pgsql ``` Enable Nginx and PHP-FPM: ```bash sudo systemctl enable --now nginx sudo systemctl enable --now php8.3-fpm ``` Check versions and required modules: ```bash nginx -v php -v composer --version php -m | grep -Ei 'ctype|curl|dom|fileinfo|filter|hash|mbstring|openssl|pcre|pdo|session|tokenizer|xml' ``` ![Terminal showing Nginx, PHP 8.3, and Composer installed on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_02_nginx_php_composer_installed_webp_c514b91056.png) **Verify:** Nginx and `php8.3-fpm` should be active, PHP should report 8.3 or newer, Composer should run successfully, and Laravel's required PHP extensions should be loaded. ## Step 3 — Prepare web firewall rules without risking SSH lockout Check the current firewall state first: ```bash sudo ufw status numbered ``` If UFW is already active, preserve the actual SSH rule and allow web traffic: ```bash sudo ufw allow 80/tcp comment 'Laravel HTTP' sudo ufw allow 443/tcp comment 'Laravel HTTPS' sudo ufw status numbered ``` If UFW is inactive, do **not** blindly run `ufw --force enable` from a single remote session. Confirm the real SSH port and create the correct SSH allowance first, then use a second SSH session to verify access during activation. The lockout-safe procedure is covered in [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). Check that Nginx currently listens where expected: ```bash sudo ss -lntp | grep -E ':(80|443)\b' || true ``` **Verify:** If UFW is active, TCP 80 and 443 should be allowed and SSH should remain reachable. If UFW is inactive, leave activation to a deliberate lockout-safe firewall change rather than forcing it here. ## Step 4 — Create or deploy the Laravel 13 application Create the application directory and assign your deployment user as owner with `www-data` as the group: ```bash sudo mkdir -p /var/www/laravel sudo chown -R "$USER":www-data /var/www/laravel cd /var/www/laravel ``` For a clean Laravel 13 sample application: ```bash composer create-project laravel/laravel . "^13.0" --prefer-dist ``` For an existing project, deploy your Git checkout or release artifact instead, then install production dependencies: ```bash composer install \ --no-dev \ --prefer-dist \ --no-interaction \ --optimize-autoloader ``` Do not run `composer update` as a routine production deployment step; deploy the dependency versions recorded in your project's lock file. Check the framework and entry point: ```bash php artisan --version ls -l artisan public/index.php composer.lock ``` **Verify:** `php artisan --version` should report Laravel 13.x for the fresh sample, `public/index.php` should exist, and production deployments should have a committed `composer.lock` controlling dependency versions. ## Step 5 — Configure the production environment and protect `.env` If your existing project does not yet have an environment file, create it from its example: ```bash cd /var/www/laravel test -f .env || cp .env.example .env ``` Generate an application key only when the application does not already have one: ```bash grep -q '^APP_KEY=base64:' .env || php artisan key:generate ``` Set the core production values: ```bash sed -i 's/^APP_ENV=.*/APP_ENV=production/' .env sed -i 's/^APP_DEBUG=.*/APP_DEBUG=false/' .env sed -i 's#^APP_URL=.*#APP_URL=https://laravel.example.com#' .env chmod 600 .env ``` For the IP-only HTTP verification path before DNS/TLS is ready, temporarily use: ```text APP_URL=http://your_server_ip ``` Do not overwrite an existing production `APP_KEY`; Laravel uses it for encrypted application data and changing it can invalidate encrypted values and sessions. Check only non-secret environment values: ```bash grep -E '^APP_ENV=|^APP_DEBUG=|^APP_URL=' .env stat -c '%a %n' .env ``` **Verify:** `APP_ENV` should be `production`, `APP_DEBUG` should be `false`, `APP_URL` should match the current public endpoint, `.env` should be mode 600, and an existing production `APP_KEY` should remain unchanged. ## Step 6 — Configure the database, migrations, and writable directories For the reproducible sample deployment, SQLite keeps the tutorial self-contained: ```bash cd /var/www/laravel sed -i 's/^DB_CONNECTION=.*/DB_CONNECTION=sqlite/' .env touch database/database.sqlite ``` For a real application, configure its existing MySQL or PostgreSQL values in `.env` instead of replacing them with SQLite. Before applying migrations to an existing production database, take an application-consistent database backup or snapshot appropriate to that database. Run migrations: ```bash php artisan migrate --force ``` Laravel's current deployment documentation requires the web server process to be able to write to `storage` and `bootstrap/cache`. Give the deployment user ownership and `www-data` group access only where Laravel needs writes: ```bash sudo chown -R "$USER":www-data /var/www/laravel sudo chmod -R ug+rwX storage bootstrap/cache sudo find storage bootstrap/cache -type d -exec chmod g+s {} \; ``` For this tutorial's SQLite database, also allow the PHP-FPM group to write the database file and directory: ```bash sudo chgrp www-data database database/database.sqlite sudo chmod g+rwX database database/database.sqlite ``` Never use `chmod -R 777` on a Laravel application. Check migration state: ```bash php artisan migrate:status ``` **Verify:** Migrations should succeed, Laravel's writable directories should be group-writable for `www-data`, and no broad world-writable permissions should be present. ## Step 7 — Configure Nginx to serve only Laravel's `public` directory Laravel's official Nginx deployment example routes requests through `public/index.php`. Serving the project root can expose `.env`, source code, logs, and configuration files. ![Diagram showing Laravel public directory structure and Nginx request flow](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_public_directory_visual_webp_602c7cb427.png) Create the server block: ```bash APP_HOST="your_server_ip" APP_DIR="/var/www/laravel" sudo tee /etc/nginx/sites-available/laravel > /dev/null <> /dev/null 2>&1 ``` Verify the installed entry: ```bash crontab -l | grep 'artisan schedule:run' ``` If your application defines sub-minute tasks, Laravel documents `php artisan schedule:interrupt` as part of deployment so an already-running scheduler does not continue executing old code for the remainder of that minute. **Verify:** Applications that use the scheduler should show their tasks in `schedule:list` and have exactly one expected `schedule:run` cron entry under the intended deployment user. ## Step 12 — Run Laravel queue workers under Supervisor if queues are asynchronous Skip this step if your application does not use asynchronous queue workers. Install Supervisor: ```bash sudo apt install -y supervisor sudo systemctl enable --now supervisor ``` Determine the deployment user: ```bash DEPLOY_USER="$(id -un)" echo "$DEPLOY_USER" ``` Create a conservative single-worker configuration. Increase concurrency only after measuring your workload and server capacity: ```bash sudo tee /etc/supervisor/conf.d/laravel-worker.conf > /dev/null </dev/null || true php artisan about --only=environment ``` **Verify:** Reloadable workers should return under their process monitor, the new code should be active, and any database migration included in the release should have an explicit recovery plan rather than relying only on a Git rollback. ## Step 14 — Verify the Laravel production deployment end to end Set the final public URL: ```bash APP_TEST_URL="https://laravel.example.com" ``` If DNS/TLS is not yet part of your saved test state, use the HTTP IP endpoint instead: ```bash APP_TEST_URL="http://your_server_ip" ``` Test the application and Laravel health route: ```bash curl -I "$APP_TEST_URL" curl -i "$APP_TEST_URL/up" ``` Check services: ```bash sudo systemctl is-active nginx sudo systemctl is-active php8.3-fpm sudo nginx -t ``` Check production configuration without printing secrets: ```bash cd /var/www/laravel grep -E '^APP_ENV=|^APP_DEBUG=|^APP_URL=' .env php artisan about --only=environment ``` Check writable paths and make sure the project root is not being served directly: ```bash namei -l /var/www/laravel/storage namei -l /var/www/laravel/bootstrap/cache grep -R 'root ' /etc/nginx/sites-enabled/laravel ``` If queues or scheduler are used, verify them too: ```bash sudo supervisorctl status 2>/dev/null || true crontab -l | grep 'artisan schedule:run' || true ``` ![Terminal showing HTTP 200 verification for Laravel on Ubuntu 24.04 with Nginx and PHP-FPM](https://raff-images.s3.raffusercloud.com/deploy_laravel_ubuntu_24_04_nginx_04_laravel_https_page_webp_097581235a.png) :::cta Deploy a Laravel Server Run Laravel 13 on an Ubuntu VM with Nginx, PHP-FPM, HTTPS, health checks, and production service supervision. ::: **Verify:** The home page and `/up` should return successfully, Nginx and PHP-FPM should be healthy, `APP_DEBUG=false` should remain in effect, Nginx should serve only `/var/www/laravel/public`, and any configured scheduler or queue worker should be running under its intended production mechanism. ## Cleanup and rollback To take only the Laravel site offline without deleting application data: ```bash sudo unlink /etc/nginx/sites-enabled/laravel sudo nginx -t sudo systemctl reload nginx ``` To stop queue workers managed by Supervisor: ```bash sudo supervisorctl stop 'laravel-worker:*' ``` Do not delete `.env`, uploaded files, the database, queue state, TLS material, or release backups until you have confirmed the application no longer needs them. To re-enable the site: ```bash sudo ln -sfn /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/laravel sudo nginx -t sudo systemctl reload nginx ``` ## Troubleshooting ### Nginx returns 403 or 404 Confirm the site root and entry point: ```bash grep -R 'root ' /etc/nginx/sites-enabled/laravel ls -l /var/www/laravel/public/index.php sudo nginx -t ``` The Nginx root should be `/var/www/laravel/public`, not `/var/www/laravel`. ### Nginx returns 502 Bad Gateway Check PHP-FPM and the configured socket: ```bash sudo systemctl status php8.3-fpm --no-pager ls -l /run/php/php8.3-fpm.sock grep fastcgi_pass /etc/nginx/sites-enabled/laravel ``` Restart only after confirming the service and socket path: ```bash sudo systemctl restart php8.3-fpm sudo systemctl reload nginx ``` ### Laravel returns 500 Server Error Inspect the application key, migrations, writable directories, and logs: ```bash cd /var/www/laravel grep '^APP_KEY=' .env php artisan migrate:status namei -l storage bootstrap/cache sudo test -f storage/logs/laravel.log && sudo tail -n 80 storage/logs/laravel.log ``` Do not regenerate an existing production `APP_KEY` just to troubleshoot an HTTP 500. ### `/up` returns HTTP 500 The built-in health route reports whether the Laravel application booted successfully. Check PHP-FPM, Laravel logs, configuration, database/cache dependencies used during boot, and any custom `DiagnosingHealth` listener your application added. ```bash curl -i https://laravel.example.com/up sudo systemctl is-active php8.3-fpm sudo tail -n 80 /var/www/laravel/storage/logs/laravel.log ``` ### Queue jobs stop after a deployment Check Supervisor first: ```bash sudo supervisorctl status sudo tail -n 80 /var/www/laravel/storage/logs/worker.log ``` Laravel's queue workers are long-lived. Use `php artisan reload` or `php artisan queue:restart` during deployment and ensure Supervisor is configured to restart workers after they exit. ### Scheduled tasks never run Check Laravel's schedule and the system cron entry: ```bash cd /var/www/laravel php artisan schedule:list crontab -l | grep 'artisan schedule:run' ``` The scheduler needs one server cron invocation every minute. Do not create a separate cron entry for each Laravel scheduled task. ### Uploaded public files return 404 If your application uses Laravel's local public disk, create the framework's documented storage link: ```bash cd /var/www/laravel php artisan storage:link ls -l public/storage ``` Laravel's public local disk stores files under `storage/app/public` and exposes them through the `public/storage` symlink. ### Certbot cannot validate the domain Check DNS, Nginx, and firewall reachability: ```bash dig +short A laravel.example.com curl -I http://laravel.example.com sudo nginx -t sudo ufw status numbered ``` The hostname must resolve to the server and port 80 must be reachable for the normal HTTP validation flow. ## Conclusion You now have a current Laravel 13 production deployment pattern for Ubuntu 24.04 using Nginx and PHP 8.3-FPM. The application is served only from Laravel's `public` directory, debug output is disabled, production caches are built, HTTPS is available for the domain deployment, and Laravel's `/up` route provides a simple application boot health check. For applications that use background work, the server is also prepared for Laravel's scheduler and Supervisor-managed queue workers. Laravel 13's `php artisan reload` command gives deployments a single framework-level way to terminate reloadable long-running services so their process monitors can restart them on the new code. For related server work, continue with [Set Up a LEMP Stack on Ubuntu 24.04](/learn/tutorials/set-up-lemp-stack-ubuntu-24-04), [Install MySQL on Ubuntu 24.04](/learn/tutorials/install-mysql-ubuntu-24-04), [Secure Nginx with Let's Encrypt](/learn/tutorials/secure-nginx-lets-encrypt-ubuntu-24-04), or [Set Up UFW Firewall](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). ## Sources - [Laravel 13 — Deployment](https://laravel.com/docs/13.x/deployment) - [Laravel 13 — Release Notes](https://laravel.com/docs/13.x/releases) - [Laravel 13 — Queues](https://laravel.com/docs/13.x/queues) - [Laravel 13 — Task Scheduling](https://laravel.com/docs/13.x/scheduling) - [Laravel 13 — File Storage](https://laravel.com/docs/13.x/filesystem) - Guidance re-verified: 2026-09-06 --- ### How to Back Up PostgreSQL to S3 with Restic on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/back-up-postgresql-raff-object-storage-restic Description: Back up PostgreSQL to S3-compatible Raff Object Storage with Restic on Ubuntu 24.04. Automate encrypted dumps, retention, checks, and restore tests. This tutorial builds an automated PostgreSQL backup to S3 workflow on Ubuntu 24.04. You will create a consistent custom-format dump with `pg_dump`, encrypt it with Restic, store it in [Raff Object Storage](/products/object-storage), apply retention, schedule backups with systemd, and prove recovery by restoring into a separate database. Raff Object Storage is S3-compatible at `https://s3.raffusercloud.com` in the `us-east` region. Its current $7/month bundle includes 100 GB of storage and 1 TB of monthly egress, and the product page publishes a 99.9% uptime commitment. Restic supports S3-compatible repositories, so the workflow uses the same repository model it documents for non-AWS S3 services. This is a **logical backup and restore** workflow. It is suitable when your recovery point objective can be met by scheduled dumps. It is not point-in-time recovery (PITR): PostgreSQL uses base backups plus WAL archiving for recovery to a specific point between backups. Prerequisites: * A Raff Linux VM running Ubuntu 24.04 * PostgreSQL installed and a database you can dump locally * SSH and sudo access * A private Raff Object Storage bucket with a scoped read-write S3 key * AWS CLI configured with a `raff` profile if you want to run the bucket verification command in Step 3 * Enough temporary disk space for one PostgreSQL dump * A password manager or another secure off-VM location for the Restic repository password > 📌 **Recovery rule:** A completed backup job is not proof of recoverability. The final step restores the latest recovery point into an isolated test database. The original workflow was tested on a Raff 2 vCPU / 4 GB RAM Ubuntu 24.04 VM. For this refresh, the PostgreSQL dump/restore behavior, Restic S3 configuration, password-file handling, retention, pruning, and repository checks were re-verified against current PostgreSQL and Restic documentation in September 2026. ## Step 1 — Install Restic and PostgreSQL client tools Update Ubuntu and install the required packages: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y restic postgresql-client ``` Verify the tools: ```bash restic version pg_dump --version pg_restore --version ``` Check the PostgreSQL server version: ```bash sudo -u postgres psql -tAc 'SHOW server_version;' ``` Use a `pg_dump` client from the same PostgreSQL major version as the server when practical. PostgreSQL documents that `pg_dump` can dump older servers, but it cannot dump a server newer than its own major version. See the official [`pg_dump` reference](https://www.postgresql.org/docs/current/app-pgdump.html). **Verification:** `restic version`, `pg_dump --version`, and the server-version query should all complete successfully before you continue. ## Step 2 — Identify and validate the source database List the databases on the server: ```bash sudo -u postgres psql -c '\l' ``` This tutorial uses `raffapp`. Replace that name everywhere with your real database name. Create a temporary custom-format dump: ```bash sudo -u postgres pg_dump \ --format=custom \ --file=/tmp/raffapp-test.dump \ raffapp ``` Validate the archive catalog and confirm the file is non-empty: ```bash sudo -u postgres pg_restore --list /tmp/raffapp-test.dump | head test -s /tmp/raffapp-test.dump && echo 'Dump validation passed' ``` Remove the temporary archive: ```bash sudo rm -f /tmp/raffapp-test.dump ``` PostgreSQL separates SQL dumps, filesystem-level backups, and continuous archiving as different backup approaches. For this tutorial, `pg_dump` creates a portable logical archive that `pg_restore` can reconstruct later. See PostgreSQL's [Backup and Restore](https://www.postgresql.org/docs/current/backup.html) documentation. **Verification:** the archive catalog should be readable and `Dump validation passed` should print before the test file is removed. ## Step 3 — Prepare S3-compatible Raff Object Storage Use a dedicated private bucket for database backups. For example: ```text company-production-postgres-backups ``` Create a scoped access key that has read-write access only to the backup bucket. Raff Object Storage currently supports per-bucket grants, so the backup process does not need credentials for unrelated buckets. If your AWS CLI `raff` profile is already configured, verify access without uploading data: ```bash aws s3api head-bucket \ --bucket company-production-postgres-backups \ --endpoint-url https://s3.raffusercloud.com \ --profile raff ``` A successful `head-bucket` command returns no output. If you still need the CLI profile, follow [Raff Object Storage with AWS CLI](/learn/tutorials/raff-s3-object-storage-aws-cli) first. **Verification:** confirm the bucket is private, the backup key is scoped to it, and `head-bucket` completes without an access error. ## Step 4 — Store Restic credentials without putting the repository password in the environment Restic supports `RESTIC_PASSWORD_FILE` for automated jobs. Keeping the repository password in a root-only file avoids placing the password itself in the service environment. Generate a strong repository password into a protected file: ```bash openssl rand -base64 32 | \ sudo tee /etc/restic-postgres.password >/dev/null sudo chown root:root /etc/restic-postgres.password sudo chmod 600 /etc/restic-postgres.password ``` Copy that password into a password manager or another secure recovery location outside the VM: ```bash sudo cat /etc/restic-postgres.password ``` Create the environment file: ```bash sudo install -m 600 -o root -g root \ /dev/null /etc/restic-postgres.env sudo nano /etc/restic-postgres.env ``` Add the following values and replace the placeholders: ```bash RESTIC_REPOSITORY="s3:https://s3.raffusercloud.com/company-production-postgres-backups/postgresql/raffapp" RESTIC_PASSWORD_FILE="/etc/restic-postgres.password" AWS_ACCESS_KEY_ID="REPLACE_WITH_RAFF_ACCESS_KEY" AWS_SECRET_ACCESS_KEY="REPLACE_WITH_RAFF_SECRET_KEY" AWS_DEFAULT_REGION="us-east" PGDATABASE="raffapp" DUMP_DIR="/var/backups/postgresql-restic" ``` Restic documents the `s3:https://server/bucket` form for non-AWS S3-compatible services and supports an explicit region through `AWS_DEFAULT_REGION`. Raff's current Object Storage documentation identifies the service region as `us-east`. Check both files without printing their secrets: ```bash sudo stat -c '%A %U:%G %n' \ /etc/restic-postgres.env \ /etc/restic-postgres.password ``` **Verification:** both files should be owned by `root:root` with `-rw-------` permissions. ## Step 5 — Initialize the encrypted Restic repository Load the protected environment and initialize the repository: ```bash sudo bash -c ' set -a source /etc/restic-postgres.env set +a restic init ' ``` Do not run `restic init` again if the same repository path is already initialized. Verify repository access: ```bash sudo bash -c ' set -a source /etc/restic-postgres.env set +a restic snapshots ' ``` A new repository should open successfully and report that no snapshots exist yet. **Verification:** `restic snapshots` must open the repository without asking for a password or returning an S3 authentication error. ## Step 6 — Create a private local staging directory Create a directory that only PostgreSQL and root can use for the temporary logical dump: ```bash sudo install -d \ -m 700 \ -o postgres \ -g postgres \ /var/backups/postgresql-restic ``` Verify permissions: ```bash sudo stat -c '%A %U:%G %n' \ /var/backups/postgresql-restic ``` Expected ownership is `postgres:postgres` with mode `drwx------`. **Verification:** do not continue if another local user can read the staging directory. ## Step 7 — Create the PostgreSQL backup to S3 script Create the backup script: ```bash sudo nano /usr/local/sbin/postgres-restic-backup.sh ``` Add: ```bash #!/usr/bin/env bash set -Eeuo pipefail umask 077 ENV_FILE="/etc/restic-postgres.env" LOCK_FILE="/run/lock/postgres-restic-backup.lock" if [[ ! -r "$ENV_FILE" ]]; then echo "Cannot read $ENV_FILE" >&2 exit 1 fi set -a source "$ENV_FILE" set +a : "${RESTIC_REPOSITORY:?Missing RESTIC_REPOSITORY}" : "${RESTIC_PASSWORD_FILE:?Missing RESTIC_PASSWORD_FILE}" : "${AWS_ACCESS_KEY_ID:?Missing AWS_ACCESS_KEY_ID}" : "${AWS_SECRET_ACCESS_KEY:?Missing AWS_SECRET_ACCESS_KEY}" : "${AWS_DEFAULT_REGION:?Missing AWS_DEFAULT_REGION}" : "${PGDATABASE:?Missing PGDATABASE}" : "${DUMP_DIR:?Missing DUMP_DIR}" install -d -m 700 -o postgres -g postgres "$DUMP_DIR" DUMP_FILE="${DUMP_DIR}/${PGDATABASE}.dump" exec 9>"$LOCK_FILE" if ! flock -n 9; then echo "Another PostgreSQL backup is already running" >&2 exit 1 fi cleanup() { rm -f "$DUMP_FILE" } trap cleanup EXIT echo "Creating PostgreSQL archive" runuser -u postgres -- pg_dump \ --format=custom \ --file="$DUMP_FILE" \ "$PGDATABASE" test -s "$DUMP_FILE" runuser -u postgres -- pg_restore \ --list "$DUMP_FILE" >/dev/null echo "Backing up encrypted archive to Restic" restic backup "$DUMP_FILE" \ --tag postgresql \ --tag "$PGDATABASE" echo "Applying snapshot retention" restic forget \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 12 echo "Backup completed successfully" ``` The dump path stays stable from run to run. That matters because Restic's retention policy groups snapshots by host and path by default; a stable path lets the daily, weekly, and monthly policy operate on the same backup set instead of treating every timestamped filename as a different group. Make the script root-owned and executable, then check its syntax: ```bash sudo chown root:root /usr/local/sbin/postgres-restic-backup.sh sudo chmod 750 /usr/local/sbin/postgres-restic-backup.sh sudo bash -n /usr/local/sbin/postgres-restic-backup.sh ``` **Verification:** `bash -n` should return no output and exit successfully. ## Step 8 — Run and verify the first backup Run the script manually: ```bash sudo /usr/local/sbin/postgres-restic-backup.sh ``` List repository snapshots: ```bash sudo bash -c ' set -a source /etc/restic-postgres.env set +a restic snapshots ' ``` Inspect the latest snapshot contents: ```bash sudo bash -c ' set -a source /etc/restic-postgres.env set +a restic ls latest ' ``` Confirm the local dump was removed after Restic committed the snapshot: ```bash sudo find /var/backups/postgresql-restic \ -maxdepth 1 -type f -print ``` The final command should print no files after a successful run. **Verification:** you should see a new Restic snapshot containing `raffapp.dump`, while the staging directory is empty. ## Step 9 — Schedule nightly PostgreSQL backups with systemd Create the service: ```bash sudo nano /etc/systemd/system/postgres-restic-backup.service ``` Add: ```ini [Unit] Description=Back up PostgreSQL to Raff Object Storage with Restic Wants=network-online.target After=network-online.target postgresql.service [Service] Type=oneshot EnvironmentFile=/etc/restic-postgres.env ExecStart=/usr/local/sbin/postgres-restic-backup.sh User=root Group=root Nice=10 IOSchedulingClass=best-effort IOSchedulingPriority=7 PrivateTmp=true NoNewPrivileges=true ``` Create the nightly timer: ```bash sudo nano /etc/systemd/system/postgres-restic-backup.timer ``` Add: ```ini [Unit] Description=Run PostgreSQL Restic backup nightly [Timer] OnCalendar=*-*-* 02:30:00 Persistent=true RandomizedDelaySec=15m Unit=postgres-restic-backup.service [Install] WantedBy=timers.target ``` Enable it: ```bash sudo systemctl daemon-reload sudo systemctl enable --now postgres-restic-backup.timer ``` Verify the schedule and run the service once through systemd: ```bash systemctl list-timers postgres-restic-backup.timer sudo systemctl start postgres-restic-backup.service sudo journalctl -u postgres-restic-backup.service -n 100 --no-pager ``` `Persistent=true` causes a missed timer to run after the VM comes back online. **Verification:** the timer should show a next-run time and the manual systemd run should finish without an error in the journal. ## Step 10 — Schedule prune and repository checks separately The backup script removes old snapshot references with `restic forget`, but it deliberately does not prune repository data during every nightly backup. Restic warns that `prune` can take significant time and locks the repository, so run it during a separate maintenance window. Restic also recommends checking the repository after pruning. Create a maintenance service: ```bash sudo nano /etc/systemd/system/postgres-restic-maintenance.service ``` Add: ```ini [Unit] Description=Prune and check PostgreSQL Restic repository Wants=network-online.target After=network-online.target [Service] Type=oneshot EnvironmentFile=/etc/restic-postgres.env ExecStart=/usr/bin/restic prune ExecStart=/usr/bin/restic check User=root Group=root Nice=15 IOSchedulingClass=idle PrivateTmp=true NoNewPrivileges=true ``` Create a weekly timer: ```bash sudo nano /etc/systemd/system/postgres-restic-maintenance.timer ``` Add: ```ini [Unit] Description=Run weekly Restic repository maintenance [Timer] OnCalendar=Sun *-*-* 04:00:00 Persistent=true RandomizedDelaySec=30m Unit=postgres-restic-maintenance.service [Install] WantedBy=timers.target ``` Enable and verify it: ```bash sudo systemctl daemon-reload sudo systemctl enable --now postgres-restic-maintenance.timer systemctl list-timers postgres-restic-maintenance.timer ``` For larger repositories, schedule maintenance when it cannot overlap a backup window. **Verification:** the maintenance timer should be enabled and show its next weekly run. ## Step 11 — Restore the latest backup into a clean test database A PostgreSQL backup and restore process is complete only when the archive can be used by PostgreSQL again. Restore the latest Restic snapshot into a temporary directory: ```bash sudo rm -rf /var/tmp/postgres-restic-restore sudo install -d -m 700 -o root -g root \ /var/tmp/postgres-restic-restore sudo bash -c ' set -a source /etc/restic-postgres.env set +a restic restore latest \ --target /var/tmp/postgres-restic-restore ' ``` Locate the restored dump: ```bash RESTORED_DUMP="$(sudo find /var/tmp/postgres-restic-restore \ -type f -name 'raffapp.dump' -print -quit)" test -n "$RESTORED_DUMP" && test -s "$RESTORED_DUMP" printf '%s\n' "$RESTORED_DUMP" ``` Inspect the archive before executing it. PostgreSQL warns that restoring a dump executes commands contained in the source archive, so only restore archives from a trusted source: ```bash sudo -u postgres pg_restore \ --list "$RESTORED_DUMP" | head ``` Create an isolated recovery database: ```bash sudo -u postgres dropdb --if-exists raffapp_restore_test sudo -u postgres createdb raffapp_restore_test ``` Restore schema and data without requiring the original role ownership and grants: ```bash sudo -u postgres pg_restore \ --exit-on-error \ --no-owner \ --no-privileges \ --dbname=raffapp_restore_test \ "$RESTORED_DUMP" ``` Verify tables and run an application-specific integrity query: ```bash sudo -u postgres psql \ --dbname=raffapp_restore_test \ --command='\dt' ``` The structural test above does not recreate cluster-wide PostgreSQL roles or prove application semantics. For a production recovery runbook, also document required roles, extensions, secrets, and application-level checks. **Verification:** the restore must complete without `pg_restore --exit-on-error` stopping, the test database must contain the expected tables, and your application-specific integrity checks must pass. :::cta bucket Create a private S3-compatible Raff Object Storage bucket for encrypted, off-VM PostgreSQL recovery points. ::: ## Cleanup (Optional) Remove the restore-test database and temporary files: ```bash sudo -u postgres dropdb --if-exists raffapp_restore_test sudo rm -rf /var/tmp/postgres-restic-restore unset RESTORED_DUMP ``` To stop future backups and maintenance: ```bash sudo systemctl disable --now \ postgres-restic-backup.timer \ postgres-restic-maintenance.timer ``` Remove the local units and scripts only when you intend to retire the workflow: ```bash sudo rm -f \ /etc/systemd/system/postgres-restic-backup.service \ /etc/systemd/system/postgres-restic-backup.timer \ /etc/systemd/system/postgres-restic-maintenance.service \ /etc/systemd/system/postgres-restic-maintenance.timer \ /usr/local/sbin/postgres-restic-backup.sh sudo systemctl daemon-reload ``` Remove local credentials only after the Restic repository password and any required recovery credentials are stored safely elsewhere: ```bash sudo rm -f \ /etc/restic-postgres.env \ /etc/restic-postgres.password sudo rm -rf /var/backups/postgresql-restic ``` These cleanup commands do **not** delete the encrypted Restic repository from Object Storage. ## Troubleshooting ### Restic returns `Access Denied` Confirm the endpoint, region, bucket name, repository path, and scoped key permissions. You can safely print only the non-secret settings: ```bash sudo grep -E \ '^(RESTIC_REPOSITORY|RESTIC_PASSWORD_FILE|AWS_DEFAULT_REGION)=' \ /etc/restic-postgres.env ``` The Raff endpoint is `https://s3.raffusercloud.com` and the current region identifier is `us-east`. ### `pg_dump` reports a server version mismatch Compare the client and server versions: ```bash pg_dump --version sudo -u postgres psql -tAc 'SHOW server_version;' ``` Install a PostgreSQL client version that is the same major version as the server or newer. ### The timer runs but no new Restic snapshot appears Inspect the service and journal: ```bash sudo systemctl status postgres-restic-backup.service --no-pager sudo journalctl \ -u postgres-restic-backup.service \ -n 120 --no-pager ``` Then run `/usr/local/sbin/postgres-restic-backup.sh` manually to expose the first failing command. ### `restic prune` overlaps the nightly backup Move the maintenance timer to a wider low-traffic window. Pruning locks the repository, so a concurrent backup may have to wait or fail depending on timing. ### A restore succeeds but ownership or permissions differ This tutorial deliberately uses `--no-owner --no-privileges` for an isolated structural restore test. If production recovery requires original ownership and grants, recreate the required PostgreSQL roles first and test that recovery path separately. ### You need point-in-time recovery instead of nightly dumps A `pg_dump` archive represents the database at one backup point. For PITR, use PostgreSQL base backups plus continuous WAL archiving or a managed database service that provides the recovery objective you need. PostgreSQL documents this separately under [Continuous Archiving and Point-in-Time Recovery](https://www.postgresql.org/docs/current/continuous-archiving.html). ## Conclusion You now have a PostgreSQL backup to S3 workflow that creates a PostgreSQL-aware logical archive, encrypts it with Restic, stores it outside the source VM, applies retention, keeps expensive repository maintenance out of the nightly backup path, and proves the recovery path with an isolated restore test. For the broader recovery design, read [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps) and [PostgreSQL Replication vs Backups vs Snapshots](/learn/guides/postgresql-replication-vs-backups-vs-snapshots). For the S3 client setup used here, see [Raff Object Storage with AWS CLI](/learn/tutorials/raff-s3-object-storage-aws-cli). Use [Raff Object Storage](/products/object-storage) for portable S3-compatible recovery points and [Raff Data Protection](/products/data-protection) as a separate VM-level recovery layer. Choose the backup frequency and recovery method from your actual RPO and RTO rather than from a generic schedule. --- ### How to Install WireGuard on Ubuntu 24.04 as a Full-Tunnel VPN URL: https://rafftechnologies.com/learn/tutorials/install-wireguard-vpn-ubuntu-24-04 Description: Install WireGuard on Ubuntu 24.04 as a full-tunnel VPN. Configure IPv4 forwarding, NAT, DNS, UFW, AllowedIPs 0.0.0.0/0, and verify public egress. A WireGuard full tunnel routes a client’s IPv4 internet traffic through the VPN server instead of sending only private-network traffic through the tunnel. In this tutorial, you will install WireGuard on Ubuntu 24.04, configure a Raff Technologies Linux VM as the internet gateway, enable forwarding and masquerading, route the client with `AllowedIPs = 0.0.0.0/0`, configure DNS for the tunnel, and verify the public egress path end to end. [Raff Linux VMs](/products/linux-vm) provide the public IPv4 address, Ubuntu environment, and root-level networking control needed for this pattern. The saved test environment for this tutorial remains a Raff Ubuntu 24.04 VM with 1 vCPU and 2 GB RAM. The original full-tunnel workflow was tested there; the routing, DNS, firewall, and key-handling guidance was re-verified against current Ubuntu Server and WireGuard documentation on September 6, 2026 without claiming a new machine test. Ubuntu’s current WireGuard default-gateway documentation describes the same core design used here: the client sends `0.0.0.0/0` through WireGuard, while the gateway server enables IPv4 forwarding and masquerades the VPN subnet onto its public interface. > **IPv4 scope:** This tutorial creates an IPv4 full tunnel. `AllowedIPs = 0.0.0.0/0` does not cover IPv6. If the client has working IPv6, configure an IPv6 WireGuard path separately or disable that path before claiming all network traffic is tunneled. ### Full tunnel vs private-access WireGuard | Design | Client `AllowedIPs` | Server forwarding/NAT | Result | |---|---|---|---| | Full tunnel — this tutorial | `0.0.0.0/0` | Required | Client IPv4 internet traffic exits through the VPN server | | Private/split tunnel | VPN/private subnet only | Not required when accessing only the WireGuard server | Normal internet traffic stays on the client’s local connection | If you only need private SSH or service access, use [Set Up WireGuard on Ubuntu 24.04 for Private Access](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04) instead. Keeping the two designs separate avoids adding forwarding and NAT when they are not needed. Prerequisites: - An Ubuntu 24.04 server with a public IPv4 address - SSH and sudo access with a working recovery path - A Linux, macOS, Windows, Android, or iOS WireGuard client - UDP port `51820` reachable through the firewall protecting the VM - A VPN subnet that does not overlap the client or server networks - A DNS resolver you want the client to use while the tunnel is active This tutorial uses: | Item | Value | |---|---| | Server WireGuard interface | `wg0` | | VPN subnet | `10.90.90.0/24` | | Server tunnel IP | `10.90.90.1/24` | | First client tunnel IP | `10.90.90.2/32` | | WireGuard listener | `51820/udp` | | Example DNS resolver | `1.1.1.1` | ## Step 1 — Verify Ubuntu, the public interface, and the VPN subnet Confirm the operating system and current IPv4 routes: ```bash cat /etc/os-release ip -4 addr ip -4 route ``` Find the interface Ubuntu uses for its default IPv4 route: ```bash OUT_IFACE="$(ip route show default | awk '/default/ {print $5; exit}')" printf 'Outbound interface: %s\n' "$OUT_IFACE" ``` Typical public-interface names include `eth0`, `ens3`, and similar names. Do not hardcode `eth0` before checking the real VM. Verify that the proposed WireGuard subnet does not already exist on the server: ```bash ip -4 route | grep '10\.90\.90\.0/24' || true ``` Run an equivalent route check on the client. If either side already uses `10.90.90.0/24`, choose another RFC1918 subnet and replace it consistently throughout the tutorial. **Verify:** Ubuntu should report 24.04, `OUT_IFACE` should resolve to the real public/default-route interface, and the proposed VPN subnet should not overlap an existing route. ## Step 2 — Install WireGuard on Ubuntu 24.04 Install WireGuard and the utilities used for the gateway rules, firewall check, and verification: ```bash sudo apt update sudo apt install -y wireguard iptables ufw curl ``` Verify the userspace tools: ```bash wg --version wg-quick --help 2>&1 | head ``` Load the kernel module as a diagnostic check: ```bash sudo modprobe wireguard lsmod | grep '^wireguard' || true ``` Ubuntu’s standard kernel includes WireGuard support, while the `wireguard` package provides tools such as `wg` and `wg-quick`. **Verify:** `wg --version` and `wg-quick` should run successfully before you create keys or interfaces. ## Step 3 — Generate the server key pair without embedding the private key in the config Create the WireGuard directory and generate a protected private key: ```bash sudo install -d -m 700 /etc/wireguard sudo sh -c 'umask 077; wg genkey > /etc/wireguard/wg0.key' sudo sh -c 'wg pubkey < /etc/wireguard/wg0.key > /etc/wireguard/wg0.pub' ``` Set explicit ownership and permissions: ```bash sudo chown root:root /etc/wireguard/wg0.key /etc/wireguard/wg0.pub sudo chmod 600 /etc/wireguard/wg0.key sudo chmod 644 /etc/wireguard/wg0.pub ``` Display only the public key: ```bash sudo cat /etc/wireguard/wg0.pub ``` Check file permissions without exposing the secret: ```bash sudo stat -c '%a %U:%G %n' \ /etc/wireguard/wg0.key \ /etc/wireguard/wg0.pub ``` The private key remains in `/etc/wireguard/wg0.key`. The server configuration will load it at interface startup rather than storing the private key directly inside text you may later inspect while troubleshooting. **Verify:** `/etc/wireguard/wg0.key` should be owned by root and mode `600`. Never paste or screenshot that private key. ## Step 4 — Enable IPv4 forwarding on the VPN gateway A full-tunnel server must forward packets from the WireGuard interface to the public network interface. Create a dedicated sysctl file: ```bash sudo tee /etc/sysctl.d/70-wireguard-routing.conf > /dev/null <<'EOF' net.ipv4.ip_forward = 1 EOF ``` Apply it immediately: ```bash sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf ``` Verify the runtime value: ```bash sysctl net.ipv4.ip_forward ``` Expected output: ```text net.ipv4.ip_forward = 1 ``` Forwarding only allows the server to route packets. The next step adds the source-NAT rule required for the client’s private `10.90.90.0/24` address to reach the public internet through the server. **Verify:** `net.ipv4.ip_forward` must equal `1` before the server can act as an IPv4 gateway. ## Step 5 — Configure the WireGuard server with forwarding and scoped masquerading Detect the public interface again: ```bash OUT_IFACE="$(ip route show default | awk '/default/ {print $5; exit}')" printf '%s\n' "$OUT_IFACE" ``` Create `/etc/wireguard/wg0.conf`: ```bash sudo tee /etc/wireguard/wg0.conf > /dev/null < /etc/wireguard/wg0.key' sudo sh -c 'wg pubkey < /etc/wireguard/wg0.key > /etc/wireguard/wg0.pub' sudo chmod 600 /etc/wireguard/wg0.key sudo chmod 644 /etc/wireguard/wg0.pub ``` Display only the client public key: ```bash sudo cat /etc/wireguard/wg0.pub ``` Windows, macOS, Android, and iOS users can generate the peer keys in the official WireGuard application and use the same addresses and peer values shown below. **Verify:** Only the client public key should be copied to the server. The client private key remains protected on the client device. ## Step 8 — Add the client peer to the server On the server, paste the **client public key** into a temporary shell variable: ```bash CLIENT_PUBLIC_KEY='PASTE_CLIENT_PUBLIC_KEY_HERE' ``` Append the peer block: ```bash sudo tee -a /etc/wireguard/wg0.conf > /dev/null < /dev/null <<'EOF' [Interface] Address = 10.90.90.2/24 PostUp = wg set %i private-key /etc/wireguard/%i.key PostUp = resolvectl dns %i 1.1.1.1; resolvectl domain %i '~.' PostDown = resolvectl revert %i [Peer] PublicKey = SERVER_PUBLIC_KEY Endpoint = SERVER_PUBLIC_IP:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 EOF sudo chmod 600 /etc/wireguard/wg0.conf ``` Replace both placeholders before continuing. `AllowedIPs = 0.0.0.0/0` tells `wg-quick` to send all IPv4 destinations through this peer. On Linux, `wg-quick` implements the default-route behavior with policy routing so the WireGuard endpoint itself remains reachable outside the tunnel. The `resolvectl` commands make `1.1.1.1` the DNS resolver for the WireGuard link and set `~.` so DNS queries prefer that link while the full tunnel is active. Replace `1.1.1.1` with another resolver if your policy requires one. `PersistentKeepalive = 25` is useful when the client sits behind NAT or a stateful firewall and needs to keep its mapping alive. WireGuard documents 25 seconds as a sensible interval for that case; omit it when you do not need persistent reachability. On Windows, macOS, Android, or iOS, use the official WireGuard application and set the peer to `AllowedIPs = 0.0.0.0/0`. Use the application’s DNS field for your selected resolver instead of the Linux `resolvectl` lines. **Verify:** The client configuration should have `10.90.90.2/24`, the real server endpoint, `0.0.0.0/0`, and a deliberate DNS path for the full tunnel. ## Step 11 — Bring up the client and verify the full-tunnel route Start the Linux client interface: ```bash sudo wg-quick up wg0 ``` Inspect its address and peer state: ```bash ip -brief addr show wg0 sudo wg show wg0 ``` Inspect the policy-routing rules that `wg-quick` created: ```bash ip rule list ip route list table 51820 2>/dev/null || true ``` A typical full-tunnel setup shows a dedicated policy-routing table containing a default route through `wg0`. If table `51820` is already in use on the client, `wg-quick` can choose another table number; the `ip rule` output reveals the active policy. Inspect DNS routing on the WireGuard link: ```bash resolvectl status wg0 ``` Expected state includes the configured resolver and a route-only domain of `~.`. **Verify:** `wg0` should be up with `10.90.90.2/24`; WireGuard policy routing should contain the IPv4 default route; and DNS should be assigned to the WireGuard link. ## Step 12 — Verify the full-tunnel VPN end to end From the client, reach the server’s tunnel address: ```bash ping -c 4 10.90.90.1 ``` Check the client’s public IPv4 address: ```bash curl -4s https://icanhazip.com ``` The result should match the VPN server’s public IPv4 address. Inspect the WireGuard handshake and transfer counters on the client: ```bash sudo wg show wg0 ``` On the server, inspect the peer as well: ```bash sudo wg show wg0 ``` A working peer should report a recent handshake and increasing transfer counters. Verify DNS still resolves while the tunnel is active: ```bash resolvectl query example.com getent hosts example.com ``` If the client has IPv6 connectivity, test that path separately: ```bash curl -6 --connect-timeout 5 https://icanhazip.com \ || echo 'No working IPv6 path' ``` If the IPv6 request succeeds, that traffic is outside this IPv4-only tunnel. Do not describe the setup as an all-protocol tunnel until IPv6 is handled explicitly. :::cta Deploy Your Server Deploy an Ubuntu 24.04 VM as the public endpoint for a WireGuard full-tunnel VPN. ::: **Verify:** The tunnel address should respond, the client public IPv4 should match the server, both peers should show a recent handshake, traffic counters should increase, and DNS should resolve through the configured tunnel DNS path. ## Step 13 — Verify reboot persistence The server interface is already enabled through `wg-quick@wg0`. During a safe maintenance window, reboot the server: ```bash sudo reboot ``` After reconnecting, verify: ```bash systemctl is-active wg-quick@wg0 ip -brief addr show wg0 sudo wg show wg0 sudo iptables -t nat -S POSTROUTING | grep '10.90.90.0/24' ``` Reconnect the client if needed: ```bash sudo wg-quick down wg0 2>/dev/null || true sudo wg-quick up wg0 ``` Repeat the egress check: ```bash curl -4s https://icanhazip.com ``` **Verify:** The server should recreate the WireGuard interface and NAT rule after reboot, and the client should again exit through the server’s public IPv4 address. ## Step 14 — Add or revoke client peers safely Give every client a unique key pair and a unique `/32` tunnel address, for example: ```text 10.90.90.2/32 laptop 10.90.90.3/32 phone 10.90.90.4/32 workstation ``` Add each public key as a separate `[Peer]` block in `/etc/wireguard/wg0.conf`. After saving a peer-only change, apply the saved WireGuard settings without dropping the interface: ```bash sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)' sudo wg show wg0 ``` `wg syncconf` updates the runtime WireGuard configuration while preserving peer sessions as much as possible. If you changed interface-level settings such as addresses, routing hooks, or NAT commands rather than only peer data, use a controlled `wg-quick` restart during a maintenance window instead. To revoke a device, remove its peer block from the saved configuration and run the same `wg syncconf` command. Rotate a peer immediately if its private key may have been exposed. Do not reuse client private keys across devices. **Verify:** Every active device should have one unique public key and one unique tunnel address; revoked peers should disappear from `wg show wg0` after the sync. ## Cleanup and rollback Disconnect the Linux client: ```bash sudo wg-quick down wg0 ``` To stop the server tunnel without deleting its configuration: ```bash sudo systemctl disable --now wg-quick@wg0 ``` Confirm the interface and NAT rule are gone: ```bash ip link show wg0 2>/dev/null || echo 'wg0 is down' sudo iptables -t nat -S POSTROUTING | grep '10.90.90.0/24' \ || echo 'WireGuard NAT rule removed' ``` If the VM no longer needs to accept WireGuard connections, remove the matching UFW rule by rule number or exact rule only after confirming no client still depends on it. Keep `/etc/wireguard/wg0.key` if you intend to restore the same server identity. Securely destroy private keys only when the peer is permanently decommissioned. ## Troubleshooting ### No WireGuard handshake appears On the server, check the listener, firewall, and saved peer: ```bash sudo systemctl status wg-quick@wg0 --no-pager sudo wg show wg0 sudo ss -lun | grep ':51820' sudo ufw status numbered ``` On the client, verify that `Endpoint` uses the current server public IP/DNS name and UDP port `51820`. Confirm the client public key on the server and server public key on the client are not swapped or stale. ### The handshake works but internet access fails Check forwarding, the public interface, and NAT: ```bash sysctl net.ipv4.ip_forward OUT_IFACE="$(ip route show default | awk '/default/ {print $5; exit}')" printf 'Outbound interface: %s\n' "$OUT_IFACE" sudo iptables -S FORWARD | grep '10.90.90.0/24' sudo iptables -t nat -S POSTROUTING | grep '10.90.90.0/24' ``` Expected state includes `net.ipv4.ip_forward = 1`, the correct public interface, matching forwarding rules, and a scoped MASQUERADE rule. ### The client connects but DNS fails First verify raw IP connectivity: ```bash ping -c 2 1.1.1.1 ``` Then inspect the WireGuard DNS link: ```bash systemctl is-active systemd-resolved resolvectl status wg0 resolvectl query example.com ``` If raw IP works while DNS fails, the WireGuard tunnel and NAT path are functioning and the remaining problem is DNS configuration. ### The client still uses a local DNS resolver Inspect: ```bash resolvectl status ``` For the Linux configuration in this tutorial, the `wg0` link should have your selected resolver and route-only domain `~.`. Ubuntu’s current default-gateway documentation treats DNS routing as a separate part of preventing information from escaping the intended full-tunnel path. ### The client loses access to its local LAN That is a normal consequence of a full-tunnel default route. If the client must continue reaching a local printer, NAS, router, or private subnet, create deliberate route exceptions or use the [private-access WireGuard tutorial](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04) instead. ### Some websites load slowly or not at all Check the tunnel handshake and try a path-MTU test before changing MTU blindly: ```bash sudo wg show wg0 ping -M do -s 1372 -c 3 1.1.1.1 ``` If large packets fail while smaller packets work, investigate the path MTU between the client and gateway. Set an explicit WireGuard `MTU` only after measuring a value that works for the actual network. ### `wg-quick up wg0` says the interface already exists Inspect it before deleting anything: ```bash ip link show wg0 sudo wg show wg0 ``` If it is the intended interface, bring it down cleanly and retry: ```bash sudo wg-quick down wg0 sudo wg-quick up wg0 ``` ### IPv4 is tunneled but IPv6 still exposes the client network This tutorial routes only `0.0.0.0/0`. Test IPv6 independently: ```bash curl -6 --connect-timeout 5 https://icanhazip.com ``` If it succeeds, either configure an IPv6 tunnel and gateway path or disable IPv6 on the client/network according to your policy. Do not add `::/0` until the server has the IPv6 addressing, forwarding, firewall, and routing needed to carry that traffic correctly. ## Conclusion You now have a WireGuard full-tunnel VPN on Ubuntu 24.04: the client uses `AllowedIPs = 0.0.0.0/0`, `wg-quick` installs the Linux policy-routing rules, the server forwards and masquerades the VPN subnet, and DNS is deliberately routed with the tunnel rather than left as an afterthought. This page should be used when the VM is meant to become the client’s IPv4 internet gateway. For private-only administration or service access, use [Set Up WireGuard on Ubuntu 24.04 for Private Access](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04). For broader cloud-to-cloud or network-to-network designs, review [Raff VPC](/products/vpc). ## Sources - [Ubuntu Server — Using the VPN as the default gateway](https://ubuntu.com/server/docs/how-to/wireguard-vpn/vpn-as-the-default-gateway/) - [Ubuntu Server — Introduction to WireGuard VPN](https://ubuntu.com/server/docs/explanation/intro-to/wireguard-vpn/) - [Ubuntu Server — WireGuard VPN](https://ubuntu.com/server/docs/how-to/wireguard-vpn/) - [WireGuard — Quick Start](https://www.wireguard.com/quickstart/) - [WireGuard — Installation](https://www.wireguard.com/install/) - Guidance re-verified: 2026-09-06 --- ### How to Install Nextcloud on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-nextcloud-ubuntu-24-04 Description: Install Nextcloud 34 on Ubuntu 24.04 with Apache, MariaDB, PHP 8.3, HTTPS, Redis, cron, backup checks, and secure production guidance. In this tutorial, you will install Nextcloud on Ubuntu 24.04 with Apache, MariaDB, PHP 8.3, HTTPS, cron background jobs, APCu caching, Redis file locking, and an application-consistent backup check. Nextcloud is a self-hosted file sync, sharing, and collaboration platform. This tutorial uses the classic manual installation path on a [Raff Linux VM](/products/linux-vm): Ubuntu 24.04, Apache, MariaDB, PHP 8.3, Redis, and the official Nextcloud server archive. Nextcloud’s current administration manual still documents Ubuntu 24.04 as a supported platform and provides a dedicated Apache/MariaDB installation example for it. As of September 6, 2026, the current stable Nextcloud 34 maintenance release is **34.0.3**. This page intentionally follows the stable 34 branch rather than a prerelease branch. The previous Nextcloud 32 workflow was tested on a Raff Ubuntu 24.04 VM with 2 vCPU, 4 GB RAM, and 80 GB storage. The Nextcloud 34.0.3 installation, caching, cron, backup, and restore guidance in this revision was re-verified against current Nextcloud documentation; a fresh 34.0.3 end-to-end Raff machine test is still required before claiming a new full test pass. Prerequisites: - A Raff Ubuntu 24.04 VM with at least 2 vCPU and 4 GB RAM for this tutorial baseline - SSH access with a sudo-capable user and a recovery path in case firewall changes affect SSH - A domain or subdomain pointed to the VM public IPv4 address - Ports `80/tcp` and `443/tcp` available - A strong Nextcloud admin password and a separate strong MariaDB password stored in a password manager - Enough storage for the files you expect users to sync, plus backup headroom If you plan to keep user data on a separate [Raff Volume](/products/volumes), attach, format, mount, and verify that volume **before** Step 5, then use the mounted path as the Nextcloud data directory. Do not move a live data directory onto another filesystem casually after users have started storing files. ![Raff VM creation screen selecting Ubuntu 24.04 for a Nextcloud server](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_00_raff_vm_ubuntu_selection_webp_e716a57cbc.png) > Replace `cloud.your-domain.com` with your real domain throughout the tutorial. ## Step 1 — Update Ubuntu 24.04 and verify the server Update the package index and installed packages: ```bash sudo apt update sudo apt upgrade -y sudo apt install -y curl wget bzip2 unzip ca-certificates dnsutils ufw snapd rsync ``` Verify the operating system and available resources: ```bash lsb_release -ds nproc free -h lsblk ``` Expected state includes Ubuntu 24.04 LTS, at least 2 vCPU, and about 4 GB RAM for this tutorial baseline. If the upgrade installed a new kernel and `/var/run/reboot-required` exists, reboot before continuing: ```bash if [ -f /var/run/reboot-required ]; then echo "Reboot required before continuing" fi ``` **Verify:** Ubuntu should report 24.04, the expected CPU/RAM/storage should be visible, and no pending reboot should be ignored before you build the application stack. ## Step 2 — Install Apache, MariaDB, PHP 8.3, Redis, and required modules Install the web server, database, PHP runtime, Redis, and the PHP modules used by Nextcloud: ```bash sudo apt install -y apache2 mariadb-server redis-server \ libapache2-mod-php8.3 \ php8.3 php8.3-cli php8.3-common php8.3-mysql php8.3-gd \ php8.3-curl php8.3-mbstring php8.3-intl php8.3-gmp \ php8.3-bcmath php8.3-xml php8.3-zip php8.3-imagick \ php8.3-apcu php8.3-redis ``` Enable and start the services: ```bash sudo systemctl enable --now apache2 sudo systemctl enable --now mariadb sudo systemctl enable --now redis-server ``` Verify service state and PHP modules: ```bash systemctl is-active apache2 systemctl is-active mariadb systemctl is-active redis-server php -v | head -n 1 php -m | grep -Ei 'curl|gd|mbstring|intl|gmp|xml|zip|imagick|apcu|redis|pdo_mysql' ``` Nextcloud 34 supports Ubuntu 24.04 and PHP 8.3. On a single-server installation, APCu is appropriate for local cache while Redis can handle distributed caching and transactional file locking. **Verify:** Apache, MariaDB, and Redis should all be active, PHP should report `8.3.x`, and the required PHP extensions should appear in the module list. ## Step 3 — Configure firewall access without risking SSH lockout Inspect UFW before changing its state: ```bash sudo ufw status verbose ``` If UFW is already active, allow HTTP and HTTPS: ```bash sudo ufw allow 'Apache Full' sudo ufw status numbered ``` If UFW is **inactive**, do not blindly run `ufw enable` from a single remote SSH session. First confirm the real SSH port used by the server, create the matching allow rule, and keep a second SSH session or console/recovery path available. The dedicated [UFW tutorial](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) covers a lockout-safe activation sequence. For a server using the standard SSH port, the rule is commonly: ```bash sudo ufw allow OpenSSH ``` Only after confirming that the SSH rule matches your actual configuration should you enable UFW: ```bash sudo ufw enable sudo ufw status numbered ``` Confirm the domain resolves to the Raff VM: ```bash dig +short cloud.your-domain.com A ``` Compare the returned address with the VM public IPv4 address. Do not continue to certificate issuance until DNS points to the correct server. **Verify:** Your existing SSH administration path must still work, Apache HTTP/HTTPS must be permitted, and the domain must resolve to the correct VM. ## Step 4 — Configure MariaDB for Nextcloud and create the database Nextcloud requires the `READ COMMITTED` transaction isolation level for MySQL/MariaDB deployments and expects InnoDB. When binary logging is enabled, row-based logging is the compatible choice. Create a dedicated MariaDB configuration file: ```bash sudo tee /etc/mysql/mariadb.conf.d/60-nextcloud.cnf > /dev/null <<'EOF' [mysqld] transaction-isolation = READ-COMMITTED binlog_format = ROW innodb_file_per_table = 1 EOF ``` Restart MariaDB: ```bash sudo systemctl restart mariadb ``` Verify the database settings: ```bash sudo mariadb -NBe "SELECT @@tx_isolation, @@binlog_format, @@innodb_file_per_table;" ``` Expected values include: ```text READ-COMMITTED ROW 1 ``` Before running the next block, replace `REPLACE_WITH_A_STRONG_DATABASE_PASSWORD` with a unique password from your password manager: ```bash sudo mariadb <<'SQL' CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER IF NOT EXISTS 'nextclouduser'@'localhost' IDENTIFIED BY 'REPLACE_WITH_A_STRONG_DATABASE_PASSWORD'; GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextclouduser'@'localhost'; FLUSH PRIVILEGES; SQL ``` Verify the database and account without exposing the password: ```bash sudo mariadb -e "SHOW DATABASES LIKE 'nextcloud';" sudo mariadb -e "SELECT User, Host FROM mysql.user WHERE User='nextclouduser';" ``` **Verify:** MariaDB should use `READ-COMMITTED`, database `nextcloud` should exist, and `nextclouduser@localhost` should be present. ## Step 5 — Download and install the stable Nextcloud 34 archive Download the current maintenance release from the stable Nextcloud 34 branch and its SHA-256 checksum file: ```bash cd /tmp curl -fLO https://download.nextcloud.com/server/releases/latest-34.tar.bz2 curl -fsSLo latest-34.tar.bz2.sha256 \ https://download.nextcloud.com/server/releases/latest-34.tar.bz2.sha256 ``` Verify the archive before extracting it: ```bash EXPECTED_SHA256="$(awk '{print $1}' latest-34.tar.bz2.sha256 | head -n 1)" ACTUAL_SHA256="$(sha256sum latest-34.tar.bz2 | awk '{print $1}')" test "$EXPECTED_SHA256" = "$ACTUAL_SHA256" \ && echo "Nextcloud checksum OK" \ || { echo "Checksum mismatch"; exit 1; } ``` Do not extract the archive if the checksum comparison fails. Confirm an existing installation will not be overwritten: ```bash test ! -e /var/www/nextcloud && echo "Install path is clear" ``` Extract the archive and move it into the Apache web directory: ```bash tar -xjf latest-34.tar.bz2 sudo mv nextcloud /var/www/nextcloud ``` Create a data directory outside the web root: ```bash sudo mkdir -p /var/nextcloud-data sudo chown -R www-data:www-data /var/www/nextcloud /var/nextcloud-data ``` If you mounted a separate Raff Volume for user data, use that mounted directory instead of `/var/nextcloud-data` and ensure it is owned by `www-data` before continuing. Check the downloaded Nextcloud version: ```bash sudo grep -E "OC_VersionString" /var/www/nextcloud/version.php ``` As of September 6, 2026, the stable release should report `34.0.3`. If a newer 34.x maintenance release is available when you run the tutorial, use the latest stable 34 maintenance release and review its changelog first. **Verify:** The checksum must match, `/var/www/nextcloud` must contain a stable `34.0.x` installation, and the application/data directories must be owned by `www-data`. ## Step 6 — Configure PHP 8.3 for Nextcloud Set practical limits for this tutorial baseline: ```bash PHP_INI="/etc/php/8.3/apache2/php.ini" sudo sed -i 's/^memory_limit = .*/memory_limit = 512M/' "$PHP_INI" sudo sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 512M/' "$PHP_INI" sudo sed -i 's/^post_max_size = .*/post_max_size = 512M/' "$PHP_INI" sudo sed -i 's/^max_execution_time = .*/max_execution_time = 360/' "$PHP_INI" sudo sed -i 's/^max_input_time = .*/max_input_time = 360/' "$PHP_INI" ``` Give APCu a 128 MB cache allocation and enable APCu for CLI commands used by `occ`: ```bash sudo tee /etc/php/8.3/apache2/conf.d/99-nextcloud-apcu.ini > /dev/null <<'EOF' apc.shm_size=128M EOF sudo tee /etc/php/8.3/cli/conf.d/99-nextcloud-apcu.ini > /dev/null <<'EOF' apc.enable_cli=1 EOF ``` Restart Apache: ```bash sudo systemctl restart apache2 ``` Verify the values: ```bash php -i | grep -E 'memory_limit|apc.enable_cli|apc.shm_size' | head systemctl is-active apache2 ``` The 512 MB upload values here are examples for this deployment, not universal Nextcloud requirements. Size them to the file sizes and memory available on your VM. **Verify:** Apache should be active, the intended PHP limits should be visible, and APCu should be enabled for CLI use. ## Step 7 — Configure Apache for Nextcloud Create the virtual host: ```bash sudo tee /etc/apache2/sites-available/nextcloud.conf > /dev/null <<'EOF' ServerName cloud.your-domain.com DocumentRoot /var/www/nextcloud Require all granted AllowOverride All Options FollowSymLinks MultiViews Dav off SetEnv HOME /var/www/nextcloud SetEnv HTTP_HOME /var/www/nextcloud ErrorLog ${APACHE_LOG_DIR}/nextcloud_error.log CustomLog ${APACHE_LOG_DIR}/nextcloud_access.log combined EOF ``` Enable the site and required modules: ```bash sudo a2ensite nextcloud.conf sudo a2dissite 000-default.conf sudo a2enmod rewrite headers env dir mime ssl setenvif ``` Validate and reload Apache: ```bash sudo apache2ctl configtest sudo systemctl reload apache2 ``` Test the HTTP endpoint: ```bash curl -I http://cloud.your-domain.com ``` A `200`, `302`, or `303` response is acceptable before the installation wizard is completed. **Verify:** Apache should report `Syntax OK`, the Nextcloud site should be enabled, and the domain should return an HTTP response from this VM. ## Step 8 — Enable HTTPS with Certbot Install Certbot using its snap package: ```bash sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot ``` Request the certificate and let Certbot configure Apache: ```bash sudo certbot --apache \ -d cloud.your-domain.com \ --redirect \ --agree-tos \ --no-eff-email \ -m admin@your-domain.com ``` Replace the example email address with one you control. Verify HTTPS and certificate renewal: ```bash curl -I https://cloud.your-domain.com sudo certbot renew --dry-run ``` **Verify:** HTTPS should respond successfully and the Certbot renewal simulation should complete without errors. ## Step 9 — Complete the Nextcloud web setup Open: ```text https://cloud.your-domain.com ``` The Nextcloud setup page should appear. ![Nextcloud setup page on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_01_setup_page_webp_377711610d.png) Create a strong Nextcloud administrator account. Do not reuse the MariaDB password. Use these database values: ```text Data folder: /var/nextcloud-data Database user: nextclouduser Database password: the password created in Step 4 Database name: nextcloud Database host: localhost ``` If you mounted a separate volume for the data directory, enter that verified mount path instead of `/var/nextcloud-data`. Complete the installation. After the dashboard appears, verify the server from SSH: ```bash cd /var/www/nextcloud sudo -u www-data php occ status sudo -u www-data php occ config:system:get trusted_domains ``` Expected state includes: ```text installed: true version: 34.0.x ``` If the domain is missing from `trusted_domains`, add it: ```bash sudo -u www-data php occ config:system:set trusted_domains 1 \ --value=cloud.your-domain.com ``` ![Nextcloud dashboard after first login on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_02_dashboard_webp_3acf1f034d.png) **Verify:** The dashboard should load over HTTPS, `occ status` should report `installed: true`, and the real hostname should be present in `trusted_domains`. ## Step 10 — Configure cron, APCu, and Redis file locking Configure Nextcloud background jobs to run with cron every five minutes under the web-server user: ```bash sudo -u www-data crontab -l 2>/dev/null | grep -v '/var/www/nextcloud/cron.php' | \ { cat; echo '*/5 * * * * php -f /var/www/nextcloud/cron.php'; } | \ sudo -u www-data crontab - ``` Run the job once and set cron mode: ```bash cd /var/www/nextcloud sudo -u www-data php -f cron.php sudo -u www-data php occ background:cron ``` Configure APCu as the local cache: ```bash sudo -u www-data php occ config:system:set memcache.local \ --value='\OC\Memcache\APCu' ``` Configure Redis for distributed caching and transactional file locking: ```bash sudo -u www-data php occ config:system:set memcache.distributed \ --value='\OC\Memcache\Redis' sudo -u www-data php occ config:system:set memcache.locking \ --value='\OC\Memcache\Redis' sudo -u www-data php occ config:system:set redis host --value=127.0.0.1 sudo -u www-data php occ config:system:set redis port --type=integer --value=6379 ``` Set a maintenance window start hour in UTC: ```bash sudo -u www-data php occ config:system:set maintenance_window_start \ --type=integer --value=1 ``` Verify the configuration: ```bash redis-cli ping sudo -u www-data php occ config:system:get memcache.local sudo -u www-data php occ config:system:get memcache.locking sudo -u www-data crontab -l ``` Expected state includes `PONG`, APCu local caching, Redis locking, and a cron job every five minutes. **Verify:** Redis must respond, Nextcloud must report the intended cache classes, and the `www-data` cron entry must exist. ## Step 11 — Verify Nextcloud end to end Open the Nextcloud admin overview: ```text Profile icon → Administration settings → Overview ``` ![Nextcloud administration overview showing setup checks](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_03_admin_overview_webp_f408b3257c.png) Resolve warnings that are specific to your environment before storing important data. Open the **Files** app and upload a small file named: ```text raff-nextcloud-test.txt ``` Suggested content: ```text Hello from Nextcloud on a Raff Ubuntu 24.04 VM. ``` ![Nextcloud Files app showing an uploaded test file](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_04_file_upload_webp_ca45658c3a.png) Confirm the browser reports a secure HTTPS connection. ![Browser HTTPS padlock for Nextcloud on Ubuntu 24.04](https://raff-images.s3.raffusercloud.com/nextcloud_ubuntu_24_04_05_https_padlock_webp_ba72800bd8.png) Run the server-side checks: ```bash systemctl is-active apache2 systemctl is-active mariadb systemctl is-active redis-server cd /var/www/nextcloud sudo -u www-data php occ status sudo -u www-data php occ config:system:get maintenance_window_start curl -I https://cloud.your-domain.com sudo ufw status numbered ``` End-to-end installation verification requires all of the following: - Apache, MariaDB, and Redis are active - Nextcloud reports `installed: true` - The installed version is in the stable `34.0.x` line - The dashboard loads over HTTPS - The admin overview opens - The test file uploads successfully - Cron, APCu, and Redis file locking are configured - The firewall preserves your administration path and permits the intended web traffic :::cta Deploy Your Server Deploy an Ubuntu 24.04 VM for your self-hosted Nextcloud server. ::: ## Step 12 — Create and verify an application-consistent Nextcloud backup A VM snapshot alone is not the same thing as an application-consistent Nextcloud backup. Nextcloud’s backup documentation requires the database, data directory, configuration, and relevant application/theme files to be recoverable together. Create a dated backup directory: ```bash STAMP="$(date +%Y%m%d-%H%M%S)" BACKUP_ROOT="/var/backups/nextcloud/$STAMP" sudo mkdir -p "$BACKUP_ROOT" echo "$BACKUP_ROOT" ``` Put Nextcloud into maintenance mode so files and database state do not continue changing during the backup: ```bash cd /var/www/nextcloud sudo -u www-data php occ maintenance:mode --on ``` Copy the entire Nextcloud application tree and data directory. Copying the application tree captures `config/` plus any installed custom app/theme files stored there: ```bash sudo rsync -Aax /var/www/nextcloud/ "$BACKUP_ROOT/nextcloud-app/" sudo rsync -Aax /var/nextcloud-data/ "$BACKUP_ROOT/nextcloud-data/" ``` If your data directory is on a separate mounted Raff Volume, replace `/var/nextcloud-data/` with that actual path. Dump the MariaDB database with a transaction-consistent dump and utf8mb4 support: ```bash sudo mariadb-dump \ --single-transaction \ --default-character-set=utf8mb4 \ nextcloud | sudo tee "$BACKUP_ROOT/nextcloud.sql" > /dev/null ``` Turn maintenance mode off after the backup commands complete: ```bash cd /var/www/nextcloud sudo -u www-data php occ maintenance:mode --off ``` If any backup command fails, correct the failure and explicitly check maintenance mode before allowing users back in: ```bash sudo -u www-data php occ maintenance:mode ``` Verify that the backup actually contains the critical components: ```bash sudo test -f "$BACKUP_ROOT/nextcloud-app/config/config.php" \ && echo "Config backup present" sudo test -d "$BACKUP_ROOT/nextcloud-data" \ && echo "Data backup present" sudo test -s "$BACKUP_ROOT/nextcloud.sql" \ && echo "Database dump present" sudo du -sh "$BACKUP_ROOT"/* ``` A successful command is only the first half of backup confidence. Periodically restore a backup into an isolated test environment instead of assuming it is recoverable. For a non-destructive **database restore check**, create a temporary database and import the dump there: ```bash RESTORE_DB="nextcloud_restore_test" sudo mariadb -e "DROP DATABASE IF EXISTS ${RESTORE_DB};" sudo mariadb -e "CREATE DATABASE ${RESTORE_DB} CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" sudo mariadb "$RESTORE_DB" < "$BACKUP_ROOT/nextcloud.sql" sudo mariadb -NBe "SELECT COUNT(*) FROM ${RESTORE_DB}.oc_filecache;" ``` If the query returns a count, the SQL dump can at least be imported and read. This does **not** replace a full restore rehearsal: a real recovery test should also restore the matching application/configuration tree and data directory on a disposable VM, use the same Nextcloud version first, load the restored database, and verify user files in the web interface. Remove the temporary restore-test database when finished: ```bash sudo mariadb -e "DROP DATABASE IF EXISTS nextcloud_restore_test;" ``` If you later restore an older Nextcloud backup while synced clients contain newer state, review Nextcloud’s `maintenance:data-fingerprint` guidance before reconnecting clients. **Verify:** The backup is only considered minimally validated when `config.php`, the data directory, and a non-empty SQL dump exist together and the SQL dump imports successfully into an isolated test database. :::cta Explore Data Protection Add infrastructure-layer VM backups and snapshots alongside the application-consistent Nextcloud backup and restore checks you control inside the server. ::: ## Step 13 — Plan upgrades without treating the updater as a backup Before every Nextcloud upgrade, create a fresh application-consistent backup and verify that you can access it. Do not assume the built-in updater protects the live data directory and MariaDB database for you. Check the installed version and update status with: ```bash cd /var/www/nextcloud sudo -u www-data php occ status sudo -u www-data php occ update:check ``` Read the release notes for the target version before upgrading, especially when crossing a major release. Nextcloud does not support arbitrary downgrades, so your rollback plan should be a tested backup/restore path rather than “install the old package again.” **Verify:** Before an upgrade, you should know the current version, target version, backup location, and exact restore procedure. ## Cleanup and rollback For a temporary test deployment, prefer a reversible shutdown before permanent deletion. Enable maintenance mode and stop public access: ```bash cd /var/www/nextcloud sudo -u www-data php occ maintenance:mode --on sudo a2dissite nextcloud.conf sudo apache2ctl configtest sudo systemctl reload apache2 ``` Disable the Nextcloud background job: ```bash sudo -u www-data crontab -l 2>/dev/null | \ grep -v '/var/www/nextcloud/cron.php' | \ sudo -u www-data crontab - ``` Move the application and data directories to a dated holding location instead of deleting them immediately: ```bash STAMP="$(date +%Y%m%d-%H%M%S)" sudo mkdir -p "/var/backups/nextcloud-retired-$STAMP" sudo mv /var/www/nextcloud "/var/backups/nextcloud-retired-$STAMP/" sudo mv /var/nextcloud-data "/var/backups/nextcloud-retired-$STAMP/" ``` If the data directory is on a separate volume, do not run the second `mv`; unmount and preserve that volume according to your storage plan instead. Keep the MariaDB database until you have confirmed that no data or restore test is needed. Permanently delete the database, files, certificate, and storage only after you have a verified backup and intentionally decommission the instance. **Verify:** The public Nextcloud site should be disabled and the application/data should be retained somewhere recoverable until decommissioning is confirmed. ## Troubleshooting ### The setup page cannot connect to MariaDB Verify MariaDB, the database, the user, and the isolation level: ```bash systemctl is-active mariadb sudo mariadb -e "SHOW DATABASES LIKE 'nextcloud';" sudo mariadb -e "SELECT User, Host FROM mysql.user WHERE User='nextclouduser';" sudo mariadb -NBe "SELECT @@tx_isolation, @@binlog_format, @@innodb_file_per_table;" ``` If credentials are wrong, change the MariaDB user password deliberately and update the setup form. Do not reuse the Nextcloud administrator password. ### Apache returns an error or the site does not load Check the site, syntax, logs, and DNS: ```bash systemctl status apache2 --no-pager sudo apache2ctl configtest sudo a2query -s nextcloud dig +short cloud.your-domain.com A sudo tail -n 80 /var/log/apache2/nextcloud_error.log ``` Fix Apache or DNS before rerunning Certbot. ### Certbot cannot issue a certificate Check DNS and HTTP reachability first: ```bash dig +short cloud.your-domain.com A sudo ufw status numbered curl -I http://cloud.your-domain.com ``` The domain must resolve to the correct server and port 80 must be reachable for HTTP validation. ### Nextcloud reports an untrusted domain Add the hostname with `occ`: ```bash cd /var/www/nextcloud sudo -u www-data php occ config:system:set trusted_domains 1 \ --value=cloud.your-domain.com sudo -u www-data php occ config:system:get trusted_domains ``` ### The admin overview reports a database isolation warning Recheck the MariaDB runtime value: ```bash sudo mariadb -NBe "SELECT @@tx_isolation, @@binlog_format;" ``` The isolation level should be `READ-COMMITTED`. If it is not, verify `/etc/mysql/mariadb.conf.d/60-nextcloud.cnf` and restart MariaDB. ### The admin overview reports missing memory cache or file locking Verify Redis, APCu, and the Nextcloud configuration: ```bash redis-cli ping php -m | grep -Ei 'apcu|redis' cd /var/www/nextcloud sudo -u www-data php occ config:system:get memcache.local sudo -u www-data php occ config:system:get memcache.locking ``` For this single-server design, APCu handles local cache while Redis handles transactional file locking and distributed cache. ### Background jobs are not running Inspect the `www-data` crontab and run `cron.php` manually: ```bash sudo -u www-data crontab -l cd /var/www/nextcloud sudo -u www-data php -f cron.php sudo -u www-data php occ status ``` The cron entry should run `cron.php` every five minutes. ### Large uploads fail Verify PHP limits and data-directory ownership: ```bash PHP_INI="/etc/php/8.3/apache2/php.ini" grep -E '^(memory_limit|upload_max_filesize|post_max_size|max_execution_time|max_input_time)' "$PHP_INI" ls -ld /var/nextcloud-data ``` If the data directory uses a separate mounted volume, inspect that path instead. After PHP changes, restart Apache and retest the upload. ### The backup exists but the restore fails Make sure you are restoring the **matching** configuration, data directory, and database from the same backup point. A database dump by itself is not a complete Nextcloud recovery source, and a VM snapshot taken at an arbitrary moment is not proof of application consistency. For MariaDB restoration, Nextcloud’s documented pattern is to restore into a clean database and then import the dump. Test that workflow on a disposable server before you need it during an incident. ## Conclusion You now have a manual Nextcloud 34 installation on Ubuntu 24.04 with Apache, MariaDB configured for `READ COMMITTED`, PHP 8.3, HTTPS, cron background jobs, APCu local caching, Redis transactional file locking, and a verified application-consistent backup workflow. The installation URL remains useful for users who want direct control of the web server, database, PHP configuration, filesystem, and backup process. Before storing important data, complete the end-to-end checks and perform a full restore rehearsal on an isolated VM. Continue with [How to Secure Your Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server), [Automate Backups with cron and rsync on Ubuntu 24.04](/learn/tutorials/automate-backups-cron-rsync-ubuntu-24-04), and [Set Up UFW Firewall on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) for the surrounding operating practices. ## Sources - [Nextcloud — Download and install](https://nextcloud.com/install/) - [Nextcloud 34 Administration Manual — Example installation on Ubuntu 24.04 LTS](https://docs.nextcloud.com/server/stable/admin_manual/installation/example_ubuntu.html) - [Nextcloud 34 Administration Manual — System requirements](https://docs.nextcloud.com/server/stable/admin_manual/installation/system_requirements.html) - [Nextcloud 34 Administration Manual — Backup](https://docs.nextcloud.com/server/stable/admin_manual/maintenance/backup.html) - [Nextcloud 34 Administration Manual — Restoring backup](https://docs.nextcloud.com/server/stable/admin_manual/maintenance/restore.html) - Guidance re-verified: 2026-09-06 --- ### How to Install PostgreSQL on Ubuntu 24.04 URL: https://rafftechnologies.com/learn/tutorials/install-postgresql-ubuntu-24-04 Description: Install PostgreSQL 18 on Ubuntu 24.04 with PGDG. Create a database and role, verify SCRAM and local-only access, then test backup and restore. To install PostgreSQL on Ubuntu 24.04, first decide which major version you need. Ubuntu 24.04’s standard `postgresql` package installs PostgreSQL 16, while the official PostgreSQL Apt repository (PGDG) provides newer supported majors. This tutorial uses PGDG to install **PostgreSQL 18**, whose current maintenance release is **18.6** as of September 7, 2026. On **Raff Technologies**, this setup is for teams that want a self-hosted PostgreSQL server with operating-system and database control on a [Linux VM](/products/linux-vm). If you would rather offload provisioning, patching, backups, and routine database operations, compare this path with [Raff Managed PostgreSQL](/products/managed-databases/postgresql) before you deploy. The shortest PostgreSQL 18 install path on Ubuntu 24.04 is: ```bash sudo apt update sudo apt install -y postgresql-common sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh sudo apt install -y postgresql-18 postgresql-client-18 ``` This tutorial goes further: you will verify the repository and running version, create an application database and role, confirm SCRAM authentication, keep PostgreSQL private to the VM, run an authenticated CRUD test, and perform a logical backup/restore smoke test. > **Ubuntu repository vs PGDG:** `sudo apt install postgresql` is valid and installs Ubuntu’s maintained PostgreSQL 16 package on Ubuntu 24.04. Use the PGDG steps below when you specifically want PostgreSQL 18 and its PostgreSQL-project maintenance stream. ## Prerequisites - An Ubuntu 24.04 LTS server; this workflow was originally tested on a Raff 2 vCPU / 4 GB RAM Linux VM - SSH access with a sudo-capable user - A recovery or console path before making firewall changes - At least 2 GB RAM for development/light workloads; production sizing should be based on measured connections, working set, query load, storage, and recovery requirements - A unique application database password stored outside source code - A backup plan before modifying an existing PostgreSQL installation This revision keeps PostgreSQL bound to loopback. Applications on the same VM connect through `127.0.0.1`; port `5432` is not opened to the public internet. ## Step 1 — Update Ubuntu 24.04 and verify the release Update installed packages: ```bash sudo apt update sudo apt upgrade -y ``` Install the packages used by the official PostgreSQL repository workflow and later checks: ```bash sudo apt install -y curl ca-certificates postgresql-common ``` Verify the Ubuntu release: ```bash . /etc/os-release printf '%s\n%s\n' "$PRETTY_NAME" "$VERSION_CODENAME" ``` Expected values include: ```text Ubuntu 24.04 LTS noble ``` If `/var/run/reboot-required` exists after the upgrade, reboot before installing PostgreSQL: ```bash if [ -f /var/run/reboot-required ]; then echo "Reboot required before continuing" fi ``` **Verify:** the server should be Ubuntu 24.04 with codename `noble`, packages should be current, and any required reboot should be handled before the database installation. ## Step 2 — Add the official PostgreSQL Apt repository The PostgreSQL project documents an automated PGDG repository setup through `postgresql-common`: ```bash sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh ``` This adds the PostgreSQL Apt repository for the detected Ubuntu release and refreshes package metadata. Verify the configured source: ```bash grep -R "apt.postgresql.org" \ /etc/apt/sources.list.d/pgdg.list \ /etc/apt/sources.list.d/pgdg.sources 2>/dev/null ``` Expected output should reference both: ```text apt.postgresql.org noble-pgdg ``` Confirm that PostgreSQL 18 is available before installing it: ```bash apt-cache policy postgresql-18 | sed -n '1,14p' ``` You should see a non-empty `Candidate` version from the PGDG repository. **Verify:** the repository must resolve to `apt.postgresql.org`, target `noble-pgdg`, and expose a PostgreSQL 18 candidate package. ## Step 3 — Install PostgreSQL 18 and verify the maintenance release Install the PostgreSQL 18 server and matching client: ```bash sudo apt install -y postgresql-18 postgresql-client-18 ``` Verify the client major version: ```bash psql --version ``` Expected format: ```text psql (PostgreSQL) 18.x ``` List database clusters managed by Ubuntu’s PostgreSQL tooling: ```bash pg_lsclusters ``` A new installation normally includes an `18/main` cluster on port `5432`: ```text Ver Cluster Port Status Owner Data directory 18 main 5432 online postgres /var/lib/postgresql/18/main ``` Query the actual server version rather than assuming it from the package name: ```bash sudo -u postgres psql -tAc "SHOW server_version;" ``` As of September 7, 2026, the current stable PostgreSQL 18 maintenance release is `18.6`. PostgreSQL 18.5 was never released; 18.6 followed 18.4. A future maintenance update may therefore report a later `18.x` version when you run these commands. If another major PostgreSQL version already exists, stop here and review `pg_lsclusters` before changing ports, packages, or data directories. **Verify:** `psql` and the running server should both be PostgreSQL 18, and `pg_lsclusters` should show the intended cluster online. ## Step 4 — Verify service health and local readiness Check the cluster-specific systemd unit: ```bash systemctl is-active postgresql@18-main systemctl is-enabled postgresql@18-main ``` Expected state: ```text active enabled ``` Check whether PostgreSQL accepts connections on its local TCP endpoint: ```bash sudo -u postgres pg_isready -h 127.0.0.1 -p 5432 ``` Expected output: ```text 127.0.0.1:5432 - accepting connections ``` Get the data directory and active configuration file from the server itself: ```bash sudo -u postgres psql -tAc "SHOW data_directory;" sudo -u postgres psql -tAc "SHOW config_file;" ``` This is safer than hard-coding configuration paths when multiple PostgreSQL majors or clusters may exist. **Verify:** the `18/main` service should be active and enabled, `pg_isready` should succeed, and PostgreSQL should report the expected 18/main paths. ## Step 5 — Create a dedicated application role and database Open `psql` as the administrative `postgres` role: ```bash sudo -u postgres psql ``` Create a login role and an application database owned by that role: ```sql CREATE ROLE raffappuser WITH LOGIN; CREATE DATABASE raffapp OWNER raffappuser; \password raffappuser ``` When `\password` prompts you, enter a unique password twice. The password is not placed in shell history. Exit: ```sql \q ``` Verify the role: ```bash sudo -u postgres psql -tAc \ "SELECT rolname, rolcanlogin FROM pg_roles WHERE rolname = 'raffappuser';" ``` Expected output includes: ```text raffappuser|t ``` Verify the database owner: ```bash sudo -u postgres psql -tAc \ "SELECT datname || '|' || pg_get_userbyid(datdba) FROM pg_database WHERE datname = 'raffapp';" ``` Expected output: ```text raffapp|raffappuser ``` Do not reuse the `postgres` superuser from an application. A dedicated login role limits application privileges and makes credential rotation clearer. **Verify:** `raffappuser` should be login-enabled and should own only the tutorial application database you created. ## Step 6 — Verify SCRAM authentication instead of assuming it Find the active host-based authentication file: ```bash HBA_FILE="$(sudo -u postgres psql -tAc 'SHOW hba_file;' | xargs)" echo "$HBA_FILE" ``` Inspect the active rules without editing them: ```bash sudo -u postgres psql -P pager=off -x -c \ "SELECT line_number,type,database,user_name,address,auth_method,error FROM pg_hba_file_rules ORDER BY line_number;" ``` For localhost TCP connections, current Ubuntu/PostgreSQL defaults normally use `scram-sha-256`. Verify the password-encryption setting: ```bash sudo -u postgres psql -tAc "SHOW password_encryption;" ``` Expected output: ```text scram-sha-256 ``` Now test the application role over TCP: ```bash psql -h 127.0.0.1 -U raffappuser -d raffapp -W \ -c "SELECT current_user, current_database();" ``` Enter the application password when prompted. Expected output includes: ```text current_user | current_database --------------+----------------- raffappuser | raffapp ``` Do not weaken authentication to `trust` to make a failed connection work. If authentication differs from the expected SCRAM path, first identify which `pg_hba.conf` rule matched and why. **Verify:** `password_encryption` should be `scram-sha-256`, the localhost HBA rule should require authentication, and `raffappuser` should authenticate successfully to `raffapp`. ## Step 7 — Keep PostgreSQL off the public network Check the configured listen addresses: ```bash sudo -u postgres psql -tAc "SHOW listen_addresses;" ``` For this tutorial, expected output is: ```text localhost ``` Inspect the actual listening sockets: ```bash sudo ss -lntp | grep ':5432' ``` Expected listeners are loopback only, such as: ```text 127.0.0.1:5432 [::1]:5432 ``` If you see `0.0.0.0:5432`, `[::]:5432`, or a public interface address, do not proceed as though the database is private. Find the active configuration file: ```bash CONFIG_FILE="$(sudo -u postgres psql -tAc 'SHOW config_file;' | xargs)" echo "$CONFIG_FILE" ``` Set the database back to loopback-only unless your architecture intentionally requires private-network access: ```conf listen_addresses = 'localhost' ``` Then restart the cluster and verify the sockets again: ```bash sudo systemctl restart postgresql@18-main sudo ss -lntp | grep ':5432' ``` ### Do not enable UFW blindly from a remote shell The PostgreSQL bind address is the primary control in this single-VM design. Check UFW state separately: ```bash sudo ufw status verbose ``` If UFW is already active, confirm there is no broad `ALLOW` rule exposing `5432/tcp`. An explicit deny can be added as defense in depth when it does not conflict with your private-network design: ```bash sudo ufw deny 5432/tcp sudo ufw status numbered ``` If UFW is inactive, do not enable it solely to complete this PostgreSQL tutorial. First preserve the real SSH administration path and follow the lockout-safe [UFW setup guide](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04). For an application on another VM, prefer a [private network](/products/vpc), bind PostgreSQL only to the required private interface, use restrictive `pg_hba.conf` source ranges, and do not expose port 5432 to the public internet. **Verify:** PostgreSQL should listen only on loopback for this tutorial, and no firewall rule should deliberately expose TCP 5432 to the public internet. ## Step 8 — Run an authenticated CRUD test Create a temporary `PGPASSFILE` so the remaining automated checks can authenticate without embedding the password in commands or scripts: ```bash read -rsp "PostgreSQL password: " DB_PASSWORD echo PGPASSFILE="$(mktemp)" chmod 600 "$PGPASSFILE" printf '127.0.0.1:5432:*:raffappuser:%s\n' "$DB_PASSWORD" > "$PGPASSFILE" unset DB_PASSWORD export PGPASSFILE ``` Run create, insert, update, and select operations as the application role: ```bash psql -h 127.0.0.1 -U raffappuser -d raffapp <<'SQL' CREATE TABLE tutorial_check ( id BIGSERIAL PRIMARY KEY, name TEXT NOT NULL UNIQUE, status TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); INSERT INTO tutorial_check (name, status) VALUES ('raff-postgresql-test', 'created'); UPDATE tutorial_check SET status = 'verified' WHERE name = 'raff-postgresql-test'; SELECT name, status FROM tutorial_check WHERE name = 'raff-postgresql-test'; SQL ``` Expected result includes: ```text name | status ----------------------+---------- raff-postgresql-test | verified ``` Confirm that the application role owns the table it created: ```bash psql -h 127.0.0.1 -U raffappuser -d raffapp -tAc \ "SELECT tableowner FROM pg_tables WHERE schemaname='public' AND tablename='tutorial_check';" ``` Expected output: ```text raffappuser ``` Leave this one-row table in place temporarily; Step 9 uses it to prove the logical backup can be restored and queried. **Verify:** the application role should create, insert, update, and read its own table successfully over authenticated TCP. ## Step 9 — Prove a logical backup can be restored A backup command succeeding is not the same as knowing the backup is usable. Create a small custom-format `pg_dump` backup from the tutorial database: ```bash BACKUP_DIR="$HOME/postgresql-tutorial-backup" mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" pg_dump \ -h 127.0.0.1 \ -U raffappuser \ -d raffapp \ -F c \ -f "$BACKUP_DIR/raffapp.dump" ``` Confirm the dump is non-empty and readable by `pg_restore`: ```bash test -s "$BACKUP_DIR/raffapp.dump" && echo "Backup file is non-empty" pg_restore -l "$BACKUP_DIR/raffapp.dump" | head -n 20 ``` Create an isolated restore-test database owned by the application role: ```bash sudo -u postgres createdb -O raffappuser raffapp_restore_test ``` Restore without replaying original ownership or privilege metadata: ```bash pg_restore \ -h 127.0.0.1 \ -U raffappuser \ -d raffapp_restore_test \ --no-owner \ --no-privileges \ "$BACKUP_DIR/raffapp.dump" ``` Query the restored row: ```bash psql -h 127.0.0.1 -U raffappuser -d raffapp_restore_test -c \ "SELECT name, status FROM tutorial_check WHERE name='raff-postgresql-test';" ``` Expected result: ```text raff-postgresql-test | verified ``` Remove only the disposable restore database and tutorial table: ```bash sudo -u postgres dropdb --if-exists raffapp_restore_test psql -h 127.0.0.1 -U raffappuser -d raffapp -c \ "DROP TABLE tutorial_check;" ``` Remove the temporary password file: ```bash rm -f "$PGPASSFILE" unset PGPASSFILE ``` You can keep the small dump as tutorial evidence or remove it after inspection: ```bash ls -lh "$BACKUP_DIR/raffapp.dump" ``` For production, a single `pg_dump` is not a complete recovery strategy. Define retention, off-server storage, encryption, monitoring, and—when required—WAL archiving and point-in-time recovery. See the [PostgreSQL backup strategy guide](/learn/guides/postgresql-replication-vs-backups-vs-snapshots) and [PostgreSQL backup to S3 with Restic tutorial](/learn/tutorials/back-up-postgresql-raff-object-storage-restic). **Verify:** the custom-format dump must be non-empty, listable by `pg_restore`, restore into an isolated database, and return the expected row before you call the smoke test successful. ## Step 10 — Verify the complete PostgreSQL installation Run the final server checks: ```bash systemctl is-active postgresql@18-main pg_lsclusters sudo -u postgres pg_isready -h 127.0.0.1 -p 5432 sudo -u postgres psql -tAc "SHOW server_version;" sudo -u postgres psql -tAc "SHOW listen_addresses;" sudo ss -lntp | grep ':5432' ``` Verify the role and database still exist: ```bash sudo -u postgres psql -tAc \ "SELECT rolname FROM pg_roles WHERE rolname='raffappuser';" sudo -u postgres psql -tAc \ "SELECT datname FROM pg_database WHERE datname='raffapp';" ``` The installation is complete when all of these are true: - The `18/main` cluster is online and its systemd service is active - `SHOW server_version` reports a supported PostgreSQL 18 maintenance release - `pg_isready` accepts local connections on port 5432 - `raffappuser` authenticates to `raffapp` using the intended password-authentication path - Authenticated create/read/update operations succeeded - The logical backup restored successfully into `raffapp_restore_test` and returned the expected row - PostgreSQL listens only on loopback addresses for this single-VM design - No public firewall rule intentionally exposes port 5432 :::cta Deploy Your Server Deploy an Ubuntu 24.04 Linux VM and use the steps above to build a self-hosted PostgreSQL 18 server. ::: ## Choose self-hosted PostgreSQL or managed PostgreSQL deliberately A self-hosted VM gives you direct control over PostgreSQL packages, extensions, configuration, filesystem layout, upgrade timing, and recovery tooling. That control also makes your team responsible for patching, monitoring, backups, restore testing, capacity planning, and incident response. If the application needs PostgreSQL but your team does not want to own those operating tasks, compare this deployment with [Raff Managed PostgreSQL](/products/managed-databases/postgresql) and the broader [managed vs self-hosted database guide](/learn/guides/managed-vs-self-hosted-databases). For a self-hosted production database, also review [VPS sizing for database workloads](/learn/guides/vps-for-databases), [PostgreSQL performance tuning](/learn/guides/postgresql-performance-tuning-small-saas), and [PostgreSQL high availability](/learn/guides/postgresql-high-availability) before treating the tutorial baseline as a production architecture. ## Cleanup (optional) Use this cleanup only if `raffapp` and `raffappuser` were created solely for the tutorial. > **Warning:** Dropping the database permanently removes its data. Terminate remaining sessions, drop the database, and then drop the role: ```bash sudo -u postgres psql <<'SQL' SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'raffapp' AND pid <> pg_backend_pid(); DROP DATABASE IF EXISTS raffapp; DROP ROLE IF EXISTS raffappuser; SQL ``` Verify removal: ```bash sudo -u postgres psql -tAc \ "SELECT datname FROM pg_database WHERE datname='raffapp';" sudo -u postgres psql -tAc \ "SELECT rolname FROM pg_roles WHERE rolname='raffappuser';" ``` Both queries should return no rows. Do not purge PostgreSQL packages or delete `/var/lib/postgresql` unless you have identified every cluster on the VM and confirmed that none contains data you need. ## Troubleshooting ### `postgresql-18` has no installation candidate Check the Ubuntu codename, repository, and package candidate: ```bash . /etc/os-release echo "$VERSION_CODENAME" grep -R "apt.postgresql.org" /etc/apt/sources.list.d 2>/dev/null sudo apt update apt-cache policy postgresql-18 ``` On this tutorial’s target system, the codename should be `noble`. If PGDG is missing, rerun the official setup: ```bash sudo apt install -y postgresql-common sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh ``` ### `sudo apt install postgresql` installed PostgreSQL 16 That is expected on Ubuntu 24.04. Ubuntu’s `postgresql` metapackage tracks its distribution-supported major, PostgreSQL 16. Use the PGDG repository and install `postgresql-18` when PostgreSQL 18 is the requirement. Do not remove an existing PostgreSQL 16 cluster until you know whether it contains data. Check first: ```bash pg_lsclusters ``` ### The `18/main` cluster is offline Inspect cluster state and logs: ```bash pg_lsclusters sudo systemctl status postgresql@18-main --no-pager sudo journalctl -u postgresql@18-main --no-pager -n 100 ``` Check for a port conflict: ```bash sudo ss -lntp | grep ':5432' ``` Correct the reported problem before restarting: ```bash sudo systemctl restart postgresql@18-main systemctl is-active postgresql@18-main ``` ### Password authentication fails Confirm the role can log in: ```bash sudo -u postgres psql -tAc \ "SELECT rolname, rolcanlogin FROM pg_roles WHERE rolname='raffappuser';" ``` Inspect parsed HBA rules and any configuration errors: ```bash sudo -u postgres psql -P pager=off -x -c \ "SELECT line_number,type,database,user_name,address,auth_method,error FROM pg_hba_file_rules ORDER BY line_number;" ``` Reset the role password without putting it in shell history: ```bash sudo -u postgres psql ``` Then: ```sql ALTER ROLE raffappuser WITH LOGIN; \password raffappuser \q ``` Retest: ```bash psql -h 127.0.0.1 -U raffappuser -d raffapp -W \ -c "SELECT current_user, current_database();" ``` ### The application role cannot create tables Confirm the database owner: ```bash sudo -u postgres psql -tAc \ "SELECT datname, pg_get_userbyid(datdba) FROM pg_database WHERE datname='raffapp';" ``` For this tutorial, `raffappuser` should own `raffapp`. If an existing application has a different permission model, do not blindly change ownership to match the tutorial. ### PostgreSQL listens on a public interface Find the active configuration file: ```bash CONFIG_FILE="$(sudo -u postgres psql -tAc 'SHOW config_file;' | xargs)" echo "$CONFIG_FILE" ``` For this single-VM tutorial, set: ```conf listen_addresses = 'localhost' ``` Restart and verify: ```bash sudo systemctl restart postgresql@18-main sudo ss -lntp | grep ':5432' ``` If you intentionally use a separate application VM, bind only to the required private interface and restrict `pg_hba.conf` to the application’s private source range. ### Port 5432 is already in use Identify the owner before changing anything: ```bash pg_lsclusters sudo ss -lntp | grep ':5432' ``` Multiple PostgreSQL majors can coexist, but each cluster needs its own port. Never delete or stop an unknown cluster just to make the tutorial output match. ### `pg_restore` fails during the smoke test Check that the dump is a valid custom-format archive: ```bash file "$BACKUP_DIR/raffapp.dump" pg_restore -l "$BACKUP_DIR/raffapp.dump" | head ``` Make sure the restore database exists and is owned by `raffappuser`: ```bash sudo -u postgres psql -tAc \ "SELECT datname || '|' || pg_get_userbyid(datdba) FROM pg_database WHERE datname='raffapp_restore_test';" ``` If a previous failed attempt left objects behind, drop and recreate **only the disposable restore database**, then retry the restore. ## FAQ ### Which PostgreSQL version is included with Ubuntu 24.04? Ubuntu 24.04’s standard `postgresql` package tracks PostgreSQL 16. This tutorial adds the official PostgreSQL Apt repository so you can install PostgreSQL 18 instead. ### What is the current PostgreSQL 18 version? PostgreSQL 18.6 is the current stable maintenance release as of September 7, 2026. PostgreSQL 19 Beta 3 is a development release and is not the production target used here. ### Should PostgreSQL port 5432 be open to the internet? No for this tutorial. Keep PostgreSQL on `localhost` when the application shares the VM. For separate servers, use private networking and allow only the required private source addresses. ### How should I create a PostgreSQL application user? Create a dedicated login role, make it owner of the intended application database when that ownership model fits, and set its password with `\password` so the secret is not stored in shell history. ### Is `pg_dump` enough for production backups? Not by itself. `pg_dump` is useful for logical backups, but production recovery design also needs retention, off-server copies, monitoring, restore testing, and—when your recovery objectives require it—WAL archiving and point-in-time recovery. ### Should I self-host PostgreSQL or use a managed database? Self-host when your team needs operating-system and database control and is prepared to own patching, backups, monitoring, upgrades, and incident response. Use a managed PostgreSQL service when reducing operational ownership is more important than host-level control. ## Sources - [PostgreSQL — Linux downloads for Ubuntu](https://www.postgresql.org/download/linux/ubuntu/) - [PostgreSQL 18.6 release notes](https://www.postgresql.org/docs/release/18.6/) - [PostgreSQL — Client authentication](https://www.postgresql.org/docs/18/client-authentication.html) - [PostgreSQL — Password authentication](https://www.postgresql.org/docs/18/auth-password.html) - [PostgreSQL — pg_dump](https://www.postgresql.org/docs/18/app-pgdump.html) - [Ubuntu Server — Install and configure PostgreSQL](https://ubuntu.com/server/docs/install-and-configure-postgresql/) - Technical guidance re-verified: 2026-09-07 --- ## Guides ### Platform Engineering for Startups: When Internal Platforms Pay Off URL: https://rafftechnologies.com/learn/guides/platform-engineering-for-startups Description: Learn platform engineering for startups by comparing ad-hoc DevOps, internal platforms, and golden paths. Know when platform investment starts paying off. ## Introduction Platform engineering for startups is the point where your team stops solving the same infrastructure problems from scratch and starts creating a repeatable internal path instead. For most teams on Raff Technologies, that does not mean building a giant internal developer platform on day one. It means recognizing when ad-hoc DevOps has become expensive enough that standardized workflows, better defaults, and self-service infrastructure start saving real time. Platform engineering is the practice of building internal tools, workflows, and operating paths that reduce developer friction while keeping infrastructure safer and more consistent. In practical terms, that often means creating golden paths for common work: how a new service is created, how environments are provisioned, how secrets are handled, how deployments happen, and how teams move from development to production without inventing a new process every time. This matters because startups usually do not suffer first from a lack of platform sophistication. They suffer from repeated operational drag. One engineer becomes the person who knows deploys. Another knows which environment variables matter. Every new service starts with copy-paste infrastructure decisions. Staging is inconsistent, secrets are handled differently in every repo, and small delivery problems start eating time that should go to product work. In this guide, you will learn what platform engineering actually means for startups, when it starts paying off, what teams usually overbuild, and how to grow toward platform thinking without creating a second product inside your company. ## What Platform Engineering Actually Means for a Startup Platform engineering is often described in enterprise language, which makes it sound bigger and heavier than it needs to be. ### It is not “build an internal cloud company” A lot of startup teams hear “platform engineering” and imagine Backstage portals, dozens of internal services, policy engines, and a dedicated platform department. That is one version of it, but it is not the only version, and it is rarely the first version a startup needs. For a startup, platform engineering usually begins much earlier and much smaller: - one standard way to provision a new service - one clear way to handle secrets - one supported deployment path - one repeatable environment model - and fewer decisions every developer has to rediscover alone That is platform engineering too. ### The real goal is lower cognitive load The most useful way to understand platform engineering is not as “more tooling.” It is as a way to reduce cognitive load. If every application team has to understand cloud networking, CI/CD quirks, secrets delivery, container deployment, and environment design from first principles, the organization becomes slower than it needs to be. The platform layer exists to remove repeated infrastructure guesswork. It gives the team a paved road for common tasks so product engineers can focus more on shipping and less on rebuilding operational context from memory. ### In startup terms, it is standardized leverage That is the language I think makes the most sense for founders and engineering leads. Platform engineering is standardized leverage. It turns: - repeated setup work into templates - tribal deployment knowledge into supported workflows - one-off infra decisions into clearer defaults - and fragile developer rituals into internal product behavior That is why the topic matters for startups. Not because “platform engineering” is trendy, but because informal DevOps eventually becomes a tax on velocity. ## The Signals That Ad-Hoc DevOps Is Starting to Break Platform work usually pays off only after the team feels enough recurring pain. ### 1. Every new service starts from scratch If creating a new service still means copying old repos, duplicating CI files, rethinking secrets, rebuilding environment structure, and making one-off infrastructure choices, the team is not really moving fast. It is just repeating work with slightly different filenames. This is one of the clearest early signs that platform engineering may be worth it. ### 2. One or two people carry too much delivery knowledge A startup is in a risky place when: - one person knows how deploys really work - one person knows which environment is closest to reality - one person knows what to rotate after an incident - or one person is always needed to bootstrap new infrastructure correctly At that point, the bottleneck is not compute. It is organizational dependency. ### 3. Environment drift starts slowing releases If staging, preview, and production behave differently for reasons nobody fully trusts, the delivery system is already paying an operational tax. This usually shows up before teams talk about “platform engineering” at all. It shows up as release hesitation, undocumented exceptions, and arguments about whether an issue is application logic or environment inconsistency. That is why this topic connects so well to [Dev, Staging, and Production Environments in the Cloud](/learn/guides/dev-staging-production-cloud-environments). Environment discipline is often the first platform problem a startup actually feels. ### 4. Security and secrets handling are inconsistent A startup does not need a huge platform because security became fashionable. It does need better internal paths when every repo, service, or workflow treats secrets and access slightly differently. This is where platform thinking often starts paying off earlier than founders expect. The more often the same secret-handling or access-control decisions are repeated manually, the more useful opinionated internal workflows become. That is why [Secrets Management for Cloud Apps: Env Vars, Vaults, Managed Stores](/learn/guides/secrets-management-cloud-apps-env-vars-vaults-managed-stores) sits naturally next to this guide. ### 5. Developer speed is being lost to infrastructure choices This is the simplest test. If developers are losing meaningful time to: - environment setup - deployment configuration - service creation - secrets plumbing - or figuring out how the “supported” path actually works then the startup is already paying a platform tax without getting the benefits of a platform. ## When Platform Engineering Starts Paying Off This is the real decision point. Platform engineering starts paying off when the cost of repeated operational work becomes higher than the cost of standardizing it. ### It usually begins before a full IDP is justified Most startups do not need an internal developer platform first. They need a smaller set of platform outcomes first: - repeatable provisioning - clearer deployment defaults - cleaner environment models - more reliable service templates - and less infrastructure guesswork for common tasks That is why I think the first useful question is not: “Should we build a platform team?” It is: “Which repeated infrastructure decisions are slowing us down enough that they should stop being ad-hoc?” That is where the value begins. ### The payoff is usually time before money Platform engineering can absolutely affect cost, but the first visible return is usually time: - faster onboarding - cleaner handoffs - fewer repeated mistakes - less dependency on one operator - shorter path from code to a supported environment This matters because startups feel wasted time earlier than they feel perfect cost models. A team can absorb a suboptimal VM for a while. It struggles much more with repetitive friction spread across every deploy, every repo, and every new service. ### The payoff grows with team parallelism The more developers, services, and environments move in parallel, the more useful a platform layer becomes. This is why platform engineering often starts making economic sense before a startup feels “big.” You do not need a hundred engineers to justify it. You just need enough repeated delivery complexity that standardization saves more than it costs. ## Side-by-Side: Ad-Hoc DevOps vs Early Platform Engineering vs Overbuilt Platform | Model | What It Looks Like | Main Advantage | Main Risk | Best Fit | |---|---|---|---|---| | Ad-Hoc DevOps | Scripts, tribal knowledge, per-service variation | Fast at very small scale | Repetition, drift, person-dependency | Very early teams with 1-2 services | | Early Platform Engineering | Templates, golden paths, self-service for common tasks | Reduces repeated friction | Can be ignored if defaults are weak | Startups with growing service and environment complexity | | Overbuilt Internal Platform | Portals, control planes, too many internal abstractions | High long-term standardization potential | Becomes a second product too early | Larger or more mature engineering organizations | That middle layer is the important one. A lot of startups jump mentally from “we have scripts” to “we need a full internal developer platform.” In practice, the highest-ROI phase is often in between. ## What Startups Usually Get Wrong ### Mistake 1: Waiting until the pain is severe Some teams wait too long because platform work feels like “non-feature work.” By the time they take it seriously, repeated deployment and environment pain is already reducing delivery speed in a visible way. ### Mistake 2: Building an internal platform as prestige infrastructure The opposite mistake is just as common. Teams read enough about developer portals, IDPs, and golden paths that they build a platform before they have enough repeated patterns to justify it. Now they are maintaining platform layers no one fully needs yet. ### Mistake 3: Treating platform engineering as a tooling shopping exercise Platform engineering is not the same thing as “buy or install platform tools.” A portal does not solve repeated delivery pain by itself. The value comes from the supported path underneath it: - what is standardized - what is self-service - what is safe by default - and what the team no longer has to guess about ### Mistake 4: Optimizing for abstraction before optimizing for clarity This is the most damaging one. If the team still does not have clear answers for environments, secrets, deployment paths, and infrastructure ownership, then more abstraction can make the problem harder to see. A startup should not abstract its way out of unresolved operational confusion. ## The Practical Building Blocks That Usually Matter First The best startup platform work is often boring. ### Standard service templates If every new app or service should have: - a default repo structure - a baseline CI path - a standard deployment method - environment conventions - and consistent secrets handling then codify that once instead of rediscovering it every time. ### Opinionated environment patterns One supported pattern for dev, staging, and production is usually worth more than many half-supported variations. This is especially important once the startup begins shipping more in parallel or onboarding more engineers. ### Self-service provisioning for common tasks A startup does not need self-service for everything. It needs self-service for the tasks that recur often enough to create drag: - creating a new app environment - provisioning a VM - deploying a service - attaching standard observability - or setting up predictable network access ### Golden paths, not infinite flexibility This is the most important principle. A golden path is useful precisely because it is opinionated. If the platform gives every team unlimited flexibility immediately, it is not really reducing cognitive load. It is moving the same complexity into a new interface. The best early platform work usually says: “Here is the supported route for the common case. Use this unless you have a real reason not to.” ## Raff-Specific Context On Raff, platform engineering for startups usually starts with practical infrastructure building blocks, not a giant platform bet. A simple but useful pattern is: - a [Linux VM](/products/linux-vm) as the foundation for shared internal tooling or deployment workflows - [Private Cloud Networks](/products/private-cloud-networks) when internal services and platform components should stay off the public internet - clear VM sizing decisions using [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) - and only later, if needed, a stronger [Kubernetes](/products/kubernetes) model once the coordination problem is genuinely bigger than a single-host or lighter pattern can handle That matters because startups often associate platform engineering with Kubernetes too early. Sometimes Kubernetes is part of the answer. Often it is not the first one. Many early platform wins can happen before the team needs a cluster at all. For cost planning, Raff’s public pricing keeps the early steps straightforward. A General Purpose 2 vCPU / 4 GB / 50 GB NVMe VM starts at $4.99/month, while a CPU-Optimized 2 vCPU / 4 GB / 80 GB VM starts at $19.99/month when steadier production-like workloads matter more. Those pricing tiers make it easier to standardize internal workflows in steps instead of jumping straight into heavy platform overhead. That is usually a healthier path for a startup than trying to look like a large platform team too early. ## Conclusion Platform engineering for startups starts paying off when repeated delivery friction costs more than standardization would. If your team is still tiny and the operational path is mostly obvious, ad-hoc DevOps may still be enough. If new services, environments, and releases are starting to feel repetitive, fragile, or too dependent on one or two people, then platform engineering is no longer a luxury topic. It is a practical way to recover speed. The important thing is not to overbuild it. Start with: - supported defaults - repeatable templates - opinionated golden paths - and self-service for the tasks your team repeats most Then let the platform grow only as fast as the workflow proves it should. For next steps, pair this guide with [Dev, Staging, and Production Environments in the Cloud](/learn/guides/dev-staging-production-cloud-environments), [Secrets Management for Cloud Apps](/learn/guides/secrets-management-cloud-apps-env-vars-vaults-managed-stores), and [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). Those are often the real startup platform decisions before a full internal developer platform ever enters the conversation. --- ### Cloud Firewall Rules Explained: Inbound, Outbound, and Least Privilege URL: https://rafftechnologies.com/learn/guides/cloud-firewall-rules-explained Description: Understand inbound and outbound firewall rules, the least privilege principle, and how to design a firewall policy for your Raff cloud infrastructure. A practical decision framework for sysadmins and DevOps teams. ## Introduction A cloud firewall rule is a filter that instructs your infrastructure to allow or drop a network packet based on its source, destination, port, and protocol. Get them right and your VM is accessible only to what it needs to serve. Get them wrong and you have either locked yourself out or left a port open that an automated scanner will find within minutes. This guide explains how firewall rules work at the network level, what inbound and outbound rules actually control, and how to apply the least privilege principle to design a firewall policy you can reason about and defend. It bridges the gap between knowing that firewalls exist and knowing how to configure them with intention — the difference between a firewall that feels safe and one that actually is. At Raff Technologies, every VM is placed behind a cloud-level firewall the moment it is provisioned. The default posture is restrictive: only SSH (port 22) is open on a fresh Linux VM, and only RDP (port 3389) on Windows. Over time, though, we see customers gradually add rules — a port here for an app, a port there for monitoring — until the ruleset becomes a graveyard of "I don't know what this is for but I'm afraid to delete it." This guide gives you the framework to audit that graveyard and keep it clean. ## How Cloud Firewall Rules Work A firewall rule is an instruction with four components: a **direction** (inbound or outbound), a **protocol** (TCP, UDP, ICMP), a **port or port range**, and an **action** (allow or deny). When a packet arrives at your VM, the firewall evaluates rules from top to bottom and applies the first match. If no rule matches, the **default policy** applies — which on a well-configured firewall is always "deny." ### Stateful vs Stateless Firewalls The single most misunderstood concept in firewall configuration is statefulness — and getting it wrong leads to either over-permissive rulesets or broken connectivity. A **stateful firewall** tracks the state of network connections. When your VM initiates an outbound connection (for example, `apt update` reaching out to Ubuntu's package servers), the firewall automatically permits the return traffic for that established session. You do not need an explicit inbound rule to allow the response — the firewall knows the connection was initiated from inside and lets the response through. A **stateless firewall** treats every packet independently with no memory of prior packets. To allow a two-way conversation, you must write rules for both directions explicitly. The Raff cloud firewall is **stateful**, as are UFW and modern iptables configurations using connection tracking (`conntrack`). This has a practical implication: for most services your VM *consumes* (package updates, API calls, DNS lookups), you do not need outbound rules at all — the stateful firewall handles the return traffic automatically. Where you do need outbound rules is when you want to **restrict** what your VM can contact — for example, preventing a compromised VM from phoning home to a command-and-control server, or enforcing that a database VM can only reach your application servers and nothing else. ### Rule Evaluation Order and Default Deny Firewall rules are evaluated in sequence. The first matching rule wins. This is why **default deny** must be the final rule in your chain: it acts as the catch-all that drops everything not explicitly permitted. ``` Rule 1: Allow TCP port 22 from 203.0.113.0/24 → Match → Allow Rule 2: Allow TCP port 443 from anywhere → Match → Allow Rule 3: Allow TCP port 80 from anywhere → Match → Allow ... Final: Deny all → Catch-all → Drop ``` On the Raff cloud firewall, the default policy is implicit deny — you do not write it explicitly. In UFW, you set it with `sudo ufw default deny incoming`. In raw iptables, you set it with `iptables -P INPUT DROP`. A subtle but important point: **deny rules and drop rules behave differently**. A deny (REJECT) sends the sender an ICMP "port unreachable" message, telling them the port is closed. A drop (DROP) silently discards the packet, leaving the sender to time out. For internal services behind a private network, REJECT gives faster feedback to legitimate clients. For internet-facing ports, DROP is preferable because it gives port scanners no confirmation the host even exists. ## Inbound Rules Inbound rules filter traffic arriving at your VM from external sources — whether from the internet, from other VMs in your network, or from within a private VPC. ### The Minimum Viable Inbound Ruleset For a typical Linux VM running a web application, you need exactly three inbound rules to start: | Protocol | Port | Source | Reason | |----------|------|--------|--------| | TCP | 22 | Your IP only | SSH admin access | | TCP | 80 | Anywhere | HTTP (redirects to HTTPS) | | TCP | 443 | Anywhere | HTTPS application traffic | Everything else is denied by default. Not your database port. Not your monitoring agent port. Not your internal API port. Those come later, scoped to the specific source that needs them. This is a deliberate starting point, not a finished policy. The process is always the same: start with the minimum, then add rules only when you have a named service and a named source that requires access. ### Common Inbound Rule Mistakes **Opening SSH to the world.** Port 22 exposed to `0.0.0.0/0` is the single most scanned port on the internet. Automated scanners find it within minutes of a VM being provisioned. Either restrict SSH to your known IP ranges, move it to a non-standard port, or — better — place it behind a VPN (as covered in the [WireGuard setup tutorial](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04)) so the port is not reachable from the public internet at all. **Leaving development ports open.** Port 8080, 3000, 5000, 8888 — these are default ports for local development servers. When you test something on a Raff VM and forget to close the port afterward, that service becomes publicly accessible. A common pattern we see in support tickets: a developer installs Jupyter Notebook for a one-time analysis, leaves port 8888 open, and returns six weeks later to find unauthorized notebooks running. **Using broad CIDR ranges for trusted sources.** Allowing `10.0.0.0/8` because "all our VMs are in that range" is imprecise. If your VMs are at `10.0.1.0/24`, write `/24`, not `/8`. The difference is 16 million addresses vs 254. **Not auditing rules after a project ends.** Every rule should have a documented reason. If you cannot explain why a rule exists, it should be deleted. A quarterly rule audit — even just a 15-minute review of the list — catches orphaned rules before they become a liability. ### Scoping Inbound Rules to Sources The most effective firewall posture is not just controlling which ports are open, but controlling *who can reach them*. The Raff cloud firewall supports source filtering by IP address, CIDR range, or another security group. Use this aggressively: | Service | Port | Recommended Source Scope | |---------|------|--------------------------| | SSH | 22 | Your office/home IP or VPN subnet only | | Database (MySQL, Postgres) | 3306, 5432 | Application server IPs only | | Redis | 6379 | Application server IPs only | | Internal API | 8080 | Load balancer or app tier only | | Monitoring agent | 9100 | Monitoring server IP only | | HTTP/HTTPS | 80, 443 | Anywhere | This table represents a principle, not a template. Every row requires a decision: who specifically needs this? If the answer is "anyone," that is fine for 80 and 443. For everything else, the answer should be a named IP range. ## Outbound Rules Outbound rules filter traffic leaving your VM. Because the Raff cloud firewall is stateful, return traffic for connections your VM initiates is automatically allowed — so your `apt update`, DNS queries, and HTTPS API calls work without any explicit outbound rules. Outbound rules become important when you want to enforce restrictions on what a VM is *allowed to contact*. This is a more advanced posture, but it is the right default for sensitive infrastructure. ### When to Write Explicit Outbound Rules **Database VMs:** A database server should not be initiating arbitrary outbound connections. Lock it down to: DNS (UDP 53) for hostname resolution, NTP (UDP 123) for time sync, your backup destination, and nothing else. If a database VM starts making connections to an external IP you don't recognize, the outbound restriction will block it and your monitoring will alert — instead of silently exfiltrating data. **Application servers in a PCI or compliance scope:** Regulated environments often require that servers only contact explicitly approved destinations. Outbound allowlists make this auditable. **Build servers and CI runners:** These often pull dependencies from the internet. Restricting outbound to known package repositories (Ubuntu mirrors, npm registry, Docker Hub) prevents a compromised build step from reaching arbitrary external endpoints. For a standard web application VM with no compliance requirements, the practical outbound policy is: allow everything outbound, deny everything inbound except what you explicitly open. This is the default Raff posture and it is reasonable for most workloads. ### A Practical Outbound Policy for a Database VM ``` Allow outbound UDP 53 → Anywhere (DNS) Allow outbound UDP 123 → Anywhere (NTP) Allow outbound TCP 443 → backup.yourinfra.com (Encrypted backup) Deny outbound all → Anywhere (Default deny) ``` This VM accepts inbound connections from your application servers on port 5432, handles DNS and time sync, sends backups, and nothing else. If it becomes compromised, the attacker cannot use it to pivot outbound to the broader internet. ## The Least Privilege Principle Applied to Firewalls Least privilege is a security principle that states every component should have access to exactly what it needs to perform its function — and nothing more. Applied to firewall rules, it means: **Every port is closed by default.** You start from zero and add access, not the reverse. The question is never "should I close this?" but always "have I confirmed this needs to be open?" **Every open port has a named owner.** If you cannot answer "what service is listening on this port and who legitimately connects to it?", the port should be closed until you can. **Every rule has a documented reason.** In a team environment, rules without documentation become permanent by default. Nobody deletes a rule they don't understand because they're afraid of breaking something. Treat firewall rules like code — they belong in version control with commit messages explaining why each change was made. **Access is scoped to the minimum necessary source.** Opening a port to `0.0.0.0/0` when only three application servers need access is not least privilege. It is convenience dressed up as configuration. ### The Firewall Rule Lifecycle Every rule should pass through a deliberate lifecycle rather than being added reactively and forgotten: ``` 1. REQUEST — a named service requires network access 2. SCOPE — identify the exact port, protocol, and source required 3. ADD — add the rule with a comment or tag recording the reason and date 4. VERIFY — confirm the rule works and that nothing unintended is accessible 5. REVIEW — revisit the rule periodically; confirm the service still exists 6. REVOKE — remove the rule when the service is decommissioned ``` Most organizations are good at steps 1–4 and skip 5 and 6 entirely. The result is firewall rulesets that grow indefinitely. A rule for a development environment that was torn down 18 months ago is still sitting open because nobody wants to be the person who breaks something by deleting it. ## Layered Firewall Architecture on Raff A production Raff VM should have two firewall layers operating independently. This is sometimes called **defense in depth** — if one layer is misconfigured or bypassed, the other provides a backstop. ### Layer 1: Raff Cloud Firewall (Perimeter) The [Raff cloud firewall](/products/security) operates at the network edge before traffic reaches your VM's operating system. It is applied in hardware/hypervisor infrastructure, which means it cannot be disabled from inside the VM — even if an attacker gains root access to the OS, they cannot modify the cloud firewall rules. Use the Raff cloud firewall for: - Internet-facing perimeter rules (HTTP, HTTPS, SSH) - Cross-VM access rules within your infrastructure - Emergency lockdown — you can close all ports from the panel even if the VM is unresponsive ### Layer 2: Host Firewall (UFW or iptables) UFW or iptables running inside the VM provides a second line of defense. It can enforce rules the cloud firewall cannot — for example, restricting access per Linux user, per network interface, or based on application context using connection tracking. Use the host firewall for: - Interface-specific rules (e.g., allow Redis only on `wg0`, the WireGuard interface — not on `eth0`) - Process-level filtering (advanced, using iptables owner module) - Local loopback restrictions - Rules that need to be co-located with application configuration in version control (e.g., managed by Ansible or Terraform) ### Raff Private Networking and Firewalls If you are running multiple Raff VMs that need to communicate privately, use [Raff private networking (VPC)](/products/private-cloud-networks) in combination with your firewall rules. VPC traffic stays within Raff's internal network and never traverses the public internet — but it still benefits from firewall rules that restrict which VMs can reach which services. A database VM on the private network should have inbound rules that only allow its private IP range, not all VPC traffic. Private does not mean trusted by default. ## Verifying Your Firewall Rules Writing rules is not enough. You must verify that your rules produce the intended outcome from the perspective of an external client. This is the step most teams skip — and where misconfigurations hide. ### Scanning From Outside Use `nmap` from a machine outside your Raff VM (your laptop, a separate VM) to confirm which ports are actually reachable: ```bash nmap -sV -p 1-65535 ``` The output lists every port that responded. Compare it against your intended ruleset. Any open port not on your list is a finding — either a misconfigured rule or a service you forgot was running. For a quick check on specific ports: ```bash # Check if port 22 is open from outside nc -zv 22 # Check if port 3306 (MySQL) is correctly closed nc -zv 3306 ``` A closed port returns `Connection refused` (REJECT) or times out (DROP). Neither is wrong — DROP is slightly preferable for internet-facing ports as discussed earlier. ### Confirming Inbound Rules Are Enforced A common mistake is configuring UFW correctly inside the VM but forgetting that the Raff cloud firewall has a separate allow rule for the same port. The two layers must be consistent. If the cloud firewall allows port 3306 from anywhere but UFW blocks it, MySQL is protected. But if the cloud firewall blocks 3306 and UFW allows it, the cloud firewall wins — and MySQL is safe regardless of what UFW says. Test both layers independently: 1. Temporarily disable UFW (`sudo ufw disable`) and scan — this tests the cloud firewall in isolation 2. Re-enable UFW (`sudo ufw enable`) and scan again — this tests the combined posture Both scans should produce the same open ports. If they differ, you have an inconsistency that needs resolving. ## A Reference Firewall Policy by VM Role Different VM roles have different legitimate access requirements. This table provides a starting-point policy for each common role — not a finished configuration, but a structured baseline to adapt. | VM Role | Inbound Allow | Outbound Restrictions | |---------|--------------|----------------------| | Web server | 80 (any), 443 (any), 22 (admin IP only) | None (stateful return traffic sufficient) | | Database server | 5432/3306 (app server IPs only), 22 (admin IP or VPN only) | DNS, NTP, backup destination only | | Load balancer | 80 (any), 443 (any) | App server IPs on app port only | | Build/CI runner | 22 (admin IP only) | Package repos, Docker Hub, git hosting | | Monitoring server | 22 (admin IP only), 9090 (internal only) | All VM IPs on monitoring port (9100, etc.) | | Bastion/jump host | 22 (your IP only) | Internal VMs on 22 only | A bastion host is worth calling out specifically: a dedicated VM whose only purpose is to be the SSH entry point into your infrastructure. It has no services of its own, and all other VMs allow SSH only from the bastion's private IP. This creates a single, auditable chokepoint for administrative access — far easier to monitor and harden than SSH open on every VM independently. ## Conclusion A firewall is only as strong as the intentionality behind its rules. The technical mechanics — stateful inspection, inbound vs outbound direction, default deny — are learnable in an afternoon. The harder discipline is maintaining the habit: every new port opened has a documented reason, every decommissioned service has its rules revoked, and every configuration is verified from outside the VM rather than assumed to be correct. The least privilege principle is not a setting you toggle on — it is a posture you maintain over time. Start with the minimum, add with justification, review quarterly, and delete without sentiment. For the practical implementation steps that build on this framework, the following resources cover the specifics: - **[Set Up WireGuard VPN on Ubuntu 24.04](/learn/tutorials/set-up-wireguard-vpn-ubuntu-24-04)** — eliminate public SSH exposure entirely by routing admin access through an encrypted private tunnel - **SSH Hardening on Ubuntu** — disable password authentication, restrict login to specific users, and harden the SSH daemon configuration - **Cloud Server Security Best Practices** — the pillar guide for this cluster, covering the full security surface beyond just firewall rules This guide was written by Serdar from the infrastructure side — the firewall policy patterns described here reflect what we apply to Raff's own internal VM fleet, refined through the kinds of incidents you learn from the hard way. --- ### DDoS Protection for Small Teams: Risk and Response URL: https://rafftechnologies.com/learn/guides/ddos-protection-small-teams-risk-response Description: Learn DDoS protection for small teams with a risk framework for exposure, traffic layers, response planning, recovery, and cloud server controls. DDoS protection is a layered defense strategy that keeps applications reachable when malicious traffic tries to exhaust network, protocol, or application resources. For small cloud teams, DDoS risk is not only a “large enterprise” problem. A public website, API, game server, SaaS dashboard, login page, or customer portal can become unavailable if hostile traffic overwhelms the wrong layer. Raff Technologies provides cloud security controls including DDoS protection, cloud firewalls, WAF, and network-to-application-layer protection, which gives small teams a practical foundation before they have a dedicated security operations function. Raff’s security product page describes DDoS protection, cloud firewalls, WAF, SSL management, Layer 3 network security, Layer 4 transport security, and Layer 7 application security. [Raff Security](https://rafftechnologies.com/products/security) This guide belongs under Raff’s cloud security and incident response cluster. Raff already covers cloud security fundamentals, firewall best practices, cloud firewall rules, observability, and disaster recovery. This guide focuses on one specific decision: how small teams should think about DDoS exposure, traffic layers, response planning, and recovery without turning the topic into a tool checklist. ## DDoS Risk Starts With Exposure A distributed denial-of-service attack tries to make a service unavailable by overwhelming the systems that keep it reachable. That sounds simple, but the attack surface is not one place. A DDoS event can target bandwidth, network devices, transport protocols, application endpoints, login flows, expensive database-backed pages, API routes, or background systems triggered by incoming requests. CISA’s joint DDoS guidance describes DoS and DDoS attacks as attempts to exhaust the resources of a target application or website so legitimate users cannot access the service. It also separates common DDoS techniques into network resource overload, protocol resource overload, and application resource overload. [CISA DDoS Guidance](https://www.cisa.gov/resources-tools/resources/understanding-and-responding-distributed-denial-service-attacks) For a small team, the first question is not “which DDoS product do we buy?” It is “which public surfaces would hurt us most if they became unreachable?” A practical exposure map should include: | Public surface | DDoS concern | |---|---| | Marketing website | Availability, brand trust, lead generation | | Customer app | Login, dashboard, checkout, customer workflows | | API endpoint | Partner traffic, mobile app traffic, automated usage | | Admin panel | Sensitive access and operational control | | Game or real-time service | Latency, connection stability, player experience | | File upload endpoint | Bandwidth, storage, and backend processing cost | | Search or report endpoint | Expensive application/database work per request | DDoS protection begins by understanding which parts of the system are public, expensive, business-critical, and hard to degrade safely. ## Not All DDoS Attacks Target the Same Layer The term “DDoS” often gets used as if it means one kind of attack. That creates bad planning. A flood of network traffic is different from a connection exhaustion attack. A connection exhaustion attack is different from an application-layer request flood. A botnet hitting an expensive search endpoint is different from raw bandwidth saturation. The response options are different because the constrained resource is different. OWASP’s denial-of-service guidance separates network or volumetric attacks, session or protocol attacks, and application attacks. Network attacks focus on saturating bandwidth, protocol attacks consume server or intermediary resources, and application attacks exhaust application resources or make the application unusable. [OWASP Denial of Service Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html) | Attack type | Target | Common effect | Better protection focus | |---|---|---|---| | Volumetric attack | Bandwidth and network capacity | Legitimate traffic cannot reach the service | Upstream DDoS protection and traffic absorption | | Protocol attack | Network or transport state | Firewalls, load balancers, or servers exhaust connection resources | Layer 3/4 filtering and connection controls | | Application-layer attack | HTTP/API/application logic | Expensive endpoints overload app or database | WAF, rate limits, caching, endpoint hardening | | Bot-driven abuse | Login, signup, search, forms, APIs | Real-looking traffic consumes business logic | Bot controls, identity checks, behavioral rules | | Multi-vector attack | Several layers at once | Confusing symptoms and shifting pressure | Layered response and observability | The key lesson: **DDoS protection is not one control; it is a layered plan for different failure modes**. A cloud firewall may reduce unnecessary exposure, but it will not automatically solve every application-layer request flood. A WAF may help with Layer 7 behavior, but it does not replace upstream volumetric protection. Scaling may absorb some traffic, but scaling without filtering can increase cost while attackers keep sending traffic. ## The DDoS Risk Decision Framework Use this framework to decide what level of DDoS protection and response planning a small team needs. | Workload profile | Exposure level | Business impact | Recommended posture | Response priority | |---|---:|---:|---|---| | Public marketing site | Medium | Medium | CDN/cache, basic DDoS protection, monitoring | Keep site reachable and protect brand trust | | Customer-facing SaaS app | High | High | DDoS protection, WAF, rate limits, app monitoring | Protect login, dashboard, and critical workflows | | Public API | High | High | API rate limits, auth controls, WAF, traffic baselines | Protect partners, customers, and backend systems | | Internal admin panel on public IP | High | Critical | Restrict access, firewall allowlists, VPN/private access | Reduce exposure before an attack | | Game or real-time workload | High | High | Network-layer protection and latency monitoring | Preserve connection stability | | Dev or staging server | Medium | Low to medium | Restrict public access, firewall rules | Avoid becoming an easy target | | Data-heavy upload service | High | Medium to high | Rate limits, file controls, queueing, storage monitoring | Prevent bandwidth and processing exhaustion | The safest default is simple: **public, business-critical, and expensive-to-process endpoints deserve stronger DDoS protection than low-value or internal workloads**. That does not mean every small team needs enterprise-grade protection on every VM. It means exposure and business impact should decide the control level. ## Firewalls Reduce Exposure, But They Are Not the Whole Plan A firewall is one of the first useful controls because it reduces what the internet can reach. Raff’s firewall best practices guide starts with the principle that a cloud server should accept only the traffic it genuinely needs. That principle matters for DDoS planning because every unnecessary open port becomes another target surface. [Firewall Best Practices for Cloud Servers](https://rafftechnologies.com/learn/guides/firewall-best-practices-cloud-servers) For DDoS planning, firewall rules help by: - closing unused ports, - restricting admin access, - limiting traffic by protocol, - separating public and private services, - reducing accidental exposure, - and making traffic patterns easier to reason about. But firewall rules have limits. If the attack targets the one public service you must keep open, the firewall cannot simply block all traffic without causing the same outage the attacker wanted. If the attack is large enough to saturate upstream bandwidth, local server rules may never see the traffic in time. If the attack looks like legitimate HTTP requests, network rules alone may not distinguish useful users from hostile clients. A firewall is a baseline exposure control. DDoS protection also needs traffic absorption, filtering, application-layer rules, monitoring, and response decisions. ## Application-Layer DDoS Is Harder Because It Looks Legitimate Application-layer DDoS attacks are especially difficult for small teams because they often resemble real users. Instead of sending obviously invalid traffic, an attacker may repeatedly call expensive endpoints, trigger search requests, hit login pages, request uncached pages, open many sessions, or create traffic patterns that force the application or database to work hard. Cloudflare describes application-layer DDoS as attacks that flood servers and network resources with requests that can slow down or crash software and critical operations. [Cloudflare Application-Layer DDoS](https://www.cloudflare.com/the-net/app-layer-ddos-attacks/) For small cloud teams, this creates a different kind of defense problem. You are not only asking whether the server is reachable. You are asking whether the application can survive traffic that technically looks valid. | Application surface | Risk pattern | Better defense | |---|---|---| | Login page | Credential stuffing or repeated auth attempts | Rate limits, bot controls, account protections | | Search endpoint | Expensive database queries | Caching, query limits, rate limits | | File upload | Bandwidth and storage exhaustion | Size limits, auth checks, queueing | | Public API | High request volume from clients or bots | API keys, quotas, throttling | | Dynamic pages | Uncached CPU/database work | Caching and WAF rules | | Checkout or signup | Business disruption | Bot controls and anomaly monitoring | The practical goal is not to block every unusual request. It is to reduce the cost of serving hostile traffic while preserving access for real users. ## Rate Limiting Is a Business Decision, Not Just a Technical Rule Rate limiting sounds technical, but the real decision is business-oriented: how much traffic should a normal user, customer, client, bot, integration, or unknown IP be allowed to create? A rate limit that is too loose may not protect anything. A rate limit that is too strict can block legitimate users. A good rule depends on the endpoint, customer behavior, and cost of the request. | Endpoint type | Rate limit posture | |---|---| | Static pages | Prefer caching before strict limits | | Login | Strict enough to reduce abuse, careful enough to avoid blocking users | | API | Tie limits to API keys, customers, or plans where possible | | Search/reporting | Limit expensive queries and cache common results | | File upload | Limit size, frequency, and unauthenticated access | | Admin routes | Restrict by source, identity, and role rather than broad public access | Small teams should avoid one global limit for every route. A login endpoint, API endpoint, static page, and admin page have different risk profiles. The better model is endpoint-aware protection. Cheap, cacheable requests can tolerate more traffic. Expensive or sensitive requests need stricter controls. ## Scaling Can Help, But Scaling Alone Is Not DDoS Protection More capacity can help with legitimate traffic growth and some traffic spikes. It is not a complete DDoS strategy. If the problem is real customer growth, scaling may be the right answer. If the problem is hostile traffic, scaling without filtering can turn an attack into a larger bill. If the application has an expensive database query, more web servers may just send more pressure to the database. Raff’s auto-scaling guide already frames scaling as a response to measurable workload pressure, not as a default replacement for architecture and traffic planning. [Auto-Scaling VM Planning](https://rafftechnologies.com/learn/guides/auto-scaling-vm-planning) | Situation | Scaling helps when | Scaling is risky when | |---|---|---| | Legitimate traffic spike | Customers are real and demand is valuable | The app bottleneck is database or disk I/O | | Short burst | More capacity absorbs temporary pressure | Traffic is hostile and unfiltered | | Worker backlog | Extra workers reduce queue depth | Workers overload the database | | DDoS traffic | Filtering is already active upstream | You are only paying to process attack traffic | | Application-layer attack | Expensive endpoints are protected | Attack traffic reaches core app logic | The DDoS principle is: **filter before you scale whenever traffic is hostile or unknown**. Capacity is useful after you know what kind of traffic you are allowing through. ## Observability Turns DDoS From Guesswork Into Response DDoS response is difficult without visibility. During an attack, a small team needs to know whether the issue is bandwidth saturation, connection exhaustion, application latency, database overload, CPU pressure, memory pressure, or a specific route being abused. Raff’s observability guide explains metrics, logs, and traces as the three signals small teams use to understand system behavior. [Observability for Small Teams](https://rafftechnologies.com/learn/guides/observability-small-teams-metrics-logs-traces) For DDoS readiness, useful signals include: | Signal | Why it matters | |---|---| | Request rate by route | Identifies abused endpoints | | Error rate | Shows whether users are being affected | | Latency | Shows degradation before full outage | | CPU and memory | Reveals server resource pressure | | Network throughput | Suggests volumetric pressure | | Connection counts | Reveals protocol or socket exhaustion | | Top source patterns | Helps distinguish normal traffic from anomalies | | Database query load | Shows whether app traffic is exhausting backend resources | The most useful baseline is normal behavior. If you know what normal traffic looks like at noon on a weekday, a sudden abnormal spike is easier to classify. Small teams do not need perfect telemetry. They need enough signal to answer the first response question: what is overloaded, and who is affected? ## The DDoS Response Framework A DDoS response plan should be short enough to use under pressure. | Response phase | Main question | Typical action | |---|---|---| | Confirm | Is this a DDoS event or another outage? | Check traffic, errors, latency, and infrastructure status | | Classify | Which layer is under pressure? | Identify volumetric, protocol, or application symptoms | | Protect | What must remain reachable? | Prioritize customer app, API, admin access, or critical workflow | | Contain | Which traffic should be reduced? | Apply firewall rules, WAF rules, rate limits, or route restrictions | | Stabilize | Can legitimate users still access the service? | Cache, fail gracefully, scale selectively, or shed noncritical load | | Communicate | Who needs updates? | Notify internal owner, support, customers, or stakeholders | | Review | What should change before next time? | Improve baselines, rules, architecture, or runbooks | NIST’s incident response guidance emphasizes preparing for incident response, reducing impact, and improving response efficiency across cybersecurity risk management activities. [NIST SP 800-61 Rev. 3](https://csrc.nist.gov/pubs/sp/800/61/r3/final) DDoS response is a specialized incident response case. The same principles apply: assign an owner, classify severity, contain harm, recover service, communicate clearly, and improve controls afterward. ## Degradation Planning Is Better Than All-or-Nothing Availability Small teams often think the only two states are “up” and “down.” DDoS planning needs a third state: degraded but usable. A degraded mode allows the most important users or workflows to keep working while less critical or expensive functions are restricted. | Feature | Degraded-mode option | |---|---| | Marketing site | Serve cached pages | | Login | Add stricter rate limits and bot checks | | Search | Limit expensive filters or reduce frequency | | Reports | Temporarily delay generation | | Uploads | Restrict file size or authenticated access | | Public API | Apply stricter quotas | | Admin access | Restrict by IP, VPN, or private path | This is not about making the product worse. It is about deciding in advance which functions are most important during pressure. The best DDoS plan protects the core customer experience first. ## Recovery Means Returning to Normal Without Reopening the Risk When traffic drops and the service stabilizes, the team still has work to do. A common mistake is removing emergency rules too quickly. Another mistake is leaving temporary rules in place forever, which creates future confusion. Recovery should return the system to a known good state while preserving useful lessons from the event. A DDoS recovery review should answer: | Recovery question | Why it matters | |---|---| | Which layer was attacked? | Improves future filtering and monitoring | | Which endpoint or service was most affected? | Shows where hardening is needed | | Which controls worked? | Confirms the defense model | | Which controls blocked real users? | Prevents overcorrection | | Which alerts fired too late? | Improves detection | | Which temporary rules should become permanent? | Turns response into prevention | | Which rules should be removed? | Avoids accidental long-term restrictions | DDoS recovery is not only restoring traffic. It is making the next attack less disruptive. ## How DDoS Protection Applies on Raff Raff’s security stack is designed around layered protection from the network to the application. Raff’s security product page describes always-on DDoS protection, cloud firewalls, WAF, SSL management, Layer 3 network security, Layer 4 transport security, and Layer 7 application security. It also lists DDoS protection and threat blocking as part of the security platform. [Raff Security](https://rafftechnologies.com/products/security) For small teams running workloads on Raff, the practical model is: - reduce exposure with cloud firewall rules, - keep admin paths restricted, - use DDoS protection for network and transport-layer resilience, - use WAF and application controls for Layer 7 risks, - monitor traffic, latency, and errors, - define response ownership before an attack, - and decide which services should degrade gracefully under pressure. Raff’s Linux VM product also supports full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) The design rationale is simple: DDoS protection should not depend on small teams becoming full-time security operations centers. Infrastructure should provide strong default protection surfaces, while the team remains responsible for exposure decisions, endpoint behavior, application cost, monitoring, and response priorities. Serdar’s infrastructure angle is direct: **a server that is publicly reachable should be designed as if unwanted traffic will eventually arrive**. The question is not whether every small team will face a major DDoS attack. The question is whether the team can keep critical services reachable when traffic becomes abnormal. ## Common DDoS Planning Mistakes **Assuming a firewall solves every DDoS problem.** Firewalls reduce exposure, but application-layer attacks may still target allowed routes. **Protecting the server but ignoring the application.** If one endpoint creates expensive database work, hostile traffic can overload the app without looking like a network flood. **Scaling before filtering.** Scaling hostile traffic can increase cost without restoring service. **Leaving admin panels public.** Admin surfaces should not be exposed like customer-facing pages. **Using one rate limit for every endpoint.** Different routes have different traffic patterns and business value. **Waiting for an attack to define ownership.** DDoS response needs a decision owner before pressure arrives. **Removing emergency rules without review.** Temporary rules should be documented, reviewed, and either removed or converted into permanent controls. ## A Practical DDoS Policy for Small Teams A small-team DDoS policy should be short and operational. | Policy area | Recommended baseline | |---|---| | Exposure review | List public websites, APIs, admin panels, upload endpoints, and expensive routes | | Firewall posture | Only expose services that genuinely need public access | | Layered protection | Combine DDoS protection, firewall rules, WAF, rate limits, and monitoring | | Critical workflows | Define which pages, APIs, and admin paths must stay reachable | | Rate limits | Apply endpoint-aware limits based on cost and normal behavior | | Degraded mode | Decide which features can be restricted during attack traffic | | Incident owner | Assign one person to coordinate response during high-severity traffic events | | Recovery review | Document attack layer, affected services, controls used, and follow-up changes | The policy should fit on one page. During a DDoS event, nobody wants to search through a long document. The team needs to know what matters, who decides, and which controls can be used safely. ## DDoS Protection Is Really Availability Planning DDoS protection for small teams is not only about blocking malicious traffic. It is about preserving availability when traffic becomes abnormal. The right plan starts with exposure mapping, layered controls, traffic baselines, endpoint-aware limits, and clear response ownership. Volumetric attacks, protocol attacks, and application-layer attacks do not fail the same way, so they should not be handled with one generic rule. For broader context, this guide should link back to Raff’s Cloud Security Fundamentals guide. For network exposure, it should connect to Firewall Best Practices and Cloud Firewall Rules Explained. For detection, it should point to Observability for Small Teams. For recovery planning, it should connect to High Availability vs Disaster Recovery. On Raff, small teams can combine DDoS protection, cloud firewalls, WAF, VM control, and monitoring discipline to build a practical defense model without overengineering the first version. --- ### Server Health Checks Explained: Liveness, Readiness, and Synthetic Monitoring URL: https://rafftechnologies.com/learn/guides/server-health-checks-explained-liveness-readiness-and-synthetic-monitoring Description: Understand server health checks with a decision framework for liveness, readiness, startup checks, synthetic monitoring, alerts, and recovery. Server health checks are automated checks that decide whether an application, service, or server should receive traffic, restart, alert the team, or be investigated. For small teams, health checks are often treated as a small monitoring detail. In reality, they are reliability decisions. A bad health check can restart a healthy service, send users to an unready server, hide a broken customer journey, or wake the team up for noise. Raff Technologies gives developers full-root Linux VMs, Docker-ready infrastructure, and flexible server control, which makes it practical to design health checks around real workload behavior instead of relying on one generic “is the server up?” signal. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s observability and reliability cluster. Raff already has guides on observability, incident response, performance bottlenecks, reverse proxies, load balancers, high availability, and disaster recovery. This guide focuses on the missing decision layer: what each health check should prove, which failures it should trigger, and when synthetic monitoring is more useful than internal status checks. ## Health Checks Are Not All the Same A health check is only useful when the team knows what decision it controls. Some checks decide whether a process should be restarted. Some decide whether a service should receive traffic. Some decide whether a new instance has finished starting. Some test the product from the outside, like a user would. Mixing these together creates dangerous behavior. For example, a database outage should not always restart every application server. A slow startup should not be treated as a dead process. A service can be alive but not ready. A homepage can return `200 OK` while checkout is broken. That is why health checks need names and responsibilities. | Health check type | Main question | Typical decision | |---|---|---| | Liveness check | Is the process alive enough to keep running? | Restart if repeatedly unhealthy | | Readiness check | Is the service ready to receive traffic? | Remove from traffic until ready | | Startup check | Has the service finished initialization? | Wait before applying other checks | | Synthetic check | Can a user-facing journey work from outside? | Alert or investigate user impact | | Dependency check | Is a required dependency usable? | Degrade, stop traffic, or alert | | Deep health check | Can critical app behavior complete? | Investigate business-impacting failure | The key rule: **a health check should control one decision, not every decision**. If the same endpoint is used for restarts, traffic routing, uptime alerts, and business health, it will eventually create the wrong reaction. ## The Server Health Check Decision Framework Use this framework to decide which health check fits each reliability question. | Scenario | Best check type | What it should prove | What it should not do | |---|---|---|---| | App process is deadlocked | Liveness | The process cannot make progress | Check every external dependency | | App is starting slowly | Startup | Initialization is still in progress | Restart too early | | App is running but warming cache | Readiness | Traffic should wait until safe | Mark the process dead | | Database is temporarily unavailable | Readiness or degraded state | App may not be able to serve full traffic | Restart every app instance immediately | | Homepage loads but checkout fails | Synthetic | User journey is broken | Depend only on internal metrics | | Load balancer needs healthy targets | Readiness | Instance can accept requests | Prove every business workflow | | Team needs uptime signal | Synthetic | Public service is reachable from outside | Replace logs, metrics, or traces | | Background worker is stuck | Liveness plus job metrics | Worker is alive and jobs are moving | Treat web endpoint health as worker health | The safest pattern is: - use liveness checks for process survival, - use readiness checks for traffic safety, - use startup checks for slow initialization, - use synthetic monitoring for user-visible availability, - and use observability to explain why a check failed. ## Liveness Checks Answer: Should This Process Keep Running? A liveness check decides whether a process is alive enough to continue running. This is useful when the service can become stuck in a state where it is technically still running but cannot make progress. A deadlock, frozen event loop, exhausted worker pool, or unrecoverable internal state may require a restart. Kubernetes’ official documentation explains that liveness probes determine when a container should be restarted. The same idea applies beyond Kubernetes: a liveness check should answer whether restarting the process is a reasonable recovery action. [Kubernetes Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) A good liveness check is usually narrow. | Liveness check should include | Liveness check should avoid | |---|---| | Process can respond at all | Full database queries | | Runtime is not deadlocked | External API calls | | Event loop or worker can make progress | Payment provider checks | | Basic internal state is not corrupted | Expensive business workflows | | Minimal timeout-sensitive check | Slow dependency chains | The danger is making liveness too deep. If the liveness check depends on the database, and the database has a short outage, every application instance may restart even though restarting does not fix the database. That can turn a dependency problem into a wider outage. A practical rule: **liveness should fail only when restarting this process is likely to help**. ## Readiness Checks Answer: Should This Instance Receive Traffic? A readiness check decides whether an instance should receive traffic right now. A service can be alive but not ready. It may be starting, warming caches, applying migrations, waiting for configuration, reconnecting to dependencies, or draining before shutdown. In those states, it may be better to keep the process running but remove it from traffic. Kubernetes’ documentation explains that readiness probes determine when a container is ready to accept traffic, and a pod is not considered ready when the readiness probe fails. [Kubernetes Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) Readiness is especially important behind reverse proxies and load balancers. | Readiness signal | Why it matters | |---|---| | App has loaded configuration | Avoids serving broken startup state | | Required local services are available | Prevents traffic before app can work | | Database connection pool is usable | Avoids routing requests that cannot complete | | Cache or warmup process is complete | Prevents slow first-user impact | | Instance is not draining | Avoids sending traffic during shutdown | | Critical feature dependency is available | Prevents known broken workflows | Readiness should control routing, not restarts. If readiness fails, the system should usually stop sending new traffic to that instance while it recovers. It should not immediately kill the process unless the liveness check also proves the process itself is unhealthy. A practical rule: **readiness should fail when the instance should not receive traffic, even if it should keep running**. ## Startup Checks Protect Slow Services From Restart Loops Some applications need time to start. They may load large models, run migrations, warm caches, build indexes, connect to multiple services, or initialize a heavy runtime. If normal liveness checks start too early, the orchestrator or supervisor may think the app is dead and restart it repeatedly. A startup check solves this by giving the service time to finish initialization before liveness and readiness checks become strict. Kubernetes’ documentation describes startup probes as a way to know when a container application has started; if configured, liveness and readiness checks do not start until the startup probe succeeds. [Kubernetes Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/) Startup checks are useful for: | Workload | Why startup checks help | |---|---| | Large web frameworks | Boot time can vary after deploy | | JVM or .NET services | Runtime warmup can be slower | | ML or AI services | Models may need loading | | Databases or search services | Recovery and index checks can take time | | Apps with migrations | Startup may include schema or state checks | | Heavy container images | Initialization can exceed normal check timeout | A startup check should not hide a broken deployment forever. It should give realistic startup time, then fail clearly if the service never becomes usable. A practical rule: **startup checks protect initialization; they should not become an excuse for unknown boot behavior**. ## Synthetic Monitoring Answers: Can Users Actually Use It? Synthetic monitoring tests the system from the outside. Instead of asking whether the process is alive internally, synthetic monitoring asks whether an external user path works. It may check a homepage, login page, API endpoint, checkout flow, dashboard load, DNS resolution, TLS certificate, or multi-step journey. Google’s SRE material distinguishes white-box monitoring from black-box monitoring. White-box monitoring uses internal system knowledge, while black-box monitoring tests externally visible behavior as a user would see it. [Google SRE: Monitoring Distributed Systems](https://sre.google/sre-book/monitoring-distributed-systems/) Datadog describes synthetic monitoring as a proactive way to simulate user flows and requests to applications, endpoints, and network layers. [Datadog Synthetic Monitoring](https://docs.datadoghq.com/synthetics/) Synthetic checks are useful because internal health can be misleading. | Internal system says... | But synthetic monitoring may reveal... | |---|---| | App process is running | Public endpoint is unreachable | | Database is healthy | Login flow is broken | | Server CPU is normal | DNS or TLS is failing | | Load balancer has healthy targets | Checkout returns an error | | API service is up | Auth provider integration is broken | | All metrics look normal | Users in one region cannot connect | Synthetic monitoring is best for user-visible truth. A practical rule: **synthetic checks should test what customers care about, not every internal detail**. ## Shallow and Deep Checks Serve Different Purposes Health checks can be shallow or deep. A shallow check proves the service can respond quickly. A deep check proves more meaningful behavior, often involving dependencies or business logic. Both are useful, but they should not control the same decisions. | Check depth | Example | Best use | |---|---|---| | Shallow liveness | Process responds quickly | Restart decision | | Shallow readiness | App is initialized and accepting traffic | Load balancer routing | | Dependency readiness | Database/cache is reachable | Traffic safety | | Deep health check | Login, checkout, or API journey works | Synthetic monitoring or alerts | | Business health check | Critical workflow produces expected result | Customer-impacting monitoring | A deep health check is more valuable but also more fragile. If it depends on several systems, it can fail for reasons that do not mean the app process should restart. This is why a deep check is often better as a synthetic monitor or alert, not a liveness check. A practical rule: **the deeper the check, the more careful you should be about what action it triggers**. ## Dependency Checks Need Careful Boundaries Dependencies matter, but they can create bad health-check behavior. A web app may depend on a database, cache, queue, object storage, payment API, email provider, authentication service, and internal API. If the health check requires every dependency to be perfect, the service may appear down too often. If it ignores every dependency, it may receive traffic it cannot handle. The right boundary depends on whether the dependency is required for the specific traffic the service receives. | Dependency | Health-check decision | |---|---| | Primary database | Often part of readiness if most requests require it | | Cache | May be degraded if app can still work without it | | Queue | Should affect worker health, not always web health | | External payment API | Better as synthetic or feature-specific check | | Object storage | Important for upload/download paths | | Email provider | Usually not liveness; may be app-specific alert | | Auth provider | Important for login readiness or synthetic login flow | | Internal API | Depends on whether requests can degrade gracefully | A dependency outage should trigger the right response. If the database is unavailable, stopping traffic may be appropriate. Restarting every web server usually is not. If the email provider is down, checkout may still work, but notifications may be delayed. If object storage is down, uploads may fail while other pages continue working. A practical rule: **dependency checks should match the feature impact, not the emotional desire to check everything**. ## Health Checks Should Support Load Balancers and Reverse Proxies Health checks are often used by reverse proxies and load balancers to decide which backend receives traffic. Raff’s Reverse Proxy vs Load Balancer guide explains that reverse proxies and load balancers sit in front of applications and control traffic flow in different ways. Health checks make that traffic flow safer because unhealthy or unready backends can be removed from rotation. [Reverse Proxy vs Load Balancer](https://rafftechnologies.com/learn/guides/reverse-proxy-vs-load-balancer) For load-balanced systems, readiness matters more than simple process uptime. | Backend state | Better traffic decision | |---|---| | Starting | Do not send traffic yet | | Ready | Send traffic | | Draining | Stop new traffic, finish existing requests | | Dependency degraded | Route only if app can serve useful responses | | Liveness failed | Restart or replace | | Synthetic check failed | Investigate customer-facing path | A backend can pass liveness and fail readiness. That is normal. For example, a service may still be alive while it is draining connections before deployment. It should not be killed, but it should stop receiving new traffic. A readiness check supports that behavior. ## Alerting Should Not Page on Every Failed Check Not every health-check failure deserves an urgent alert. Some failures are expected during deploys, restarts, warmups, or short dependency blips. If every check failure pages the team, health checks become noise. If no check failure alerts the team, users may discover outages first. Google SRE guidance emphasizes that monitoring should help decide which problems deserve human attention and which do not. [Google SRE: Monitoring Distributed Systems](https://sre.google/sre-book/monitoring-distributed-systems/) A practical alerting model looks like this: | Signal | Alert urgency | |---|---| | One readiness failure during deploy | Usually no page | | One instance fails liveness and restarts | Ticket or watch if isolated | | Many instances fail readiness | High urgency | | Synthetic user journey fails from multiple locations | High urgency | | Startup check fails after realistic window | Investigate deployment | | Dependency check degraded but app still works | Warning or ticket | | Public endpoint unavailable | Page if customer-impacting | The best alert is tied to user impact. A liveness failure on one worker may be low severity if redundancy exists. A synthetic login failure for all users may be urgent even if internal metrics look healthy. A practical rule: **health checks should inform alerts, but customer impact should decide urgency**. ## False Positives and False Negatives Are Both Dangerous A false positive says the system is unhealthy when it is actually acceptable. A false negative says the system is healthy when users are actually affected. Both are expensive. | Error type | Example | Result | |---|---|---| | False positive | Readiness fails because cache is briefly slow, but app can still serve traffic | Unnecessary traffic removal | | False positive | Liveness depends on external API and restarts app during API outage | Restart loop | | False negative | Health endpoint returns OK while checkout is broken | Users see failure first | | False negative | App process responds but worker queue is stuck | Background work silently stops | | False negative | Server is up but DNS is broken | External users cannot reach app | Good health-check design reduces both. A shallow liveness check reduces false restarts. A useful readiness check reduces traffic to unready instances. Synthetic checks reduce false confidence from internal-only monitoring. ## Health Checks Should Be Different for Web Apps, Workers, and Databases Different workloads need different health checks. A web application receives user traffic. A background worker processes jobs. A database stores state. A reverse proxy routes traffic. Treating them all with the same health endpoint creates confusion. | Workload | Best health signal | |---|---| | Web app | Liveness, readiness, public synthetic endpoint | | API | Readiness, dependency checks, synthetic API check | | Background worker | Worker process liveness, queue progress, job failure rate | | Database | Connection availability, replication, disk, memory, backup status | | Cache | Connection and response check, but not always app liveness | | Reverse proxy | Backend availability and public endpoint checks | | Scheduled jobs | Last successful run and duration | | WebSocket service | Active connections, reconnect rate, message latency | For background workers, a web health endpoint is not enough. A worker can be alive but not processing jobs. For scheduled jobs, the health question is not whether a port responds; it is whether the job ran successfully on time. A practical rule: **health checks should match the workload’s responsibility**. ## Synthetic Monitoring Should Cover Critical User Journeys Synthetic monitoring becomes more valuable when it covers the paths that matter most. A homepage check is useful, but it may not prove the product works. For a SaaS application, login may matter more. For an API platform, an authenticated API call may matter more. For an e-commerce app, checkout matters more. For a control panel, VM creation or dashboard loading may matter more. | Product type | Useful synthetic check | |---|---| | Marketing site | Homepage loads and TLS is valid | | SaaS app | Login and dashboard load | | API platform | Authenticated API request returns expected response | | E-commerce app | Product page and checkout path | | Developer tool | API, docs, and status endpoint | | Real-time app | WebSocket connect and basic message flow | | Admin panel | Restricted login page availability | | File app | Upload or download path | Synthetic checks should not test every feature at high frequency. That can create noise, cost, and false alarms. They should test the small number of user journeys that prove the service is usable. A practical rule: **synthetic monitoring should represent the customer experience, not the developer’s curiosity**. ## How Health Checks Apply on Raff Raff gives teams the server-level control needed to design health checks around their actual application. On a Raff Linux VM, developers can run application processes, Docker containers, reverse proxies, monitoring agents, cron jobs, workers, and custom health endpoints. Raff Linux VMs provide full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) A practical Raff health-check model looks like this: | Need | Raff-friendly approach | |---|---| | Simple web app | Basic liveness and readiness endpoint | | Docker app | Container health checks plus app-level readiness | | Reverse proxy | Backend readiness and public synthetic checks | | Background worker | Worker liveness plus queue progress | | Production API | Readiness, dependency checks, synthetic API probe | | Deployment safety | Startup checks and readiness before traffic | | Incident response | Preserve health-check events with logs and metrics | | Performance review | Combine health with CPU, RAM, disk, and network metrics | Health checks should not replace observability. They should work with observability. Raff’s Observability guide explains metrics, logs, and traces as the signals that help teams understand system behavior. Health checks answer the first operational question: is this instance usable right now? Observability answers the next question: why? Serdar’s infrastructure angle is direct: **a health check is only as good as the action it triggers**. If the action is wrong, the health check can create downtime instead of preventing it. ## Common Health Check Mistakes **Using one endpoint for everything.** Liveness, readiness, startup, and synthetic checks should not all mean the same thing. **Making liveness too deep.** A liveness check that depends on every external service can restart healthy apps during dependency outages. **Making readiness too shallow.** A service that returns “OK” before it can serve traffic creates bad deployments and user errors. **Ignoring startup time.** Slow-starting apps can be restarted repeatedly if startup checks are not designed realistically. **Only monitoring from inside the server.** Internal metrics can look healthy while users cannot reach the app. **Alerting on every check failure.** Health checks should reduce noise, not create it. **Forgetting workers and scheduled jobs.** A website can be healthy while background processing is stuck. **Not reviewing checks after incidents.** Every incident should teach the team whether health checks were too shallow, too deep, or missing. ## A Practical Health Check Policy for Small Teams A small-team health check policy should be simple enough to follow. | Policy area | Recommended baseline | |---|---| | Liveness | Check whether restarting the process would help | | Readiness | Check whether the instance should receive traffic | | Startup | Give slow services enough time to initialize | | Dependencies | Include only dependencies that affect the decision being made | | Synthetic monitoring | Test critical user journeys from outside the system | | Workers | Track process health and job progress | | Alerts | Page on customer impact, not every isolated check failure | | Deployment | Use readiness to avoid sending traffic too early | | Review | Update checks after incidents and major architecture changes | The goal is not to add every possible check. The goal is to create the few checks that make production safer. ## Good Health Checks Make Failure Boring Server health checks are reliability controls. Liveness checks keep dead processes from staying dead. Readiness checks keep traffic away from unready instances. Startup checks prevent slow services from being restarted too early. Synthetic monitoring proves whether users can actually reach and use the product. For related reading, this guide should link to Raff’s Observability for Small Teams guide, Server Incident Response guide, Performance Bottlenecks guide, Reverse Proxy vs Load Balancer guide, High Availability vs Disaster Recovery guide, and Auto-Scaling VM Planning guide. On Raff, the practical path is to start with simple, accurate health checks, connect them to the right actions, and expand only when the workload proves it needs more detail. A good health check should make failure easier to detect, easier to route around, and easier to recover from. --- ### Cloud Runbooks for Small Teams: Incidents, Deployments, Access, and Recovery URL: https://rafftechnologies.com/learn/guides/cloud-runbooks-small-teams-incidents-deployments-access-recovery Description: Learn cloud runbooks for small teams with a decision framework for incidents, deployments, access, patching, backups, recovery, and ownership. Cloud runbooks are repeatable operating guides that tell a team what to do when a known infrastructure event, incident, deployment, access change, or recovery task happens. For small teams, the biggest operational risk is often not that nobody knows the answer. It is that only one person knows the answer. A runbook turns that person’s memory into a repeatable process. Raff Technologies gives teams full root access on Linux VMs, full administrator access on Windows VMs, fast deployment, snapshots, backups, and flexible infrastructure control. That control becomes more valuable when teams document how to operate the servers before something goes wrong. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s reliability, security, and cloud operations cluster. Raff already covers incident response, patch management, backup strategy, disaster recovery, and first-server setup. This guide focuses on the missing operational layer: how small teams should decide which runbooks they need, what each runbook should contain, and how to keep them useful without building an enterprise process too early. ## Runbooks Turn Operational Memory Into Team Process A runbook is useful because production systems fail under pressure. During a quiet workday, a senior engineer may know exactly how to restart a service, roll back a deployment, rotate an SSH key, restore a snapshot, or validate a backup. During an outage, that same knowledge becomes harder to apply. People are tired. Customers are waiting. Alerts are noisy. The team is trying to decide whether to fix forward, roll back, isolate the VM, restart a process, or escalate. A runbook reduces decision pressure by making the first safe steps clear. NIST’s incident response guidance emphasizes preparation, detection, response, and recovery as part of improving incident response effectiveness. [NIST SP 800-61 Rev. 3](https://csrc.nist.gov/pubs/sp/800/61/r3/final) Google’s SRE incident response material also emphasizes clear command, defined roles, working records, and early incident declaration. [Google SRE Workbook: Incident Response](https://sre.google/workbook/incident-response/) For small teams, the lesson is simple: **a runbook is not bureaucracy when it helps someone make the right decision at 2 AM**. ## Runbooks Are Not the Same as Documentation Documentation explains how a system works. A runbook explains what to do. Both matter, but they serve different moments. | Document type | Main purpose | Example | |---|---|---| | Architecture documentation | Explains system design | App, database, queue, storage, and network diagram | | Setup guide | Explains initial installation | First server provisioning notes | | Runbook | Explains repeatable operations | What to do when the database is full | | Playbook | Coordinates a broader scenario | How the team handles a security incident | | Checklist | Confirms required steps | Pre-deployment validation | | Postmortem | Records what happened and what changed | Review after outage | A runbook should be practical. It should help the person on call answer: - What triggered this runbook? - What should I check first? - What should I avoid doing? - Who owns the decision? - When should I escalate? - How do I verify the system is healthy again? - What should I record afterward? A good runbook is not necessarily long. The best runbook is the one your team can actually use during pressure. ## The Cloud Runbook Decision Framework Use this framework to decide which runbooks your small team needs first. | Operational area | Trigger | Recommended runbook | Why it matters | |---|---|---|---| | Customer-facing outage | App unavailable or major error spike | Incident response runbook | Reduces confusion and assigns ownership | | Failed deployment | New release breaks service | Deployment rollback runbook | Protects production from bad releases | | Suspicious access | Unknown login, exposed key, or admin change | Access review and credential rotation runbook | Reduces security risk | | Server patching | OS or package update needed | Patch window and rollback runbook | Prevents maintenance from becoming downtime | | Backup restore | Data loss, corruption, or migration issue | Restore validation runbook | Makes backups usable under pressure | | Full VM failure | Server unavailable or corrupted | Rebuild or recovery runbook | Defines whether to repair, restore, or rebuild | | Windows workload issue | RDP, IIS, Windows service, or licensing issue | Windows operations runbook | Keeps Windows-specific actions repeatable | | Linux workload issue | SSH, systemd, package, or firewall issue | Linux operations runbook | Keeps server operations consistent | | Cost or idle resource review | Unexpected bill increase | Cloud cost review runbook | Prevents waste from becoming normal | | Access onboarding/offboarding | User joins or leaves team | Access change runbook | Protects production access | The key rule: **write runbooks for the events that are repeatable, risky, and time-sensitive**. If an event happens once and is unlikely to repeat, a post-incident note may be enough. If an event is likely to happen again and the wrong response can harm production, it deserves a runbook. ## A Good Runbook Starts With a Trigger A runbook should begin with the condition that makes it relevant. Without a clear trigger, people do not know when to use it. They either ignore it or open it too late. | Weak trigger | Better trigger | |---|---| | “Server is broken” | “Production web app returns 5xx errors for more than 5 minutes” | | “Database issue” | “Database CPU, disk, or connection count is blocking user requests” | | “Deployment failed” | “New release causes elevated errors, failed health checks, or rollback decision” | | “Access problem” | “Admin key, password, token, or user access must be granted, removed, or rotated” | | “Backup problem” | “A restore is required or backup success cannot be verified” | | “Windows problem” | “RDP unavailable, Windows service stopped, or IIS site unhealthy” | The trigger should match the operational decision. For example, “CPU is high” is not always a runbook trigger. High CPU during useful work may be normal. A better trigger is “CPU pressure is causing customer-facing latency or failed requests.” ## Incident Runbooks Reduce Confusion During Outages An incident runbook helps the team move from panic to structured response. Raff already has a dedicated guide on server incident response covering triage, containment, recovery, communication, and post-incident review. This runbook guide should link to that article as the broader incident-management foundation. [Server Incident Response for Small Teams](https://rafftechnologies.com/learn/guides/server-incident-response-small-teams-triage-containment-recovery) An incident runbook should include: | Section | What it should answer | |---|---| | Trigger | What qualifies as an incident? | | Severity | Is this low, medium, high, or critical? | | Owner | Who coordinates the response? | | First checks | Which signals confirm scope and impact? | | Containment | What can reduce damage immediately? | | Recovery path | Restart, rollback, restore, fail over, or rebuild? | | Communication | Who needs updates and how often? | | Evidence | What logs, screenshots, timestamps, or metrics should be preserved? | | Exit criteria | What proves the incident is resolved? | | Review | What should be documented afterward? | For small teams, one person may hold several roles. That is acceptable. The key is that roles are explicit. During a high-severity incident, the team should know who is coordinating, who is investigating, who is communicating, and who is making the recovery decision. ## Deployment Runbooks Reduce Release Risk Deployments are one of the most common causes of production incidents. A deployment runbook does not need to describe every line of CI/CD logic. It should define the decisions around release safety: when to deploy, what to check before deployment, when to pause, when to roll back, and how to verify success. | Deployment runbook section | What it should include | |---|---| | Pre-deployment checks | Health checks, backup/snapshot status, migration risk, active incidents | | Deployment owner | Person responsible for the release decision | | Change summary | What is changing and why | | Risk level | Low-risk patch, database migration, dependency change, major release | | Rollback path | Previous version, image, snapshot, database restore, or fix-forward | | Verification | Health checks, logs, critical user journeys, error rate, latency | | Stop condition | When the deployment should be paused or rolled back | | Communication | Who should know before and after deployment | The most important part is the rollback decision. A small frontend change may only need a previous application version. A database migration may need a more careful plan. A system package update may need a snapshot or restore path. A Windows application update may need a service restart, IIS validation, or RDP access check. A practical rule: **if a deployment cannot be rolled back safely, the runbook should say what the team will do instead**. ## Access Runbooks Reduce Security Mistakes Access changes are easy to underestimate. Granting SSH access, adding a Windows administrator, rotating an API key, disabling a user, replacing a shared password, or removing a former teammate can all affect production security. These actions are not complicated individually, but mistakes can create serious risk. Raff’s cloud security guide frames access control, firewalls, patching, backups, and monitoring as core cloud security fundamentals. [Cloud Security Fundamentals](https://rafftechnologies.com/learn/guides/cloud-security-fundamentals) An access runbook should cover: | Access event | Runbook decision | |---|---| | New engineer joins | Which systems they need and who approves | | Teammate leaves | Which SSH keys, RDP access, tokens, and accounts are removed | | Admin access requested | Who approves and for how long | | SSH key rotation | Which keys are replaced and how access is verified | | API key leaked | Which services are affected and what must be rotated | | Windows RDP access change | Which administrator accounts are created, disabled, or audited | | Emergency access | Who can grant temporary access and how it is reviewed | | Production credential change | Which applications, workers, and integrations depend on it | A good access runbook should separate normal access from emergency access. Emergency access may be necessary during an incident, but it should be temporary, recorded, and reviewed. Permanent access should follow a calmer approval path. ## Recovery Runbooks Make Backups Usable A backup strategy is only useful if the team knows how to restore. Raff already has backup and disaster recovery guides that explain RPO, RTO, snapshots, restore planning, and the difference between high availability and disaster recovery. A recovery runbook turns those concepts into operational decisions. [Cloud Server Backup Strategy](https://rafftechnologies.com/learn/guides/cloud-server-backup-rpo-rto-snapshots) A recovery runbook should include: | Recovery section | What it should answer | |---|---| | Recovery trigger | What failure requires restore or rebuild? | | Recovery owner | Who decides which restore point to use? | | Data priority | Which data must be recovered first? | | RPO | How much data loss is acceptable? | | RTO | How quickly service must return? | | Restore source | Backup, snapshot, image, or rebuild process | | Validation | How do we know the restored system is correct? | | DNS or traffic | What needs to move after recovery? | | Communication | Who needs to know about data loss or downtime? | | Post-recovery checks | What logs, alerts, and user journeys must be verified? | The runbook should not wait until data is lost to define the restore path. A practical rule: **if the backup restore process has never been tested, the runbook should say that clearly and treat the first test as a priority**. ## Patch Runbooks Prevent Maintenance From Becoming Incidents Patching is a routine task until it breaks production. Raff’s patch management guide already covers maintenance windows, emergency patches, deferral decisions, and rollback planning. A patch runbook should convert that framework into repeatable operating steps. [Cloud VM Patch Management](https://rafftechnologies.com/learn/guides/cloud-vm-patch-management-maintenance-windows-rollback) A patch runbook should define: | Patch decision | What the runbook should say | |---|---| | Patch urgency | Routine, urgent, or emergency | | Affected systems | Which Linux or Windows VMs are included | | Maintenance window | When the work will happen | | Owner | Who applies, verifies, and decides rollback | | Pre-patch safety | Snapshot, backup, service health, access check | | Expected impact | Reboot, service restart, downtime, or no interruption | | Verification | Package version, service status, app health, logs | | Rollback path | Snapshot restore, backup restore, rebuild, or app rollback | | Deferral rule | What compensating control applies if patching waits | Linux and Windows patch runbooks may differ in details, but the decision structure is the same: risk, owner, window, rollback, and verification. ## Windows Runbooks Are Different Enough to Name This guide is not Windows-specific, but Windows workloads deserve examples because the operational paths differ. A Linux runbook often involves SSH, systemd services, package managers, firewall rules, logs, and shell access. A Windows runbook may involve RDP, Windows Services, IIS, Event Viewer, Windows Update, local administrator accounts, licensing state, and application-specific consoles. Raff’s Windows VM page lists Windows Server 2022 and 2025, full RDP access, administrator rights, and a 6-month evaluation license. [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) Windows-specific runbooks can include: | Windows runbook | Why it matters | |---|---| | RDP access recovery | Prevents lockout during incidents | | Windows service restart | Makes application recovery repeatable | | IIS site health check | Supports Windows web workloads | | Windows patch window | Handles reboot and compatibility planning | | Administrator account review | Reduces access risk | | Windows backup restore | Supports recovery for business apps | | License review | Prevents unexpected compliance or activation issues | The point is not to create a separate operations culture for Windows. The point is to document the parts that differ so the team does not improvise during pressure. ## Linux Runbooks Should Avoid Tribal Knowledge Linux servers are flexible, but that flexibility can become tribal knowledge. One engineer may know which service manager is used, where logs live, which firewall rules matter, where environment variables are stored, how deployments happen, and which directories should never be deleted. A Linux runbook should make these assumptions visible. | Linux runbook area | What to document | |---|---| | SSH access | Who can connect and how access is managed | | Service management | Which services matter and how health is verified | | Logs | Where app, system, and proxy logs live | | Firewall | Which ports should be open | | Deployment | How application releases happen | | Rollback | How to return to a previous version | | Backups | What is backed up and where | | Disk pressure | What can be safely cleaned and what cannot | | Package updates | Patch rhythm and reboot expectations | Raff’s first-server guide already covers the initial post-provisioning workflow for a cloud server. A runbook extends that setup into repeatable operations after the server is in use. [First Cloud Server After Provisioning](https://rafftechnologies.com/learn/guides/first-cloud-server-after-provisioning) ## Runbooks Need Owners and Review Dates A stale runbook can be worse than no runbook. If the service name changed, the backup path moved, the access model changed, or the rollback process is outdated, the runbook can lead responders in the wrong direction. Small teams should not write runbooks once and forget them. Every runbook should have: | Field | Why it matters | |---|---| | Owner | Someone is responsible for accuracy | | Last reviewed date | Shows whether the runbook is fresh | | Applies to | Which service, VM, app, or environment it covers | | Trigger | When to use it | | Escalation path | Who to involve when it fails | | Verification steps | How to confirm success | | Related documents | Links to architecture, backup, incident, or deployment notes | | Change history | Shows major updates to the procedure | A good review cadence is simple: | Runbook type | Suggested review cadence | |---|---| | Incident runbook | After every major incident and quarterly | | Deployment runbook | After major deployment process changes | | Access runbook | Monthly or after team changes | | Recovery runbook | After restore tests and quarterly | | Patch runbook | Before major maintenance windows | | Windows operations runbook | After OS, service, or licensing changes | | Linux operations runbook | After service, firewall, or deployment changes | The best time to update a runbook is immediately after it fails, confuses someone, or saves the team during an incident. ## Runbooks Should Contain Decisions, Not Just Steps A runbook full of steps can still be unsafe if it does not explain decision points. Small teams should avoid writing runbooks that say only “restart service” or “restore backup.” The dangerous part is usually deciding whether that action is appropriate. | Weak instruction | Better runbook decision | |---|---| | Restart the server | Restart only if liveness fails and no data operation is in progress | | Restore backup | Restore only after confirming data corruption and choosing restore point | | Roll back deployment | Roll back if error rate remains elevated after defined window | | Rotate key | Rotate affected key, update dependent services, and verify access | | Delete old VM | Confirm owner, data value, and backup status before deletion | | Open firewall port | Confirm business need, source restriction, and owner | A useful runbook gives responders enough context to avoid dangerous shortcuts. Serdar’s infrastructure angle for this guide should be direct: **a runbook is not a script; it is an operating decision written down before pressure arrives**. ## Automating a Bad Runbook Makes the Problem Faster Runbooks can become automation later. That is useful. A repeated manual action can become a script, workflow, scheduled task, or infrastructure automation. But automation should come after the decision is understood. If a team automates a poorly understood runbook, it can create faster mistakes: wrong restarts, unsafe deletions, rushed rollbacks, or overbroad access changes. | Manual runbook is better when... | Automation is better when... | |---|---| | The decision is new or risky | The task is repeated and well understood | | Human approval matters | Conditions are clear and measurable | | Data loss is possible | Rollback is tested | | The system is changing often | Inputs and outputs are stable | | The team is still learning | Failure behavior is predictable | Raff’s Infrastructure-as-Code guide is useful sibling content here because repeatability improves operations, but only when the team understands what should be repeated. [Automation & Infrastructure-as-Code on Raff](https://rafftechnologies.com/learn/guides/automation-infrastructure-as-code-raff) A practical rule: **document first, test second, automate third**. ## The Minimum Runbook Set for a Small Team A small team does not need 50 runbooks on day one. It needs the few runbooks that reduce the highest operational risk. | Priority | Runbook | Why it comes first | |---:|---|---| | 1 | Production incident runbook | Defines ownership and first response | | 2 | Deployment rollback runbook | Protects production from bad releases | | 3 | Access onboarding/offboarding runbook | Reduces security mistakes | | 4 | Backup restore runbook | Makes recovery possible | | 5 | Patch maintenance runbook | Prevents routine updates from becoming outages | | 6 | Server rebuild runbook | Helps recover from serious VM failure | | 7 | Windows or Linux operations runbook | Covers OS-specific actions | | 8 | Cost and idle resource review runbook | Prevents silent infrastructure waste | This is enough to make operations more repeatable without slowing the team down. The goal is not to document everything. The goal is to document the actions that are painful to improvise. ## How Cloud Runbooks Apply on Raff Raff gives teams control over Linux and Windows server operations, which makes runbooks especially useful. Raff Linux VMs provide full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) Raff Windows VMs provide RDP access, full administrator rights, Windows Server 2022 and 2025 options, and a 6-month evaluation license. [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) Raff Data Protection supports snapshots and automated backups for recovery planning. [Raff Data Protection](https://rafftechnologies.com/products/data-protection) A practical Raff runbook model looks like this: | Runbook area | Raff context | |---|---| | Incident response | VM access, logs, health checks, restore path | | Deployment | Linux or Windows app release and rollback decisions | | Access | SSH keys, RDP users, admin access, emergency access | | Patching | Linux package updates or Windows Server maintenance | | Recovery | Snapshots, backups, rebuilds, restore verification | | Rebuild | Deploy replacement VM and restore known-good state | | Cost review | Check old VMs, snapshots, backups, and environments | The design rationale is simple: Raff should give small teams infrastructure they can control, but control only becomes operational maturity when the team knows what to do repeatedly. A runbook turns that control into process. ## Common Runbook Mistakes **Writing runbooks only after a serious outage.** The best time to write the first version is before pressure arrives. **Making runbooks too long.** A 20-page runbook will not help during a high-pressure incident if the first safe action is buried. **Writing steps without triggers.** Teams need to know when the runbook applies. **Forgetting verification.** A runbook should end with proof that the system is healthy again. **Not naming an owner.** Unowned runbooks become stale quickly. **Mixing Linux and Windows assumptions.** SSH and RDP workflows, service management, patching, and logs may differ. **Treating backups as a runbook.** A backup is a resource. The restore process is the runbook. **Never testing the runbook.** A runbook that has not been tested is still partly theoretical. ## A Practical Cloud Runbook Template A simple runbook template should fit most small-team operations. | Section | What to write | |---|---| | Runbook name | Clear title tied to the event | | Applies to | Service, VM, environment, or product area | | Owner | Person or role responsible for accuracy | | Last reviewed | Date of last review | | Trigger | Conditions that make this runbook relevant | | Severity | Expected urgency or impact | | First checks | Signals to confirm scope and status | | Decision points | Choices the responder must make | | Safe actions | Low-risk actions allowed immediately | | Risky actions | Actions that require approval | | Escalation | Who to contact when uncertain | | Rollback or recovery | How to reverse or recover | | Verification | How to prove success | | Communication | Who needs updates | | Post-action notes | What to record after completion | This template is intentionally simple. For most small teams, the best runbook is a one-page document that is accurate, owned, and easy to update. ## Runbooks Make Small Teams More Reliable Cloud runbooks are not about adding bureaucracy. They are about reducing repeatable risk. An incident runbook reduces confusion. A deployment runbook protects production. An access runbook reduces security mistakes. A patch runbook makes maintenance safer. A recovery runbook turns backups into a real path back. For related reading, this guide should link to Raff’s Server Incident Response guide, Cloud VM Patch Management guide, Cloud Backup Strategy guide, High Availability vs Disaster Recovery guide, Cloud Security Fundamentals guide, and First Cloud Server guide. On Raff, small teams can run Linux and Windows VMs with full control, fast deployment, snapshots, backups, and flexible access. The stronger operating habit is making sure every important operational action has a clear trigger, owner, decision path, and verification step before the team needs it. --- ### API Rate Limiting Explained: Protecting Apps Without Blocking Real Users URL: https://rafftechnologies.com/learn/guides/api-rate-limiting-protecting-apps-real-users Description: Understand API rate limiting with a decision framework for fair usage, abuse prevention, endpoint protection, 429 responses, and real-user experience. API rate limiting is the practice of controlling how many requests a client, user, token, IP address, or tenant can make within a defined period. For developers, rate limiting is not only a security feature. It is a product reliability decision. A good rate limit protects the application from abuse, accidental spikes, expensive requests, scraping, brute-force attempts, and runaway integrations. A bad rate limit blocks real users, breaks customers’ automations, or gives attackers the wrong path around your controls. Raff Technologies gives teams full-root Linux VMs, Docker-ready infrastructure, and flexible backend control, which makes it practical to design rate limits around real application behavior rather than applying one generic rule everywhere. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s API, security, and backend reliability cluster. Raff already covers cloud security, DDoS protection, firewalls, observability, API keys, and application logs. This guide focuses on the missing application-layer decision: how to limit API usage fairly without punishing legitimate users. ## Rate Limiting Is About Fairness and Protection The first mistake is thinking rate limiting is only for attackers. Attackers are one reason to rate limit, but not the only one. Real customers can also overload a system by accident. A mobile app bug can retry too aggressively. A partner integration can loop. A dashboard can refresh every second. A batch job can call an endpoint thousands of times. A developer can write a script that ignores backoff. Rate limiting protects the system from both hostile and accidental pressure. OWASP’s API Security Top 10 includes unrestricted resource consumption as a major API risk because API requests consume CPU, memory, storage, network, and external-provider resources. [OWASP API4:2023 Unrestricted Resource Consumption](https://owasp.org/API-Security/editions/2023/en/0xa4-unrestricted-resource-consumption/) A useful rate limit should protect: | Protection goal | What it prevents | |---|---| | Backend stability | One client overwhelming CPU, memory, database, or workers | | Fair user access | One tenant consuming capacity that others need | | Security | Brute-force logins, scraping, credential stuffing, token abuse | | Cost control | Expensive endpoint usage creating unexpected infrastructure spend | | Third-party dependency health | External APIs, payment providers, email systems, or webhooks being overloaded | | Product quality | Real users experiencing slow or failed requests because of noisy clients | The best rate limit is not the strictest one. It is the one that protects the system while allowing legitimate usage to continue. ## The API Rate Limiting Decision Framework Use this framework to decide what kind of rate limit an endpoint needs. | API surface | Risk | Better limiting key | Recommended posture | |---|---|---|---| | Public unauthenticated endpoint | Bot traffic, scraping, abuse | IP address, device signal, route | Conservative limits and bot controls | | Login endpoint | Credential stuffing, brute force | Account, IP, device, username | Strict limits with lockout/backoff care | | Signup endpoint | Spam, fake accounts, cost abuse | IP, email domain, device, account | Moderate limits plus abuse checks | | Authenticated API | Customer overuse, integration bugs | API key, user, tenant, plan | Fair quotas by identity or plan | | Expensive search/report endpoint | CPU/database exhaustion | User, tenant, endpoint | Lower endpoint-specific limits | | File upload endpoint | Bandwidth, storage, processing cost | User, tenant, file size, route | Limits on frequency, size, and concurrency | | Webhook receiver | Burst events from external systems | Source, account, event type | Queueing and backpressure | | Admin endpoint | Sensitive action abuse | Admin user, role, IP, action | Strict limits and audit logs | | Internal API | Service overload | Service identity, route, concurrency | Protect dependencies and workers | A practical rule: **limit by the identity that best represents responsibility**. For unauthenticated traffic, that may be IP address or device signal. For authenticated APIs, it should usually be user, API key, workspace, tenant, organization, or plan. For internal systems, it may be service name or job type. ## Not Every Endpoint Needs the Same Limit One global rate limit is easy to implement, but rarely ideal. Different endpoints have different costs. A simple status endpoint may be cheap. A search endpoint may hit the database. A report endpoint may run heavy queries. A file upload may consume bandwidth and storage. A login endpoint may need security controls. A billing endpoint may affect customer trust. | Endpoint type | Cost profile | Better rate-limit behavior | |---|---|---| | Health check | Very low | Avoid strict user-facing limits | | Static metadata | Low | Higher limits or caching | | Login | Security-sensitive | Strict per account/IP/device limits | | Search | Database-heavy | Endpoint-specific limits | | Report generation | CPU/database-heavy | Lower frequency and queueing | | File upload | Bandwidth/storage-heavy | Size, concurrency, and frequency limits | | API list endpoint | Moderate | Pagination and per-token limits | | API write endpoint | Higher business impact | Limits by user/tenant/action | | Admin action | Sensitive | Strict limits plus audit logging | A good API rate-limiting strategy starts by classifying endpoints by cost and risk. If every endpoint has the same limit, cheap endpoints may be unnecessarily restricted while expensive endpoints remain too easy to abuse. ## 429 Too Many Requests Should Be Useful, Not Mysterious When a client exceeds a rate limit, the standard HTTP response is usually `429 Too Many Requests`. RFC 6585 defines `429 Too Many Requests` as a status code indicating that a user has sent too many requests in a given amount of time. It also says responses should include details explaining the condition and may include a `Retry-After` header telling the client how long to wait before making another request. [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585) A useful 429 response should help legitimate clients recover. | Response element | Why it matters | |---|---| | Clear error message | Tells the client what happened | | Retry timing | Helps clients slow down correctly | | Limit scope | Explains whether the limit is per user, IP, token, or route | | Documentation link | Helps developers adjust integrations | | Request ID | Helps support investigate | | Safe metadata | Helps clients understand without exposing internal logic | A bad 429 response only says “Too many requests” and leaves developers guessing. A better response makes the limit understandable enough for a real client to change behavior. ## Rate Limits Should Communicate With Clients Rate limiting works better when clients can see how close they are to the limit. The IETF HTTPAPI draft for RateLimit header fields defines `RateLimit-Policy` and `RateLimit` headers so servers can advertise quota policy and current service limits to clients. [IETF RateLimit Header Fields Draft](https://ietf-wg-httpapi.github.io/ratelimit-headers/draft-ietf-httpapi-ratelimit-headers.html) Many APIs also use older `X-RateLimit-*` style headers such as limit, remaining, and reset time. The exact header convention matters less than the principle: clients should have enough information to avoid being throttled when they are acting normally. | Client-facing signal | Why it helps | |---|---| | Limit | Shows the quota ceiling | | Remaining | Shows how much usage is left | | Reset | Shows when the quota window resets | | Retry-After | Shows when to try again after rejection | | Request ID | Helps support trace the issue | | Documentation | Helps API users design correctly | Rate limit communication is especially important for public APIs, partner APIs, and customer automation. If your API is used by developers, a silent limit becomes a developer-experience problem. ## Rate Limiting Is Different From DDoS Protection Rate limiting and DDoS protection are related, but they are not the same thing. DDoS protection usually focuses on hostile traffic at the network, protocol, or application layer. API rate limiting focuses on application-level fairness and resource control. Both can protect availability, but they operate at different layers. Raff’s DDoS protection guide explains volumetric, protocol, and application-layer attacks as separate failure modes. This API guide focuses specifically on endpoint-level request behavior after traffic reaches the application layer. [DDoS Protection for Small Teams](https://rafftechnologies.com/learn/guides/ddos-protection-small-teams-risk-response) | Control | Best for | Limitation | |---|---|---| | Firewall | Blocking unwanted ports and source ranges | Does not understand API identity | | DDoS protection | Absorbing or filtering attack traffic | May not know endpoint business cost | | WAF | Filtering known web threats and request patterns | May not understand tenant fairness | | API rate limit | Controlling usage by identity, token, tenant, or endpoint | Needs careful product-aware design | | Quotas | Enforcing plan or contract usage | Can be too slow for burst protection | | Concurrency limits | Protecting workers and dependencies | Does not always control total daily usage | A practical rule: **DDoS protection protects availability at the edge; API rate limiting protects fairness and backend resources inside the application**. Both matter for public APIs. ## Choose the Right Rate Limit Key A rate limit key decides who or what is being limited. This is one of the most important design choices. If the key is wrong, the rate limit will either block legitimate users or fail to stop abuse. | Key | Good for | Watch out for | |---|---|---| | IP address | Unauthenticated traffic, quick abuse controls | Shared networks, NAT, VPNs, mobile carriers | | User ID | Authenticated user fairness | One user may belong to large organization | | Account / tenant | B2B SaaS fairness | One large tenant may need higher limits | | API key | Developer integrations and automation | Keys may be shared across systems | | Route / endpoint | Protecting expensive operations | Needs endpoint classification | | Device or session | Consumer app behavior | Can be spoofed or reset | | Organization plan | Paid quota management | Must match business rules | | Service identity | Internal APIs | Needs service authentication | | Action type | Sensitive operations | Requires good event classification | IP-based limits are useful, but they are not enough for authenticated APIs. Many real users may share one IP address through an office, VPN, university, mobile carrier, or corporate network. Blocking by IP too aggressively can punish innocent users. For authenticated APIs, identity-aware limits are usually better. ## Burst Limits and Sustained Limits Solve Different Problems APIs need to handle both short bursts and long-term abuse. A burst limit allows short spikes without letting them continue forever. A sustained limit controls total usage over a longer window. | Limit type | Example purpose | |---|---| | Burst limit | Allow short spikes from page loads or batch actions | | Per-minute limit | Prevent aggressive loops or rapid abuse | | Per-hour limit | Control steady overuse | | Daily quota | Enforce plan or contract usage | | Concurrency limit | Prevent too many expensive operations at once | | Cost-based limit | Limit expensive requests more than cheap requests | A good API may need more than one limit. For example, an endpoint might allow short bursts for normal UI behavior but still cap sustained usage across an hour. A report endpoint might have a low concurrency limit because each request is expensive, even if daily usage is acceptable. A practical rule: **burst limits protect short-term stability; quotas protect longer-term fairness and cost**. ## Algorithms Matter, But Product Behavior Matters More Developers often start by asking which algorithm to use: fixed window, sliding window, token bucket, or leaky bucket. That matters, but it is not the first decision. The first decision is what user behavior the product should allow. Common models include: | Model | Best for | Trade-off | |---|---|---| | Fixed window | Simple limits like 100 requests per minute | Boundary spikes can occur | | Sliding window | Smoother limits over recent time | More storage/calculation complexity | | Token bucket | Allows bursts while controlling average rate | Needs careful bucket sizing | | Leaky bucket | Smooths request processing | Can delay or reject bursts | | Concurrency limit | Protects expensive active work | Does not control total request count | | Quota | Plan-based or daily usage control | Not enough for sudden abuse | NGINX’s `limit_req` module uses a leaky bucket method to limit request processing rate for a defined key, often an IP address. [NGINX limit_req module](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html) Envoy documents both local and global rate limiting, and notes that local token-bucket rate limiting can reduce load before a global rate limit service is involved. [Envoy Global Rate Limiting](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_features/global_rate_limiting) For most small teams, the exact algorithm is less important than choosing sensible keys, limits, endpoints, and failure behavior. ## Real Users Need Graceful Failure Rate limiting should protect the app without making real users feel randomly punished. When a real user hits a limit, the product should respond in a way that feels understandable. That might mean showing a clear message, slowing an action, queueing a task, asking the user to wait, or suggesting a plan upgrade. | Situation | Better user experience | |---|---| | User searches too quickly | Ask them to wait briefly | | User uploads too many files | Explain upload limit and reset time | | API client exceeds quota | Return 429 with retry guidance | | Admin triggers many exports | Queue exports or limit concurrency | | Login attempts fail repeatedly | Slow down attempts and explain security check | | Tenant exceeds plan quota | Show usage and upgrade/contact option | A hard block is not always the best response. Sometimes the better response is delay, queue, cache, or degrade. A practical rule: **rate limits should feel like a safety boundary, not a random failure**. ## Protect Expensive Endpoints First Small teams do not need perfect rate limiting everywhere on day one. Start with endpoints that are expensive, public, sensitive, or frequently abused. | Endpoint | Why to prioritize | |---|---| | Login | Brute force and credential stuffing risk | | Signup | Spam and fake account creation | | Password reset | Email abuse and account enumeration risk | | Search | Database-heavy queries | | Reports / exports | CPU, database, and storage cost | | File upload | Bandwidth, storage, and processing cost | | AI or compute-heavy endpoints | High cost per request | | Webhooks | Burst events and retry storms | | Admin actions | Sensitive state changes | | Public unauthenticated API | Scraping and bot traffic | If one endpoint can consume disproportionate resources, it deserves endpoint-specific protection. This is especially true for endpoints that trigger background work, database scans, email delivery, file processing, external API calls, or billing operations. ## Rate Limiting Should Work With Queues Some requests should not be rejected immediately. They should be queued. This is common when the work is valuable but expensive: report generation, exports, batch operations, webhook processing, file conversion, image processing, email sending, or long-running tasks. Raff’s background work guide explains the difference between cron jobs, queues, and workflow automation. Queues are useful when work needs retries, worker scaling, and separation from user-facing requests. [Cron Jobs vs Queues vs Workflow Automation](https://rafftechnologies.com/learn/guides/cron-jobs-queues-workflow-automation-background-work) | Work pattern | Better control | |---|---| | User action must be instant | Rate limit and reject if too frequent | | Work can happen later | Queue and show pending status | | External webhook burst | Accept, queue, and process safely | | Heavy report generation | Limit concurrency and queue | | File processing | Limit upload size and queue processing | | Email sending | Queue and throttle provider calls | A queue does not replace rate limiting. It changes where pressure is absorbed. Without limits, queues can grow forever. Without queues, APIs may reject valuable work too aggressively. ## Rate Limits Need Observability A rate limit that nobody monitors can create silent product problems. If legitimate users are hitting limits often, the limit may be too strict or the product flow may be inefficient. If no one ever hits a limit, it may be unnecessary or set too high. If only bots hit the limit, it may be doing its job. Raff’s observability guide explains metrics, logs, and traces as production signals. Rate limits should become part of that observability layer. [Observability for Small Teams](https://rafftechnologies.com/learn/guides/observability-small-teams-metrics-logs-traces) Track: | Signal | Why it matters | |---|---| | 429 response count | Shows how often clients are limited | | Limit hits by endpoint | Shows which routes need adjustment | | Limit hits by user/tenant/API key | Distinguishes abuse from real demand | | Top blocked IPs or clients | Helps abuse investigation | | Retry behavior | Shows whether clients respect limits | | Error rate after limiting | Reveals product impact | | Support tickets about limits | Shows user experience problems | | Backend resource usage | Confirms whether limits protect infrastructure | | Queue depth | Shows whether queued work is backing up | | Cost trend | Shows whether limits reduce resource waste | Rate limiting should be reviewed after launch, after traffic spikes, after abuse attempts, and after major API changes. ## Rate Limits Should Be Versioned Like Product Policy Rate limits affect user behavior. Changing a limit can break integrations, slow workflows, or change what customers can do under their plan. That makes rate limits partly a product policy, not just backend configuration. A good rate-limit change process includes: | Change area | Why it matters | |---|---| | Owner | Someone is responsible for the limit | | Reason | The team knows why the limit exists | | Scope | Endpoint, user, tenant, IP, API key, or plan | | Start value | Initial limit is documented | | Review date | Limit is not forgotten | | Communication | API customers know if behavior changes | | Rollback | Team can restore prior limit | | Monitoring | Impact is measured after change | If API customers depend on your service, rate limits should be documented and communicated clearly. Internal limits can be changed faster. External developer-facing limits need more care. ## Rate Limiting and API Keys Should Work Together API keys help identify automation and integrations. Rate limits decide how much usage each key should allow. Raff already has a guide on API keys for automation, covering how API keys support infrastructure workflows and programmable operations. [Raff API Keys Automation Guide](https://rafftechnologies.com/learn/guides/raff-api-keys-automation-small-teams) For API platforms, rate limits should often be tied to API keys because each key represents a known integration or application. | API key pattern | Rate-limit decision | |---|---| | One key per customer | Limit by customer usage | | One key per integration | Limit by integration behavior | | One key per environment | Separate dev/staging/prod quotas | | One key shared across systems | Harder to diagnose and control | | Key with broad scope | Higher risk if leaked | | Key with no owner | Difficult to review or rotate | A practical rule: **if an API key can generate traffic, it needs an owner, scope, and rate-limit policy**. ## How API Rate Limiting Applies on Raff Raff gives developers the infrastructure control to implement rate limiting where it makes sense for their application. On a Raff Linux VM, a team can run an API server, reverse proxy, queue, Redis, gateway, application middleware, worker processes, observability tools, and logging stack. Raff Linux VMs provide full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) A practical Raff rate-limiting model looks like this: | Need | Raff-friendly approach | |---|---| | Basic public endpoint protection | Reverse proxy or application-level limits | | Authenticated API fairness | Limit by user, tenant, or API key | | Expensive endpoint protection | Endpoint-specific limits and queueing | | Login protection | Stricter account/IP/device limits | | Webhook bursts | Queue events and process with backpressure | | Abuse investigation | Application logs, audit logs, and metrics | | Scaling pressure | Combine rate limits with performance monitoring | | DDoS pressure | Use rate limits alongside firewall and DDoS strategy | The design rationale is simple: Raff should let teams choose the right enforcement layer for their application. Some limits belong at the reverse proxy. Some belong in the application because they need user or tenant identity. Some belong near a queue because the goal is to smooth work rather than reject it. Aybars’ practical angle for this guide is direct: **rate limiting should be designed around real user behavior, not copied from a random default**. ## Common API Rate Limiting Mistakes **Using only IP-based limits for authenticated APIs.** Shared networks, VPNs, and mobile carriers can make IP-only limits block real users. **Setting one global limit for every endpoint.** Cheap and expensive endpoints should not always share the same rule. **Not returning useful 429 responses.** Legitimate clients need retry guidance, not mystery failures. **Blocking instead of queueing valuable work.** Expensive but valid operations may be better handled asynchronously. **Ignoring failed login patterns.** Authentication endpoints need stricter security-aware limits. **Not monitoring rate-limit hits.** A limit can protect the backend while quietly hurting customers. **Making limits too strict during launch.** Early product flows may produce bursts that look suspicious until real behavior is understood. **Letting API keys share one broad quota.** Shared keys make it hard to identify who is causing traffic. ## A Practical API Rate Limiting Policy for Small Teams A small-team rate-limiting policy should be clear and adjustable. | Policy area | Recommended baseline | |---|---| | Public endpoints | Limit by IP and route, with bot/abuse awareness | | Authenticated APIs | Limit by user, tenant, or API key | | Expensive endpoints | Use lower limits, concurrency controls, or queueing | | Login and auth | Apply stricter security-aware throttling | | File uploads | Limit size, frequency, and processing concurrency | | Webhooks | Accept safely, queue, and process with backpressure | | 429 responses | Include clear message and retry guidance | | Observability | Track 429s, endpoint hits, blocked clients, and user impact | | Review cadence | Revisit limits after launches, incidents, and traffic growth | | Documentation | Document public API limits for developers | This policy should evolve as the product grows. The first version does not need to be perfect. It needs to protect the most expensive and sensitive paths without making normal users feel blocked. ## Good Rate Limiting Protects Both the App and the User API rate limiting is not about saying no to users. It is about protecting the experience for everyone. The right limits prevent abusive traffic, accidental loops, expensive endpoint overuse, brute-force attempts, runaway integrations, and backend overload. The wrong limits block real customers, hide product issues, or fail to protect the resources that actually matter. For related reading, this guide should link to Raff’s Cloud Security Fundamentals guide, Firewall Best Practices guide, DDoS Protection guide, Observability guide, Application Logs vs Audit Logs guide, and Raff API Keys Automation guide. On Raff, the practical path is to start with endpoint-aware limits, monitor real traffic, protect expensive operations first, communicate clearly with API clients, and adjust limits as the product’s usage patterns become real. --- ### Right-Sizing Cloud Servers: Avoiding Costly VM Mistakes URL: https://rafftechnologies.com/learn/guides/right-sizing-cloud-servers Description: Learn cloud server right-sizing with a practical framework for choosing VM CPU, memory, and storage without overpaying or underbuilding. Right-sizing cloud servers is the practice of matching VM CPU, memory, and storage to real workload demand instead of guessing too high or too low. For developers and small teams, cloud server sizing is one of the easiest decisions to get wrong. Choose too small, and your application becomes slow, unstable, or difficult to maintain. Choose too large, and you quietly pay for unused resources every month. The right VM is not always the biggest one, and it is not always the cheapest one either. Raff Technologies builds its VM plans for teams that need a practical middle ground: enough performance to run real workloads, enough flexibility to resize later, and clear infrastructure characteristics such as 3 Gbps port speed, unmetered bandwidth, and 1 IPv4 on visible VM plans. This guide is part of the broader [Cloud VM Hosting Guide](/learn/guides/cloud-vm-hosting-guide) series. It explains how to think about cloud server right-sizing before choosing a plan, when to resize, and how to avoid the two classic mistakes: overpowered VMs and underpowered VMs. ## Right-sizing is about fit, not maximum power A cloud VM is a bundle of resources: CPU, memory, storage, bandwidth, and network capacity. Right-sizing means choosing the combination that fits your workload’s actual behavior. That sounds simple, but many teams choose servers based on incomplete signals. Some choose the cheapest VM because they want to reduce cost. Others choose a large VM because they want to avoid performance issues. Both approaches can be wrong. The cheapest VM can become expensive if it causes downtime, failed deployments, slow pages, or engineering time spent troubleshooting avoidable resource limits. The largest VM can also become expensive if most of its CPU and memory sit idle while the monthly bill keeps running. Right-sizing sits between those extremes. It asks a more useful question: **What does this workload actually need to run reliably today, with enough headroom for normal growth?** That question is especially important for small teams. Large companies may have dedicated infrastructure engineers, detailed monitoring, and budget buffers. Smaller teams usually need simpler decisions. They need a VM that works now, does not waste cash, and can grow when the workload proves it needs more capacity. ## Oversized VMs waste budget and hide problems An oversized VM has more resources than the workload can realistically use. At first, this feels safe. The server has plenty of CPU, memory, and storage. The application runs smoothly. Nobody complains. But over time, oversized infrastructure creates two quiet problems. The first problem is cost. If a workload only needs 2 vCPU and 4 GB RAM, running it on a much larger machine means the team is paying for unused capacity every month. One oversized VM may not feel painful, but several oversized environments across production, staging, testing, and internal tools can create real waste. The second problem is hidden inefficiency. A large VM can mask slow database queries, inefficient background jobs, memory leaks, or poor application design. Because the machine has excess capacity, the problem may not appear until traffic grows or the workload moves to a more cost-conscious setup. Oversizing is not always wrong. Production systems need headroom. Spiky workloads need buffer capacity. Critical customer-facing applications should not run at the edge of their limits. But there is a difference between healthy headroom and unused excess. A VM with moderate resource use and room for spikes is right-sized. A VM that uses only a small fraction of its CPU and memory for weeks at a time is probably oversized. ## Undersized VMs create instability and engineering drag An undersized VM does not have enough resources for the workload it is expected to run. This usually appears as slow response times, failed deployments, crashed services, high CPU usage, memory exhaustion, full disks, or background jobs that never catch up. Sometimes the application does not fail completely. It simply becomes unreliable enough to waste time. Undersizing often happens when teams optimize for the lowest monthly price before understanding the workload. A small VM may be fine for a test environment, but not for a production API, database, queue worker, or multi-service application. The most common undersizing symptoms are: - CPU usage stays high during normal traffic - Memory usage grows until the system starts swapping or killing processes - Disk space fills because of logs, uploads, database growth, or Docker images - Background jobs fall behind because workers lack compute capacity - Application restarts become more frequent under load - Basic updates or deployments feel risky because there is no resource headroom The hidden cost of undersizing is engineering drag. A team may save a few dollars on the VM but lose hours diagnosing performance issues that would be solved by a better resource fit. For production workloads, undersizing is often more expensive than it looks. ## CPU, memory, and storage should be sized separately A common mistake is choosing a VM only by vCPU count. CPU matters, but it is not the only resource that determines performance. A workload can have enough CPU and still fail because it lacks memory. A database can have enough memory but still run out of disk. A worker VM can have enough disk and memory but still take too long because it lacks CPU capacity. Right-sizing works better when you evaluate each resource separately. ### CPU measures processing pressure CPU matters when the server spends time calculating, compiling, testing, encoding, rendering, parsing, or processing requests. A CPU-bound workload slows down because the processor is the bottleneck. Examples include CI jobs, background workers, game servers, analytics jobs, scraping pipelines, and compute-heavy APIs. If CPU usage regularly stays above 70–80% during normal operation, the VM may need more CPU, better workload distribution, or application optimization. ### Memory measures stability pressure Memory matters when the application needs to keep active data, processes, caches, or database buffers available. A memory-constrained server may become unstable even when CPU usage looks acceptable. Examples include databases, Redis-style caches, analytics tools, observability services, self-hosted platforms, and multi-container environments. If memory usage stays high, swap usage increases, or services are killed by the operating system, the VM likely needs more RAM or fewer workloads running on the same machine. ### Storage measures growth pressure Storage matters when the workload produces or stores data over time. Disk pressure often grows quietly until it becomes urgent. Examples include databases, application logs, user uploads, Docker images, media files, build artifacts, backups, and package caches. A VM with full disk can fail in ways that are more abrupt than CPU or memory limits. Databases may stop writing. Deployments may fail. Logs may disappear. Applications may crash. For storage-heavy workloads, right-sizing means planning for growth, not only today’s files. ## A practical decision framework for right-sizing cloud servers Use this framework before choosing or resizing a VM. | Resource signal | Healthy range | Warning sign | Likely decision | |---|---:|---|---| | CPU usage | Usually below 70% | Sustained 80%+ during normal work | Move to more CPU or CPU-optimized class | | Memory usage | Enough free RAM for spikes | Swap usage, process crashes, 80%+ sustained RAM | Move to more RAM or high-memory class | | Disk usage | Below 70% with growth room | 80%+ disk usage or fast log/database growth | Increase storage or split data workload | | Traffic pattern | Predictable daily variation | Large spikes or unknown launch demand | Add headroom before production events | | Background jobs | Jobs complete on schedule | Queue backlog keeps growing | Add CPU, workers, or separate worker VM | | Database behavior | Stable query times | Slow queries under normal load | Add memory, storage headroom, or separate DB | | Monthly cost | Resources actively used | Low usage for weeks | Downsize or consolidate workloads | | Production risk | Room for updates and spikes | Updates cause pressure or downtime | Resize before reliability suffers | A useful right-sizing rule is this: if a resource stays above 80% during normal workload periods, you are no longer using headroom — you are relying on luck. That does not mean every brief spike requires a larger VM. Short spikes are normal. Sustained pressure is the important signal. A server that briefly reaches high CPU during a deployment may be fine. A server that stays high every afternoon under normal traffic is asking for a different size. Right-sizing should be based on patterns, not panic. ## The right starting size depends on workload maturity New projects and mature workloads should not be sized the same way. An early project usually has uncertainty. Traffic is unknown. Usage patterns are unclear. The product may change quickly. In this stage, the best VM is often a modest, balanced server that can be resized later. A mature production workload is different. It has real users, clearer traffic patterns, known database size, and higher reliability expectations. In this stage, aggressive cost-minimization can become dangerous. The VM should have enough headroom to handle normal spikes, maintenance tasks, and expected growth. A simple way to think about maturity: | Workload stage | Main goal | Sizing approach | |---|---|---| | Experiment | Learn cheaply | Start small | | MVP | Validate usage | Use balanced resources | | Early production | Stay reliable | Add modest headroom | | Growing production | Prevent bottlenecks | Resize based on metrics | | Mature workload | Optimize cost and reliability | Separate workloads if needed | For small teams, this staged approach is healthier than trying to design the perfect server on day one. The first VM choice should be reasonable, not permanent. ## Common workload patterns need different sizing choices A static website, API server, database, CI worker, and self-hosted automation platform may all run on VMs, but they do not need the same resource shape. A small website or basic web app usually fits a balanced VM. It needs enough CPU to handle requests, enough memory for the runtime and database connection pool, and enough storage for application files and logs. A backend API with paying users needs more headroom. Even if average usage is low, production services should not run near their limits. Slow response times can affect customer trust. A database VM needs memory and storage planning. CPU matters, but many database workloads benefit from extra RAM for buffers and caching. Storage growth also matters because database files, indexes, and backups can expand over time. A worker VM needs CPU if it processes jobs continuously. If queues are growing, the issue may be compute capacity rather than web-server performance. A self-hosted tool VM may need more memory than expected. Tools with multiple services, dashboards, queues, and databases can consume RAM even when traffic is modest. A development VM can be smaller. It does not need the same headroom as production because downtime has lower consequences. The right sizing decision starts by naming the workload honestly. ## Raff context for right-sized VM planning Raff’s VM lineup gives small teams a practical path for right-sizing because the plans are organized around resource patterns rather than a single one-size-fits-all server type. General Purpose plans are a strong starting point for balanced workloads such as web apps, APIs, dashboards, small production services, and development environments. They are useful when CPU, memory, and storage all matter, but none is obviously the main bottleneck. CPU-Optimized plans make more sense when processing speed directly affects the workload. Build jobs, queue workers, game servers, testing workloads, and compute-heavy services can benefit from this class when CPU pressure is the limiting factor. High-memory configurations help when RAM is the resource that protects stability. Databases, caches, analytics tools, self-hosted platforms, and multi-service VMs often need more memory per CPU core than a simple web server. Visible Raff VM plans include 3 Gbps port speed, unmetered bandwidth, 1 IPv4, optional IPv6 dual-stack, and resize support. That means teams can make a conservative starting choice, then adjust as real usage becomes clearer. The design rationale is straightforward: early-stage teams should not be forced to guess their final infrastructure size before they have traffic, customers, or workload history. A right-sized starting VM should support today’s workload while leaving a clear upgrade path for tomorrow. ## Best practices for avoiding VM sizing mistakes ### Start with a balanced VM unless the bottleneck is obvious If the workload is new, choose balance first. A General Purpose VM is often safer than jumping immediately into a specialized class. ### Use production headroom intentionally Production servers should not run constantly near their limits. Leave room for traffic spikes, deployments, updates, backups, and background jobs. ### Treat sustained pressure differently from short spikes A short CPU or memory spike does not always require resizing. Sustained pressure during normal activity is the stronger signal. ### Separate workloads when one service dominates the VM If a database, worker, or cache consumes most resources, consider separating it from the main application. This can make sizing clearer and reduce cross-service failures. ### Watch storage growth before it becomes urgent Disk issues often arrive suddenly. Track logs, database growth, uploads, Docker images, and backup-related storage before the server reaches a critical point. ### Resize based on evidence, not anxiety The best resizing decisions come from usage patterns. Upgrade when the workload proves it needs more. Downsize when resources stay idle for long periods. ## Right-sizing is an ongoing infrastructure habit Cloud server right-sizing is not a one-time decision. It is an operating habit. The right VM today may not be the right VM three months from now. A side project may become a production app. A small database may become the center of the product. A background worker may become more important than the web server. A single VM may eventually become several specialized VMs. The goal is not to predict every future requirement. The goal is to avoid obvious waste, prevent avoidable instability, and keep your infrastructure easy to adjust. For more context on VM class selection, read [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained). For the broader planning layer, continue with the [Cloud VM Hosting Guide](/learn/guides/cloud-vm-hosting-guide). If you are choosing a server for a real project, Raff’s Linux and Windows VM plans give you a clear starting point, with resize support when your workload proves it needs more capacity. --- ### AI Coding Agents and Cloud Dev Environments Explained URL: https://rafftechnologies.com/learn/guides/ai-coding-agents-cloud-dev-environments Description: Understand the infrastructure AI coding agents need, from clean cloud dev environments to testing VMs, secrets isolation, and workload sizing. AI coding agents are software assistants that can inspect codebases, make changes, run checks, and prepare code for human review. The important point is that an AI coding agent is not only a chat window. Once it starts editing files, installing dependencies, running tests, or preparing pull requests, it needs a real software environment. That environment may be local, hosted by a tool provider, or created by the team on a cloud VM. The infrastructure decision matters because the agent can only work as reliably as the environment around it. Raff Technologies is relevant here because many developers and small teams do not need a complex enterprise developer platform to begin using AI-assisted workflows. They often need something simpler: a clean Linux VM, a predictable test server, enough CPU and memory for the project, and a safe boundary between development and production. ![Raff cloud VM configuration screen showing a 2 vCPU, 2 GB RAM, 40 GB NVMe entry server plan for lightweight workloads.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_05_31_at_10_22_10_1397fa66c1.png) This guide is part of the broader [Cloud VM Hosting Guide](/learn/guides/cloud-vm-hosting-guide) series. It explains what infrastructure AI coding agents need, when a cloud dev environment makes sense, and how to choose a VM for agent-assisted development. ## AI coding agents still need real development environments AI coding agents can generate code, propose changes, explain errors, write tests, and refactor files. But every useful coding task eventually meets the same practical question: where does the code actually run? A useful agent workflow needs an environment that can: * Clone or access the repository * Install project dependencies * Run package managers * Execute tests * Start local services * Read logs and errors * Build the application * Validate changes before review Without that environment, the agent is mostly guessing. It can still suggest code, but it cannot reliably prove whether the change works. This is why cloud dev environments are becoming more important. They give developers and agents a repeatable workspace that is separate from the local machine. Instead of every developer configuring dependencies manually, the team can create a clean server or containerized environment where the project behaves consistently. For AI-assisted work, consistency is not a luxury. It is how you reduce false positives, broken patches, and “works on my machine” problems. ## Cloud dev environments create a safer place for agent work A cloud dev environment is a remote workspace used to write, test, build, or review software outside the developer’s local laptop. For AI coding agents, this has a practical advantage: the agent can work in a controlled environment without touching production systems or personal machines. That boundary matters because coding agents are still tools that need review. They can be useful, but they should not be treated as trusted production operators. A good cloud dev environment gives the agent a place to: * Work on a branch * Install dependencies * Run tests * Build the project * Produce logs * Generate a patch or pull request * Fail safely without affecting production ![Terminal window connected to a Raff cloud development VM used for testing code in an isolated environment.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_05_31_at_13_19_49_e1ec1f5eaf.png) This environment should be disposable or easy to reset. If the agent breaks dependencies, creates temporary files, or produces a failed build, the team should be able to clean the workspace and start again. That is one reason VMs remain useful even when modern tools offer managed agent sandboxes. A self-managed cloud VM gives teams a familiar place to test code, reproduce bugs, host staging versions, or run workloads that need more control than a browser-based environment provides. ## The main infrastructure need is isolation The first infrastructure requirement for AI coding agents is isolation. An agent should not have unlimited access to production databases, customer data, deployment keys, or internal systems. It should work in a limited environment where mistakes are contained. There are several useful isolation boundaries: * Repository branch isolation * Development VM isolation * Staging environment isolation * Test database isolation * Limited secrets access * Separate SSH keys * Separate deployment permissions * Human review before production deployment This does not mean the agent is dangerous by default. It means the environment should assume mistakes are possible. A human developer can also run the wrong command or deploy the wrong branch. The difference is that an agent may perform more steps faster, so guardrails matter earlier. For small teams, the simplest isolation pattern is often this: Use one VM for development or testing, keep production separate, and avoid giving the agent direct access to production credentials. That one decision prevents many problems. ## CPU, memory, and storage needs depend on the project There is no single VM size that fits every AI coding workflow. The infrastructure requirement depends less on the agent itself and more on the project the agent is working on. A small static website has very different needs from a monorepo with a large test suite, database, queue, frontend build process, and background workers. A cloud dev environment must have enough resources for the project’s normal development loop. CPU matters when the project runs builds, tests, compilers, bundlers, or analysis tools. If builds are slow and CPU usage stays high, the environment needs more processing power. Memory matters when the project runs multiple services, containers, databases, dev servers, or large frameworks. If the VM starts swapping or services restart, the environment needs more RAM. Storage matters when the project uses large dependency folders, Docker images, build artifacts, logs, datasets, or local database files. If the disk fills, the environment becomes unreliable no matter how much CPU it has. For a small project, an entry cloud VM can be enough. For larger development workflows, the right answer may be a higher-memory VM, a higher-vCPU VM, or separate environments for app, database, and workers. ## A decision framework for AI-agent infrastructure Use this framework when choosing infrastructure for AI-assisted development. | Workflow type | Infrastructure need | Recommended VM direction | | ----------------------------- | ------------------------------ | ------------------------------- | | Small website edits | Simple remote workspace | Entry General Purpose VM | | Lightweight API changes | App runtime and basic tests | Small General Purpose VM | | Documentation and refactoring | Low CPU, low memory | Entry General Purpose VM | | Docker-based app | Multiple services and images | 4 GB or 8 GB RAM VM | | Database-backed app | App plus database testing | HiMem VM | | Large frontend build | CPU and memory for bundling | Larger General Purpose VM | | Backend test suite | CPU for repeated tests | More vCPU or CPU-focused plan | | Monorepo | CPU, RAM, and storage together | Larger VM or split environments | | Staging review app | Stable demo environment | General Purpose or HiMem VM | | Production deployment | Human-controlled release path | Separate production VM | A useful rule is this: size the cloud dev environment for the test and build workload, not only for the app when idle. A project may look lightweight when it is running, but become resource-heavy during installation, build, test, or dependency updates. AI coding agents often spend time in exactly those tasks, so the development environment must handle them. ## Small projects can start with a modest cloud VM A small project does not need an enterprise-grade developer platform. A simple website, lightweight API, internal tool, or early MVP can often start with a modest cloud VM. The goal is not maximum power. The goal is to create a clean place where the project can be installed, tested, and reviewed. A small cloud dev VM is useful for: * Trying AI-assisted code changes * Testing deployment scripts * Running lightweight app builds * Hosting a temporary staging version * Reproducing bugs outside a laptop * Keeping dependencies separate from the local machine For this type of workflow, Raff’s [2 vCPU / 2 GB cloud VM guide](/learn/guides/2-vcpu-2gb-cloud-vm-workloads) is a useful next read. A small VM can be enough when the repository is simple, the test suite is light, and the environment runs one main workload. The limit appears when the agent workflow starts running several services at the same time. If the VM needs to run the app, database, queue, cache, frontend dev server, and tests together, 2 GB RAM may become too tight. ## Docker-based agent workflows usually need more memory Docker is common in modern development environments because it makes services repeatable. It is also common in AI-assisted workflows because agents can use a defined environment instead of guessing local setup steps. The challenge is that Docker stacks can consume memory quickly. A single lightweight container may run well on a small VM. A real development stack may include: * Application container * Database container * Cache container * Queue container * Worker container * Frontend dev server * Reverse proxy * Test runner Each service needs memory. Docker images and volumes also consume storage. If the agent installs dependencies, runs builds, and executes tests inside this environment, the VM needs enough headroom for more than idle runtime. For Docker-based AI workflows, memory is often more important than raw CPU at the beginning. If containers restart, swap appears, or the database becomes unstable, a HiMem VM may be the better upgrade. For more detail, read [HiMem VMs Explained](/learn/guides/himem-vms-explained). That guide explains why more RAM can matter more than more CPU for databases, self-hosted tools, and multi-service environments. ## Test-heavy repositories need CPU headroom Some repositories are not memory-heavy first. They are test-heavy. A backend service with many unit tests, integration tests, type checks, linters, or build steps may need more CPU to keep iteration fast. AI agents are often assigned tasks such as refactoring, adding tests, fixing bugs, or updating dependencies. Those tasks usually require repeated validation. If every agent task waits several minutes for the test suite, the development loop becomes slow. The agent may still work, but the review cycle becomes less efficient. CPU headroom matters for: * Large test suites * Compiled languages * Type checking * Frontend bundling * Static analysis * Dependency builds * Multiple parallel checks This does not mean every AI coding workflow needs a CPU-Optimized machine. Start by identifying the bottleneck. If memory is stable but tests are slow and CPU is busy, more CPU is useful. If CPU is idle but services are crashing, more RAM is the priority. Raff’s [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained) guide can help decide whether a General Purpose, HiMem, or CPU-focused plan is the better fit. ## Secrets and permissions should be limited by design AI coding agents should not receive broad production access by default. A development environment may need environment variables, test credentials, package tokens, or API keys. But those should be scoped carefully. The agent should only access what it needs to install, test, and validate code. Safer patterns include: * Use test credentials instead of production credentials * Keep production database access out of dev environments * Use read-only tokens where possible * Use separate SSH keys for development VMs * Rotate credentials used in experiments * Avoid storing secrets directly in repository files * Require human review before deployment For small teams, the simplest rule is enough: never give an agent more access than you would give a temporary junior developer working on a test branch. That may sound conservative, but it protects the business. AI-assisted development is still development. It should follow the same security boundaries as any other code workflow. ## Human review remains part of the infrastructure Infrastructure is not only CPU, RAM, and storage. It is also the workflow that controls how code moves from idea to production. AI coding agents should produce work that humans can inspect. That usually means branches, commits, pull requests, logs, test output, and clear summaries. The environment should make review easier, not bypass it. A healthy workflow looks like this: * Agent works in an isolated environment * Changes are committed to a branch * Tests and checks are visible * Human reviews the diff * Human approves or requests changes * CI/CD runs under controlled permissions * Production deployment remains separate This is why cloud dev environments and staging VMs matter. They give the team a place to validate agent output before it becomes a production change. The more autonomous the agent becomes, the more important the review path becomes. ## Raff context for AI-assisted development environments Raff does not need to replace AI coding tools to be useful in AI-assisted workflows. The useful role for Raff is infrastructure: clean Linux VMs, development servers, testing environments, staging machines, and resizeable cloud compute for developers who need a place to run projects outside their laptops. For small projects, Raff’s entry General Purpose VM can be a practical starting point. The **2 vCPU / 2 GB RAM / 50 GB NVMe** plan fits lightweight repositories, small web apps, basic APIs, test environments, and early MVPs. For Docker stacks, database-backed apps, or self-hosted tools, Raff’s HiMem options can be more suitable because these workloads often need more RAM than expected. The **2 vCPU HiMem / 4 GB RAM / 80 GB NVMe** and **4 vCPU HiMem / 8 GB RAM / 160 GB NVMe** plans give teams more breathing room for multi-service development environments. Across visible Raff VM plans, users get resize support, NVMe storage, unmetered bandwidth, standard 3 Gbps port speed, and 1 IPv4 with optional IPv6. That matters because AI-assisted workflows may begin small, then grow as the team adds more tests, services, agents, and staging environments. The design principle is simple: give the agent and the developer a safe place to work, then keep production separate. ## Common mistakes when building AI-agent infrastructure The first mistake is giving the agent production access too early. AI agents should help prepare code for review. They should not directly control production systems unless the team has strong safeguards, audit logs, and approval gates. The second mistake is sizing the VM only for idle runtime. Agent workflows often install dependencies, run tests, build assets, and restart services. The environment must handle active development work, not only the app sitting idle. The third mistake is mixing too many services on a small VM. An app, database, queue, cache, worker, test runner, and monitoring tool can overwhelm an entry environment. When several services run together, memory pressure becomes the main risk. The fourth mistake is treating local setup as the source of truth. If every developer and agent uses a different environment, bugs become harder to reproduce. A shared cloud dev environment can create cleaner, more consistent validation. ## Best practices for cloud dev environments with AI agents ### Start with isolation before automation Create a safe development or staging boundary before giving agents more responsibility. The agent should work where mistakes are contained. ### Size the VM for build and test activity Do not size only for the running app. Consider dependency installation, test suites, Docker builds, package caches, logs, and temporary files. ### Keep production credentials out of agent workspaces Use test credentials and limited permissions. Production deployment should remain behind human approval. ### Use clear repository instructions Agents perform better when the project documents setup commands, test commands, coding conventions, and expected review steps. ### Resize when the workflow becomes slower or unstable If tests are slow because CPU is saturated, move to more CPU. If containers restart or swap appears, move to more memory. If Docker images and logs fill storage, choose more NVMe capacity. ## AI agents make development infrastructure more important, not less AI coding agents can change how developers work, but they do not remove the need for infrastructure. They still need clean environments, reliable dependencies, safe permissions, test execution, build capacity, logs, and human review. A good cloud dev environment gives the agent a place to work without risking production systems or polluting local machines. For small teams, the best starting point is usually simple: one clean VM for development or testing, clear boundaries around secrets, and enough CPU, memory, and storage for the project’s real workflow. For related infrastructure planning, read [Raff General Purpose VM Plans Explained](/learn/guides/raff-general-purpose-vm-plans-explained), [2 vCPU / 2 GB Cloud VM Workloads](/learn/guides/2-vcpu-2gb-cloud-vm-workloads), and [HiMem VMs Explained](/learn/guides/himem-vms-explained). If your team is experimenting with AI-assisted development, Raff’s Linux VMs give you a clean place to run code, test changes, and resize the environment as your workflow grows. --- ### Developer Supply Chain Security: Protecting Cloud Servers URL: https://rafftechnologies.com/learn/guides/developer-supply-chain-security-cloud-servers Description: Learn developer supply chain security risks, from dependencies and CI/CD secrets to cloud server access, with a practical protection framework. Developer supply chain security is the practice of protecting the tools, dependencies, workflows, and credentials used to build, test, deploy, and operate software. For many small teams, cloud server security starts with firewalls, SSH keys, operating system updates, and backups. Those are still important. But modern software rarely reaches a server directly from one developer’s laptop. Code passes through package managers, Git repositories, build tools, CI/CD workflows, containers, deployment scripts, secrets, SSH keys, and third-party developer tools. That chain is now part of the security boundary. Raff Technologies is relevant because many developers and small teams use cloud VMs as development, staging, and production environments. A secure VM is not only about the machine itself. It is also about what is allowed to deploy to it, which tools can reach it, and which credentials exist between the codebase and the server. This guide explains where developer supply chain risk appears, how compromised tools can affect cloud servers, and how to build a practical protection framework without turning a small team into an enterprise security department. ## Cloud server security starts before code reaches the server A cloud server can be patched, monitored, and properly configured, but still be exposed through the path that delivers code to it. That path might include: * A developer laptop * A Git repository * Package dependencies * IDE extensions * Build scripts * CI/CD workflows * Docker images * Deployment keys * SSH credentials * Environment variables * Cloud API tokens If one part of that chain is compromised, the server can become reachable indirectly. An attacker may not need to break into the VM through SSH. They may only need to steal a deployment token, modify a workflow file, poison a dependency, or access a secret used by the build pipeline. That is why developer supply chain security matters. It protects the path between code creation and production infrastructure. For small teams, this can feel abstract until the first incident happens. A leaked `.env` file, a public SSH key, an overpowered GitHub token, or a risky package update can create real exposure. The goal is to build simple guardrails before those mistakes become production problems. For broader infrastructure basics, this guide should link naturally to [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ## The most common risk is not the server itself Many teams secure the server but forget the tools around it. A cloud VM may have a strong password policy, SSH key access, updates, and a firewall. But if the deployment workflow stores production secrets too broadly, the server remains exposed. If any developer tool can read tokens or modify deployment scripts, the server inherits that risk. Common supply chain risk points include: * Dependencies installed from public package registries * Scripts that run automatically during install or build * CI/CD workflow files that can be changed in pull requests * Secrets stored in repository settings or plain files * Personal access tokens with broad permissions * Docker images pulled from untrusted sources * SSH keys reused across dev, staging, and production * IDE plugins or browser extensions with excessive access * Developer machines with access to production credentials The server is only one layer. The workflow around the server is another layer. A practical security mindset asks: **what can reach production, and what can change the code that reaches production?** That question usually reveals more risk than a basic server checklist. ## Dependencies can become part of the attack surface Modern software depends on third-party packages. That is normal. No team writes every library from scratch. But every dependency introduces a trust relationship. The package may be maintained by a strong team, a single developer, an abandoned project, or an account that could be compromised. Dependency risk can appear through: * Malicious new packages * Compromised maintainer accounts * Typosquatting package names * Abandoned dependencies * Vulnerable versions * Install scripts with unexpected behavior * Transitive dependencies several layers deep The practical answer is not “never use dependencies.” That is unrealistic. The answer is to reduce blind trust. Small teams can improve dependency security by using lockfiles, reviewing major updates, avoiding unknown packages for critical paths, pinning versions where appropriate, and removing libraries that are no longer needed. This matters for cloud servers because dependencies often run during build, deployment, or application startup. If a dependency can execute code, access environment variables, or change build output, it can affect what reaches the VM. Dependency hygiene is infrastructure hygiene. ## CI/CD workflows are privileged infrastructure CI/CD pipelines are not just automation. They are privileged systems. A deployment workflow may be able to pull code, install dependencies, access secrets, build artifacts, connect to a server, restart services, push containers, or run database migrations. That makes the pipeline powerful. If a workflow can deploy to production, it should be treated as part of production security. CI/CD risk often appears when workflows are too permissive: * Any branch can trigger deployment * Pull requests can access sensitive secrets * Tokens have broad repository or cloud permissions * Workflow files can be changed without review * Deployment scripts run untrusted code * Logs expose environment variables * Build jobs reuse long-lived credentials * Production deployment happens without human approval The safer pattern is to limit what each workflow can do. A test workflow does not need production secrets. A documentation build does not need SSH access. A pull request from an external contributor should not receive deployment credentials. A production deploy should require more control than a lint check. For small teams, this distinction is often the biggest improvement: separate testing workflows from deployment workflows. ## Secrets are the bridge between code and infrastructure Secrets are often the shortest path from a codebase to a cloud server. A secret might be an SSH private key, API token, database password, cloud credential, registry token, Git provider token, or webhook secret. If it allows code to deploy, connect, or authenticate, it needs careful handling. Common secret mistakes include: * Storing secrets in source code * Committing `.env` files * Reusing the same SSH key across environments * Giving CI/CD tokens more permissions than needed * Keeping old tokens active after people leave * Sharing production credentials in chat tools * Allowing secrets to appear in logs * Using one credential for development and production A better approach is to scope secrets by environment. Development secrets should not unlock production. Staging secrets should not unlock production databases. CI/CD deployment keys should do only what the deployment requires. If a key is exposed, the damage should be limited. This is also where rotation matters. A secret that has existed for years and is used everywhere becomes difficult to replace. Smaller, scoped secrets are easier to rotate when something goes wrong. ## SSH access should be narrow and intentional SSH is powerful because it gives direct server access. That power is useful for administration, troubleshooting, and deployment. It also creates risk when access is too broad. A good cloud server access model avoids treating SSH as a shared team shortcut. Instead, access should be deliberate: * Use SSH keys instead of reusable passwords * Give each person their own key * Remove old keys when access is no longer needed * Avoid sharing one root credential across the team * Disable unnecessary direct root access where possible * Separate development, staging, and production SSH keys * Restrict deployment keys to deployment tasks * Keep emergency access separate from daily access ![Terminal window showing separate SSH key files for development, staging, and production server access.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_06_01_at_11_10_54_6bc25a4f50.png) For small teams, the simplest improvement is individual access. If everyone uses the same key, nobody knows who did what and rotation becomes painful. If each person has their own key, access can be removed cleanly. SSH should be treated like production access, not convenience. ## A decision framework for developer supply chain risk Use this framework to decide what level of protection your team needs. | Situation | Risk level | Recommended protection | | -------------------------------------- | -------------- | ----------------------------------------------------------------- | | Personal test project | Low | Basic SSH keys, no production secrets, simple dependency review | | Public demo app | Low to medium | Separate test credentials, lockfiles, limited deployment access | | Small production website | Medium | Staging environment, scoped secrets, reviewed deploy workflow | | Database-backed app | Medium to high | Separate database credentials, backups, limited CI/CD permissions | | Customer-facing SaaS | High | Separate dev/staging/prod, protected branches, required reviews | | CI/CD deploys to production | High | Least-privilege tokens, workflow review, deployment approvals | | Multiple developers have server access | High | Individual SSH keys, access review, offboarding process | | AI agents or automation modify code | Medium to high | Isolated dev environment, human review, no production secrets | | Open-source contributors submit PRs | High | No secrets in untrusted PR workflows, strict workflow permissions | The key question is: **what can change production, and who or what can control that path?** If only one developer manually deploys a test project, the risk is lower. If a CI/CD workflow can deploy customer-facing software with production secrets, the risk is much higher. The protection level should match the blast radius. ## Separate development, staging, and production whenever possible Environment separation is one of the simplest ways to reduce supply chain risk. A development VM is where code can change quickly. A staging VM is where changes can be tested in a production-like environment. A production VM is where customer-facing workloads run. These environments should not all share the same credentials. A safer structure looks like this: | Environment | Purpose | Access level | | ----------- | ----------------------------------------------- | -------------------------------- | | Development | Experiment, build, test, agent-assisted changes | Low-risk credentials | | Staging | Validate changes before production | Production-like, but isolated | | Production | Serve real users and data | Strict, reviewed, limited access | This structure prevents a mistake in development from immediately becoming a production incident. ![Raff dashboard showing separate cloud VMs for development, staging, and production environments.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_06_01_at_11_03_26_1592238e5d.png) It also helps with AI-assisted development. If an AI coding agent, automation script, or junior developer works in a development environment, their mistakes stay contained. Production deployment remains a human-controlled decision. For related AI workflow planning, link to [AI Coding Agents and Cloud Dev Environments](/learn/guides/ai-coding-agents-cloud-dev-environments). ## AI-assisted development increases the need for boundaries AI coding agents and automation tools can improve productivity, but they also make boundaries more important. An AI assistant may edit files, suggest commands, generate workflow changes, update dependencies, or prepare pull requests. That does not mean it should have production access. It means the environment around it should be designed carefully. Safer AI-assisted development patterns include: * Run agent work in a development VM * Use test credentials only * Keep production secrets out of the workspace * Review workflow file changes manually * Review dependency changes carefully * Require human approval before deployment * Keep staging and production separate ![Terminal window showing a clean cloud development workspace prepared for AI-assisted coding.](https://raff-images.s3.raffusercloud.com/A_clean_cloud_development_workspace_gives_AI_assisted_coding_tools_a_safe_place_to_prepare_changes_before_they_reach_production_2f8eaf77ea.png) This is not about mistrusting AI. It is about using normal engineering discipline. Any tool that can change code should operate inside a boundary. A clean cloud dev environment gives the agent a place to work. Human review decides what moves forward. ## Raff context for supply chain-safe cloud workflows Raff VMs can help small teams create cleaner boundaries between development, staging, and production. A team might use one Raff Linux VM as a development or testing environment, another as staging, and a separate VM for production. This makes the deployment path easier to reason about. Code can be tested before it reaches the production server, and production secrets do not need to exist in every workspace. For lightweight development or testing, Raff’s **2 vCPU / 2 GB RAM / 50 GB NVMe** General Purpose plan can be a practical starting point. For staging environments with databases, Docker Compose stacks, or self-hosted tools, Raff’s HiMem options may be more suitable. For production workloads, teams can choose a larger General Purpose or CPU-focused plan depending on the workload. Across visible Raff VM plans, users get resize support, NVMe storage, unmetered bandwidth, standard **3 Gbps port speed**, and **1 IPv4 with optional IPv6**. This gives teams a simple way to start with separated environments and resize as the workflow grows. The design rationale is practical: secure workflows should not require enterprise complexity. Even a small team can separate development from production, limit secrets, and use cloud VMs as clear infrastructure boundaries. ## Common mistakes that expose cloud servers The first mistake is storing secrets in the repository. Even private repositories should not be treated as secret stores. Repositories are copied, cloned, backed up, integrated, and accessed by tools. Secrets belong in controlled secret systems or environment-specific settings. The second mistake is letting test workflows access production credentials. A workflow that runs on every pull request should not have the same access as a production deployment workflow. The third mistake is reusing SSH keys everywhere. One key for every server is convenient until it must be rotated. Separate keys by user, environment, and purpose. The fourth mistake is ignoring workflow file changes. CI/CD workflow files can be as sensitive as application code. If someone changes what the pipeline runs, they may change what gets deployed or what secrets are exposed. The fifth mistake is trusting dependencies without review. Package updates are useful, but they should not be automatic for critical production paths without some level of review, testing, or version control. ## Best practices for protecting cloud servers from supply chain risk ### Separate environments early Use separate development, staging, and production environments when the workload becomes customer-facing. This limits the impact of mistakes and compromised tools. ### Give CI/CD the least access it needs A pipeline should not have broad permissions by default. Give each workflow only the access required for its specific job. ### Review workflow changes like infrastructure changes CI/CD configuration controls how code moves to servers. Treat workflow changes as security-sensitive. ### Keep production secrets out of development Development environments should use test credentials. Production credentials should be limited, rotated, and protected. ### Pin and review important dependencies Use lockfiles, review major updates, and avoid unknown packages in critical paths. Dependency updates should be visible, not invisible. ### Use individual SSH keys Avoid shared server access. Individual keys make access easier to audit, revoke, and rotate. ### Resize security boundaries as the team grows A solo project may begin simply. A production team needs stronger boundaries, more review, and clearer separation between environments. ## Supply chain security is practical infrastructure hygiene Developer supply chain security is not only for large enterprises. Any team that uses dependencies, Git workflows, deployment scripts, CI/CD secrets, SSH keys, or cloud servers has a supply chain. The question is whether that chain is visible and controlled, or accidental and over-permissioned. The safest path is practical: separate environments, limit secrets, review workflow changes, control SSH access, and choose cloud server boundaries that match the workload’s risk. For broader infrastructure planning, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). For AI-assisted development boundaries, continue with [AI Coding Agents and Cloud Dev Environments](/learn/guides/ai-coding-agents-cloud-dev-environments). For choosing the right VM size for each environment, read [Raff General Purpose VM Plans Explained](/learn/guides/raff-general-purpose-vm-plans-explained). If your team is moving code from Git to cloud servers, Raff’s Linux VMs give you a simple way to separate development, staging, and production environments while keeping the infrastructure clear and resizeable. --- ### RDP VPS Pricing: What Actually Affects Cost? URL: https://rafftechnologies.com/learn/guides/rdp-vps-pricing-cost-factors Description: Learn what affects RDP VPS pricing, including Windows licensing, CPU, RAM, storage, bandwidth, backups, users, RDS CALs, and support needs. RDP VPS pricing is the monthly cost of running a Windows VPS that users access through Remote Desktop Protocol. The visible VPS plan price is only one part of the real cost. CPU, RAM, storage, Windows licensing, Remote Desktop usage, RDS CAL requirements, backups, bandwidth, support, and security all affect what a remote desktop server actually costs. Many buyers search for the cheapest RDP VPS and compare only the monthly price. That is risky. A very low-cost RDP VPS may be enough for one admin login, one lightweight Windows app, or a short test. But the same plan may become expensive if the workload needs more memory, multiple users, accounting software, SQL Server, backups, support, or Remote Desktop Services licensing. This guide explains what actually affects RDP VPS cost so small teams can compare plans more clearly before deploying. ## RDP VPS Pricing Explained An RDP VPS is usually a Windows VPS used through Remote Desktop Protocol. RDP is the access method. The VPS is the server. That distinction matters. You are not only paying for “RDP.” You are paying for the server environment behind the remote desktop session. That environment may include: * Windows Server * CPU * RAM * NVMe or SSD storage * Network bandwidth * IPv4 address * Remote Desktop access * Windows licensing * Optional RDS licensing * Backups or snapshots * Security controls * Support * Monitoring * Application setup * Future resizing A simple admin-only RDP server can be relatively small. A multi-user Remote Desktop environment running accounting software, browser sessions, file shares, and database tools needs more planning. So the better question is not: ```text What is the cheapest RDP VPS? ``` The better question is: ```text What does this Remote Desktop workload actually need to run safely? ``` ## The Monthly VPS Price Is Only the Starting Point The advertised monthly VPS price usually covers the base server resources. That typically means: * vCPU * RAM * storage * network port * operating system availability * basic VM access * public IP * provider infrastructure For a Linux VPS, that may be close to the full infrastructure cost. For an RDP VPS, the picture can be different because Windows workloads often have extra requirements. A Windows remote desktop workload may need: * More RAM than a basic Linux server * Windows licensing consideration * RDS CAL planning for multiple users * Stronger security controls * Backups for user files or business data * Enough CPU for desktop apps * Enough storage for profiles, logs, exports, and application data * Support for user access issues * Performance tuning for Remote Desktop sessions This is why two RDP VPS plans with the same headline price can have very different real value. One may include enough storage, bandwidth, support, and upgrade flexibility. Another may look cheap but become limiting once real users connect. ## The RDP VPS Cost Framework Use this framework before choosing a plan. | Cost factor | Why it matters | What to check | | ----------------- | -------------------------------------------------------------------------------- | ------------------------------------------------- | | CPU | Desktop apps, browsers, trading tools, and server roles consume CPU | vCPU count, CPU type, resize path | | RAM | Remote Desktop sessions are often memory-sensitive | RAM per user, app memory, browser usage | | Storage | Windows, apps, user profiles, logs, and files grow over time | NVMe/SSD size, storage expansion, backup storage | | Bandwidth | Remote Desktop, downloads, updates, file transfers, and apps use network traffic | Included traffic, overage risk, port speed | | Windows licensing | Windows Server is not the same as a free Linux OS | Whether Windows licensing is included or separate | | RDS licensing | Multi-user desktop access may need RDS CALs | Admin RDP vs RDS Session Host use case | | Backups | Business software and files need recovery planning | Backup price, retention, restore process | | Security | RDP is a sensitive access path | Firewall, access control, updates, monitoring | | Support | RDP issues often affect daily work | Support scope, response expectations | | Resizing | Remote Desktop workloads can outgrow the first plan | Upgrade/downgrade flexibility | This table is more useful than comparing only one number. A cheap RDP VPS can be the right choice for light use. It becomes the wrong choice when the workload depends on uptime, multiple users, data recovery, or software that needs more memory. ![Diagram showing the main factors that affect RDP VPS pricing, including CPU, RAM, storage, bandwidth, Windows licensing, RDS licensing, backups, support, and security.](https://raff-images.s3.raffusercloud.com/rdp_vps_cost_factors_diagram_webp_0938f12e21.png) ## CPU Affects RDP VPS Pricing CPU affects how responsive the remote desktop feels when users open apps, browse, run reports, or manage software. Light RDP access does not need a large CPU allocation. One admin checking Server Manager or running PowerShell is not the same as several users working inside browser-heavy sessions all day. CPU becomes more important when the VPS runs: * Multiple Remote Desktop sessions * Browsers * Accounting software * ERP clients * SQL tools * IIS applications * Trading platforms * Scheduled tasks * Antivirus scans * Reports or exports * Background services A low-cost RDP VPS may have enough CPU for setup and testing. Production workloads need enough headroom for normal peaks. For example, a remote desktop may feel fine when idle but slow down when users open browser tabs, run reports, or launch multiple apps at the same time. That is why pricing should be compared with the workload in mind. ## RAM Is Often the Biggest RDP Cost Driver RAM is one of the most important RDP VPS pricing factors. Windows Server already needs memory. Each user session adds more. Applications add even more. A small RDP server may look affordable with low RAM, but the user experience can become poor quickly if the server runs out of memory. RAM pressure usually comes from: * Windows Server itself * Remote Desktop sessions * User profiles * Browser tabs * Office-style applications * Accounting software * SQL Server * Antivirus * Backup processes * Background services * Monitoring tools For admin-only access, a smaller RAM plan may be enough. For real users doing daily work, RAM should be planned more carefully. A useful rule: ```text Size by concurrent activity, not only by total user count. ``` A company with 20 employees may only have 2 people connected at the same time. Another company with 6 employees may have all 6 working inside the server for hours. Concurrent users matter more than total employees. ## Storage Changes the Real Monthly Cost Storage affects both the base VPS price and the long-term operating cost. RDP VPS storage is used by: * Windows Server * Installed applications * User profiles * Downloads * Documents * Exports * Logs * Application data * Database files * Backup staging files * Temporary files * Windows updates A small storage plan may be enough at launch. But business software and user profiles can grow quietly. Storage also affects performance. NVMe storage is especially valuable when the Windows VPS handles database files, app data, logs, and multiple users. Before choosing the cheapest RDP VPS, ask: * How much storage does Windows need? * How much space do the applications need? * Will users save files on the server? * Will profiles grow over time? * Are databases involved? * Will backups be stored separately? * Can storage be expanded later? * What happens when the disk fills up? Disk space problems are not only annoying. They can break updates, stop applications, corrupt workflows, and make the server difficult to recover. ## Bandwidth and Port Speed Can Affect Value Remote Desktop itself is usually not as bandwidth-heavy as video streaming, but bandwidth still matters. An RDP VPS may use network traffic for: * Remote Desktop sessions * File uploads and downloads * Windows updates * Application updates * Database connections * Backups * Reports and exports * Browser traffic inside sessions * Software installers * User profile sync * Remote support activity Some providers include generous transfer. Others meter bandwidth or charge overages. That changes the real price. If two RDP VPS plans look similar, check: * Is bandwidth metered or unmetered? * Is there an overage fee? * What is the port speed? * Are backups counted separately? * Are file transfers common? * Will users download reports or large files? * Will the VPS run browser-based workflows all day? For small teams, predictable bandwidth can be more valuable than a slightly lower base price. ## Windows Licensing Can Change the Comparison RDP VPS pricing is different from Linux VPS pricing because Windows Server licensing may be part of the cost. Some providers include Windows licensing in the Windows VPS price. Others separate licensing, require bring-your-own licensing, or handle Windows through a specific provider licensing model. The buyer should check: * Does the listed price include Windows Server? * Which Windows Server versions are available? * Is the license suitable for hosted use? * Is BYOL allowed? * Are there restrictions by provider? * Does the provider support the Windows version you need? * Is the monthly price different for Windows and Linux? This is one reason “VPS from $X/month” can be misleading. The cheapest VPS price on a provider’s website may refer to Linux. A Windows VPS with Remote Desktop access can cost more because of operating system licensing and higher resource requirements. ## RDS CALs Can Be the Cost Factor Teams Miss Default RDP access and multi-user Remote Desktop Services are different. A small team may only need admin RDP for server management. In that case, the cost model is usually simpler. But if multiple employees use the Windows server as a daily desktop or app environment, Remote Desktop Services planning may apply. That can add licensing and management complexity. Use this distinction: | Use case | Cost implication | | ---------------------------------------------------- | ------------------------------------------------ | | One admin manages the server | Base Windows VPS cost may be the main cost | | Two admins occasionally connect | Still usually admin access planning | | Several employees need desktop sessions | RDS Session Host and RDS CAL planning may apply | | Users run accounting software through Remote Desktop | Licensing, RAM, backups, and support matter more | | Users need hosted apps instead of full desktops | Architecture and licensing should be reviewed | RDS licensing can be per-user, per-device, or service-provider style depending on the deployment and licensing path. This is why “RDP VPS pricing” cannot be answered only with a server plan table. The access model changes the cost. ## User Count Changes Pricing Only When Users Are Active User count matters, but not in the simple way many people expect. The total number of employees is less important than: * How many users connect at the same time * What each user does inside the session * Whether users need separate profiles * Whether the app supports multi-user access * Whether RDS licensing is required * Whether support needs increase with user count For example: | Scenario | Cost pressure | | ------------------------------------- | ----------------------------------------------- | | 1 admin connects occasionally | Low | | 1 user runs a light Windows app | Low to moderate | | 3 users run accounting software | RAM, storage, backups, licensing | | 8 users work inside RDP daily | RAM, CPU, RDS licensing, support | | 15 users run reports and browser apps | Larger VM, monitoring, support, backup planning | The practical pricing question is: ```text How many users are active at the same time, and what are they running? ``` That answer gives a better cost estimate than total company size. ## Application Type Affects the Right RDP VPS Size Not all RDP workloads are equal. The software running inside the Windows VPS can change the plan size more than the number of users. | Application type | Cost impact | | --------------------------- | ------------------------------------- | | Server Manager / PowerShell | Light | | Browser-based admin tools | RAM-sensitive | | Accounting software | RAM, storage, file/database behavior | | QuickBooks or Sage | Multi-user planning, backups, storage | | SQL Server tools | RAM and database pressure | | IIS / .NET apps | App pools, logs, memory, traffic | | MetaTrader / trading apps | Uptime, CPU, RAM, latency | | ERP clients | RAM, database, user count | | Legacy Windows apps | Compatibility and support testing | | Office-style apps | RAM and licensing review | A cheap RDP VPS may be fine for one admin tool. It may be a bad fit for multi-user accounting, SQL Server, or browser-heavy work. The application inventory should come before the pricing decision. ## Backups and Snapshots Are Part of the Real Cost Backups are easy to ignore when comparing monthly server prices. That is a mistake. If users store business data on the RDP VPS, recovery planning matters. Backups may cover: * The full VM * Specific files * User profiles * Application folders * SQL Server databases * Accounting company files * Reports and exports * Configuration files * License files * Scheduled task scripts Snapshots and backups may be included, optional, or billed separately depending on provider and setup. When comparing RDP VPS pricing, check: * Is backup storage included? * Is there a per-GB backup cost? * How often do backups run? * How long are backups retained? * Can backups be restored quickly? * Are application-aware backups needed? * Is SQL Server backed up separately? * Has anyone tested the restore process? The cheapest RDP VPS is not cheap if one failed update or deleted company file causes hours of downtime. ## Support Can Be Worth More Than the Price Difference RDP workloads often support real business activity. If a remote desktop server is slow or unreachable, users may not be able to work. Support matters when: * Users cannot log in * RDP disconnects * Windows updates fail * Disk space fills up * The server becomes slow * Backups fail * Firewall rules block access * Licensing errors appear * Applications stop working * A resize or migration is needed A low-cost provider with limited support may be acceptable for hobby usage. A business RDP server should be judged differently. The question is not only “what is the monthly price?” The question is: ```text What happens when the server blocks work during business hours? ``` That is part of the real cost. ## Cheap RDP VPS vs Reliable RDP VPS Cheap RDP VPS plans can be useful. They are a good fit for: * Testing * Learning * Short-term admin access * One lightweight Windows app * Personal use * Temporary environments * Low-risk workloads Reliable RDP VPS plans are better for: * Business software * Daily Remote Desktop users * Accounting workloads * Client data * SQL Server * Long-running automation * Remote teams * Production admin tools * Workloads that need backups and support The difference is not only price. It is workload risk. If the server can be deleted tomorrow without real damage, a cheaper plan may be fine. If the server contains company data or daily work, reliability and recovery matter more. ## RDP VPS Pricing Decision Matrix Use this matrix to choose the right cost level. | Situation | Recommended pricing mindset | | ----------------------------------------- | ------------------------------------------------------------------ | | Testing Remote Desktop for the first time | Start small and keep risk low | | One admin managing a server | Choose enough RAM for Windows and admin tools | | One user running light software | Prioritize RAM and storage over lowest price | | 2–5 users running business apps | Plan for CPU, RAM, backups, licensing, and support | | Multi-user Remote Desktop environment | Review RDS CALs, session policy, and support | | Accounting software or company files | Budget for backups and recovery | | SQL Server on the same VPS | Budget more RAM and storage performance | | Production daily work | Choose reliability, support, and resize path over the lowest price | The stronger the business dependency, the less the cheapest advertised price matters. ## A Practical RDP VPS Budget Model A useful RDP VPS budget should include more than the VM plan. Use this model: ![Visual budget model showing the real cost components of an RDP VPS, including base Windows VPS, storage, backups, RDS CALs, application licenses, support, migration, and monitoring.](https://raff-images.s3.raffusercloud.com/rdp_vps_budget_model_webp_702e31f773.png) This gives a more honest monthly estimate than the base VPS price alone. ## Raff RDP VPS Pricing Context At Raff, RDP VPS cost should be understood through the Windows VPS workload, not only the starting plan price. Raff’s pricing page is the current source of truth for monthly VM pricing. The plan you choose should depend on the workload: admin-only RDP, one remote user, business software, multi-user sessions, accounting tools, SQL Server, IIS, or always-on Windows applications. Raff plans are designed around practical cloud VM usage: NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and predictable monthly pricing. For RDP use cases, that means the biggest decision is usually not “what is the cheapest plan?” It is “which plan has enough RAM, storage, and headroom for the users and applications?” A small admin-only Windows VPS can start smaller. A business Remote Desktop environment may need more RAM, better backup planning, and licensing review. If the workload grows, resizing is usually better than forcing a real business process to stay on a plan that no longer fits. Use Raff’s pricing page to check current plan options, then choose the Windows VPS size based on concurrent users, application load, data protection, and licensing needs. ## Common Mistakes When Comparing RDP VPS Pricing ### Comparing Linux VPS prices to Windows VPS needs A very low VPS price may apply to Linux or lightweight use. Windows Remote Desktop workloads often need more RAM, licensing consideration, and support. ### Assuming RDP means unlimited users RDP access does not automatically mean a server is ready for multiple daily users. Multi-user desktop access may require Remote Desktop Services planning. ### Buying too little RAM RAM is often the first bottleneck in Remote Desktop environments. A plan that is fine for setup may feel slow with real users. ### Ignoring backups If users save files or run business software on the server, backup cost is part of the real price. ### Choosing by storage size only Storage type and performance matter too. Databases, logs, profiles, and business files benefit from fast storage. ### Forgetting application licenses The VPS plan does not replace software licensing. QuickBooks, Sage, SQL Server, Office apps, and ERP tools may have their own licensing rules. ### Treating support as optional For business RDP use, support quality can matter more than saving a few dollars per month. ## Best Practices for Choosing an RDP VPS Plan ### Start with the workload List the users, applications, files, databases, and access model before comparing prices. ### Separate admin RDP from user desktops Admin access and daily multi-user Remote Desktop work have different cost and licensing requirements. ### Size for concurrent users Use active simultaneous users as the sizing baseline, not the total employee count. ### Give Windows enough RAM Do not choose the smallest plan if users will run browsers, accounting software, SQL tools, or multiple apps. ### Budget for backups If the server holds business data, backups are not optional. ### Check licensing before production Review Windows, RDS, application, SQL Server, and Microsoft app licensing before moving real users. ### Choose a provider with a resize path Remote Desktop workloads can grow. The provider should make it practical to move to a stronger plan. ### Test before migrating daily work Run the actual software, not just the Windows desktop, before deciding the final size. ## Conclusion RDP VPS pricing is not only the monthly server number. The real cost depends on what the Windows VPS is expected to do. A lightweight admin server, a one-user Remote Desktop machine, a multi-user accounting environment, and a SQL-backed business server all have different cost profiles. Before choosing a plan, compare CPU, RAM, storage, bandwidth, Windows licensing, RDS requirements, backups, support, and resize flexibility. For current Raff VM pricing and Windows VPS options, review the pricing page: [View Raff pricing](/pricing) ## Sources * [Raff — Pricing](/pricing) * [Raff — Windows VPS Hosting for Small Teams](/learn/guides/windows-vps-hosting-small-teams) * [Raff — RDS CAL Licensing Guide](/windows-server/rds-cal-licensing-guide) * [Raff — Multi-User RDP vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) * [Microsoft Learn — License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) * [Microsoft Learn — Remote Desktop Services: Choose how you pay](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-plan-choose-how-you-pay) * [Microsoft Learn — Remote Desktop Services overview](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) --- ### VPS vs Cloud VM vs Cloud Server: What’s the Difference? URL: https://rafftechnologies.com/learn/guides/vps-vs-cloud-vm-vs-cloud-server-explained Description: Learn the difference between VPS, cloud VM, and cloud server, when the terms overlap, and how to choose the right virtual server for apps, websites, and workloads. VPS, cloud VM, and cloud server are terms people often use when talking about virtual servers, but they do not always mean exactly the same thing. The practical answer is simple: **A VPS is a virtual private server product. A cloud VM is the technical virtual machine resource. A cloud server is the user-friendly term for a server you deploy and manage online.** In many cases, all three terms point to the same basic idea: ```text A virtual server with CPU, RAM, storage, networking, an operating system, and root or administrator access. ``` The difference is mostly how the product is described. A developer might say: ```text I need a cloud VM for this app. ``` A hosting buyer might say: ```text I need a VPS. ``` A business owner might say: ```text I need a cloud server. ``` They may all be asking for the same thing: a virtual machine they can deploy, access, and control. This guide explains what each term means, where the terms overlap, where they differ, and how to choose the right server for your workload. ## Quick answer | Term | Simple meaning | Best way to think about it | | ------------ | ---------------------- | ---------------------------------------------------------------- | | VPS | Virtual private server | Product category used by hosting providers | | Cloud VM | Cloud virtual machine | Technical compute resource running on virtualized infrastructure | | Cloud server | Server deployed online | User-friendly term for a VM-based server in the cloud | ![VPS vs Cloud VM vs Cloud Server comparison infographic showing the shared virtual server foundation, key differences, typical users, use cases, and what buyers should compare before choosing a server.](https://raff-images.s3.raffusercloud.com/vps_vs_cloud_vm_vs_cloud_server_infrastructure_comparision_png_33f55be122.png) The short version: > VPS is the hosting-market term. Cloud VM is the technical infrastructure term. Cloud server is the customer-friendly product term. For most users, the more important question is not the label. The better question is: > Does this server give me the CPU, RAM, storage, bandwidth, operating system, access, security, and reliability my workload needs? ## What is a VPS? A VPS, or virtual private server, is a virtual server created by dividing physical server hardware into separate virtual environments. Each VPS usually has its own: * CPU allocation * RAM allocation * storage * operating system * IP address * SSH or remote access * firewall rules * application environment A VPS feels like a server you control, even though it runs on shared physical infrastructure. You can use a VPS to host: * websites * APIs * SaaS apps * staging environments * databases * Docker workloads * VPN servers * automation tools * game servers * business applications * internal dashboards The word “VPS” is common in the hosting industry. Buyers often search for VPS when they want a server that is more flexible than shared hosting but simpler than large enterprise cloud platforms. A VPS is usually a good fit when you want: * root access * predictable monthly pricing * full server control * the ability to install packages * a public IP address * Linux or Windows server access * a place to run apps, websites, or services ## What is a cloud VM? A cloud VM, or cloud virtual machine, is a virtual machine running on cloud infrastructure. Technically, a VM is created by a virtualization layer. It behaves like a standalone server with virtual CPU, memory, disk, and networking. A cloud VM usually includes: * vCPU * RAM * virtual disk * network interface * public or private IP * operating system image * firewall and network controls * console or SSH access * snapshot or backup options The term “cloud VM” is common among developers, DevOps teams, and infrastructure teams. It sounds more technical than VPS because it describes the actual compute unit: a virtual machine. You might use a cloud VM for: * production app servers * Docker hosts * CI/CD runners * databases * monitoring tools * internal services * development servers * private network workloads * reverse proxy servers * load-balanced app nodes A cloud VM can be part of a larger cloud architecture. For example: ```text Load balancer ↓ Cloud VM 1 Cloud VM 2 Cloud VM 3 ↓ Private database VM ``` In that setup, each VM is a building block in the infrastructure. ## What is a cloud server? A cloud server is a broader, user-friendly term for a server that runs in a cloud environment. In most cases, a cloud server is a cloud VM presented as a usable product. The phrase “cloud server” is often used when the audience does not need to think about virtualization details. It focuses on the outcome: ```text You get a server online, deploy an operating system, connect to it, and run your workload. ``` A cloud server usually provides: * online deployment * public IP address * operating system selection * compute resources * storage * network access * security controls * backup or snapshot options * remote management Cloud server is a practical term for buyers who care less about whether the provider calls it a VPS or VM and more about what they can run on it. Examples: * “I need a cloud server for my web app.” * “I need a cloud server for a database.” * “I need a Windows cloud server for accounting software.” * “I need a Linux cloud server for Docker.” In many product pages, “cloud server” and “cloud VM” mean nearly the same thing. ## Are VPS and cloud VM the same thing? Often, yes. A VPS and a cloud VM can both describe a virtual server with CPU, RAM, storage, networking, and an operating system. The difference is usually product positioning. | Question | VPS | Cloud VM | | ------------------------------------------ | ----------- | ---------- | | Is it virtualized? | Yes | Yes | | Does it run an operating system? | Yes | Yes | | Can you access it remotely? | Usually yes | Yes | | Can it host apps and websites? | Yes | Yes | | Is it a technical compute unit? | Sometimes | Yes | | Is it a hosting product term? | Yes | Sometimes | | Is it used in cloud architecture diagrams? | Less often | More often | The term VPS is more common in hosting and search behavior. The term cloud VM is more common in infrastructure, DevOps, and cloud architecture. A provider might sell “cloud servers,” but technically those servers are virtual machines. A buyer might search for “VPS,” but the product they choose may be a cloud VM. The terms overlap heavily. ## VPS vs cloud VM vs cloud server comparison | Factor | VPS | Cloud VM | Cloud server | | --------------- | ------------------------------------- | -------------------------------------------- | ------------------------------------------- | | Main meaning | Virtual private server | Virtual machine in cloud infrastructure | Online server product | | Audience | Hosting buyers, developers, SMBs | Developers, DevOps, infrastructure teams | General buyers and technical users | | Technical depth | Medium | High | Low to medium | | Typical access | SSH, RDP, console | SSH, RDP, console, API | SSH, RDP, console | | Common use | Websites, apps, VPS hosting | App nodes, databases, CI/CD, infrastructure | Websites, apps, business workloads | | Pricing style | Often monthly | Monthly or usage-based depending on provider | Usually plan-based | | Best for | Buyers who want a controllable server | Teams designing cloud infrastructure | Users who want a simple server in the cloud | The safest interpretation: > A VPS is usually a type of cloud server. A cloud VM is the technical resource behind many cloud servers. A cloud server is the product-level name users understand. ## Why providers use different terms Providers use different terms because different buyers search for different things. A developer may search for: ```text cloud VM for Docker ``` A small business owner may search for: ```text cloud server for accounting software ``` A hosting buyer may search for: ```text cheap VPS hosting ``` A DevOps team may search for: ```text Linux VM with private networking ``` These searches can point to similar products. The terminology changes based on audience: * **VPS** sounds familiar to hosting buyers. * **Cloud VM** sounds precise to technical teams. * **Cloud server** sounds clear to business and general users. This is why you may see one provider use all three terms on different pages. That is not always a contradiction. It is often a way to describe the same infrastructure from different angles. ## Which term should you care about? If you are choosing infrastructure, do not over-focus on the term alone. Focus on what the server actually provides. Check: * How many vCPUs does it include? * How much RAM does it include? * What type of storage is used? * Is the storage NVMe SSD? * How much bandwidth is included? * Is bandwidth metered or unmetered? * What operating systems are available? * Can you use Linux or Windows? * Do you get root or administrator access? * Are backups and snapshots available? * Is private networking available? * Are firewall rules available? * Is there DDoS protection? * How fast is deployment? * Is support responsive? * Is pricing predictable? These factors matter more than whether the page says VPS, cloud VM, or cloud server. A weak “cloud VM” is not better than a strong “VPS” just because the term sounds more modern. A good server is good because of performance, reliability, pricing, support, and operational fit. ## When should you choose a VPS? Choose a VPS when you want a simple, controllable server for a clear workload. A VPS is a good fit for: * websites * web apps * small SaaS apps * APIs * staging servers * developer environments * Linux services * Windows workloads * Docker Compose apps * internal tools * small databases * VPN servers * automation tools A VPS is usually better than shared hosting when you need: * root access * custom packages * server-level control * better isolation * app runtimes * background workers * custom firewall rules * Docker * database control For many teams, VPS is the practical starting point before larger cloud architecture becomes necessary. ## When should you choose a cloud VM? Choose a cloud VM when you are designing infrastructure at the VM level. A cloud VM is a good fit when you need: * app server nodes * database server nodes * private networking * load-balanced app servers * CI/CD runners * monitoring servers * worker VMs * separate dev/staging/production environments * infrastructure automation * API-based provisioning * snapshots and backups * repeatable deployment patterns Cloud VM is the better term when you are thinking in architecture diagrams. Example: ```text VM 1: reverse proxy VM 2: application server VM 3: database server VM 4: worker server ``` This is more infrastructure-oriented than saying “four VPS plans,” even if the underlying product is similar. ## When should you choose a cloud server? Choose a cloud server when your main goal is to deploy and manage a server online without worrying too much about terminology. A cloud server is a good fit for: * business websites * company applications * remote access workloads * internal systems * simple app hosting * managed infrastructure replacement * general-purpose Linux or Windows hosting Cloud server is the broadest term. It is useful when explaining infrastructure to non-specialists. For example: ```text We moved the app from an office server to a cloud server. ``` That sentence is easier for many business users than: ```text We moved the app to a Linux virtual machine running on cloud infrastructure. ``` Both may describe the same architecture. ## How Raff VM fits this terminology Raff VM is best understood as a cloud server product built around virtual machines. That means it can be described in all three ways depending on the user’s intent: | User says | Raff answer | | --------------------- | ------------------------------------------------------------------------ | | I need a VPS | Raff VM gives you a virtual server with CPU, RAM, storage, and OS access | | I need a cloud VM | Raff VM gives you a deployable virtual machine for apps and workloads | | I need a cloud server | Raff VM gives you an online server you can deploy and manage quickly | Raff VM is designed for teams that want cloud servers without unnecessary cloud complexity. You can use Raff VM for: * Linux app hosting * Windows workloads * Docker deployments * APIs * staging environments * internal tools * business applications * remote access workloads * databases * automation servers * development environments Raff’s role is to provide the compute foundation: a cloud server / VM / VPS that you can deploy, access, secure, and scale based on your workload. ## VPS vs cloud platforms VPS, cloud VMs, and cloud servers are often simpler than large cloud platforms. A large cloud platform may include hundreds of services: * compute * managed databases * serverless functions * queues * IAM * load balancers * object storage * observability tools * Kubernetes * data pipelines * enterprise networking That can be powerful. It can also be more complex than small teams need at the beginning. A VPS or cloud VM is often enough when the workload needs: * one server * a few services * predictable monthly cost * root access * standard Linux or Windows * a clean place to run an app * Docker or Nginx * a database * backups * firewall rules * simple scaling path A practical rule: > Use a cloud server when the workload is server-shaped. Use a larger cloud platform when the architecture truly needs many managed services. Many apps start as server-shaped workloads. That is why VPS and cloud VM products still matter. ## Common mistakes when comparing VPS and cloud servers ### Mistake 1: Thinking cloud VM always means better than VPS A cloud VM is not automatically better than a VPS. Compare the actual specs, storage, networking, reliability, support, and pricing. ### Mistake 2: Choosing only by the lowest monthly price The cheapest plan may not be the best value. Slow storage, weak CPU performance, limited bandwidth, poor support, or missing backups can cost more later. ### Mistake 3: Ignoring bandwidth Bandwidth can matter for APIs, media-heavy websites, SaaS apps, backups, downloads, and customer-facing workloads. Always check whether bandwidth is metered, capped, or unmetered. ### Mistake 4: Ignoring storage type NVMe SSD storage is usually better for modern applications than older disk or basic SSD storage. Storage speed affects database performance, builds, file operations, and app responsiveness. ### Mistake 5: Forgetting backups A virtual server is not a backup strategy. Check whether backups, snapshots, or recovery options are available before production use. ### Mistake 6: Choosing cloud complexity too early A large cloud platform may be unnecessary for a simple app, internal tool, or early SaaS product. Start with the simplest infrastructure that meets the reliability and growth needs. ## Decision framework Use this framework if you are still unsure. | Need | Best term to search | What to choose | | --------------------------------- | ----------------------------------- | ---------------------------------------- | | Simple website or app hosting | VPS or cloud server | General-purpose cloud server | | Technical infrastructure node | Cloud VM | VM with clear CPU/RAM/storage/networking | | Business app online | Cloud server | Easy-to-manage VM product | | Docker host | VPS or cloud VM | Linux VM with enough CPU/RAM/NVMe | | Windows workload | Windows VPS or Windows cloud server | Windows VM | | Private app/database architecture | Cloud VM | Multiple VMs with private networking | | Predictable monthly server cost | VPS or cloud server | Plan-based VM pricing | | Developer environment | VPS or cloud VM | Small Linux VM | | Scaling application tier | Cloud VM | Multiple app VMs behind a load balancer | The name is less important than the fit. Choose the server that matches the workload. ## Conclusion VPS, cloud VM, and cloud server are closely related terms. A VPS is usually the hosting product term. A cloud VM is the technical virtual machine term. A cloud server is the user-friendly product term. In many buying decisions, they point to the same thing: a virtual server you can deploy online and use for real workloads. The term matters less than the server behind it. Before choosing a provider, compare CPU, RAM, NVMe storage, bandwidth, operating systems, root access, firewall rules, backups, snapshots, private networking, support, and pricing model. For teams that want a simple virtual server for apps, websites, Docker, internal tools, databases, or business workloads, Raff VM fits naturally into all three categories: VPS, cloud VM, and cloud server. The best choice is the one that gives your workload the right balance of control, performance, reliability, and simplicity. --- ### When Should a Small Business Move from Shared Hosting to a VPS? URL: https://rafftechnologies.com/learn/guides/shared-hosting-vs-vps-small-business Description: Learn when a small business should move from shared hosting to a VPS, including performance, control, security, scaling, backups, and migration signs. Shared hosting is often the easiest way to put a small business website online. It is cheap. It is simple. It usually comes with a control panel. It works well for basic websites, landing pages, and early-stage business sites. But shared hosting has a ceiling. At some point, your website or application may need more performance, more control, better reliability, custom software, stronger security, or a cleaner growth path. That is when moving from shared hosting to a VPS starts to make sense. The short answer: > A small business should move from shared hosting to a VPS when the website or application becomes important enough that performance, control, reliability, security, or flexibility can no longer depend on a shared environment. This guide explains when shared hosting is still enough, when it becomes limiting, and how to decide whether a VPS is the right next step for your business. ## Quick answer Shared hosting is enough when your business only needs a simple website, low traffic, standard CMS features, and minimal technical control. A VPS is better when your business needs: * faster performance * more predictable resources * root or administrator access * custom software * better isolation * more control over security * custom backend apps * database control * Docker or modern deployment workflows * stronger backup planning * staging environments * business-critical uptime * room to grow A practical rule: > Stay on shared hosting while your website is simple. Move to a VPS when your hosting environment starts limiting your business. ## Shared hosting vs VPS: the simple difference Shared hosting means your website runs on a server shared with many other customers. ![Shared hosting vs VPS comparison for small business showing the difference between simple shared website hosting and a more flexible VPS server environment.](https://raff-images.s3.raffusercloud.com/shared_hosting_vs_vps_small_business_comparison_png_6815814446.png) You usually get: * a hosting account * a control panel * limited storage * limited CPU and memory usage * shared server resources * preconfigured PHP, database, and email tools * restricted server access * limited customization A VPS, or virtual private server, gives you a virtual server with dedicated operating system access. You usually get: * CPU allocation * RAM allocation * storage * operating system control * SSH or remote access * firewall control * software installation control * web server control * database control * application deployment flexibility The difference is control. Shared hosting gives you a managed box inside someone else’s server environment. A VPS gives you your own server environment. ## What shared hosting is good for Shared hosting is not bad. It is useful for many small businesses. It can be a good fit for: * brochure websites * simple WordPress sites * local business websites * small service pages * early landing pages * low-traffic blogs * basic company websites * simple contact forms * websites with no custom backend * businesses without technical support Shared hosting works best when your website is mostly static or CMS-based and does not need much server customization. For example, a small law firm, restaurant, consultant, photographer, or local service business may be fine on shared hosting if the website only includes: * homepage * service pages * about page * contact form * blog * basic SEO pages * simple analytics * standard plugins In this stage, the business needs visibility more than infrastructure control. Shared hosting solves that. ## What a VPS gives you that shared hosting does not A VPS gives your small business a real server environment. That unlocks more control. With a VPS, you can usually manage: * operating system packages * web server configuration * database configuration * firewall rules * SSL setup * background workers * cron jobs * custom runtimes * app deployments * Docker containers * staging environments * monitoring tools * backup scripts * security hardening This matters when the website becomes more than a simple website. For example, a small business may need to run: * a customer portal * booking system * internal dashboard * API backend * custom CRM * private application * inventory system * automation tool * business database * Laravel, Node.js, Python, or Docker app * WordPress site with high traffic or heavy plugins Shared hosting may not give you enough control for these workloads. A VPS does. ## 9 signs your small business has outgrown shared hosting ### 1. Your website is slow even after basic optimization If your site is slow, first check normal causes: * large images * too many plugins * poor theme performance * no caching * heavy third-party scripts * unoptimized database * weak frontend structure But if the site is still slow after basic optimization, shared hosting may be part of the problem. On shared hosting, your website can be affected by resource limits and other customers on the same server. A VPS gives your business a cleaner environment where you can control the stack, caching, database, PHP version, web server, and background processes. Move to a VPS when speed is no longer just a design issue — it is an infrastructure issue. ### 2. Traffic spikes cause errors or downtime A small business website may start with low traffic. Then traffic grows from: * SEO * ads * email campaigns * seasonal demand * product launches * local press * social posts * marketplace listings * partner campaigns If shared hosting cannot handle spikes, users may see: * slow pages * timeout errors * database connection errors * 500 errors * temporary account throttling * unavailable checkout or forms That is a strong sign to move. A VPS gives you more room to handle predictable growth and lets you tune the environment around the workload. ### 3. Your hosting account keeps hitting resource limits Shared hosting plans often limit CPU, memory, processes, database usage, file count, or I/O. You may see messages like: * CPU usage exceeded * memory limit reached * entry process limit reached * inode limit reached * database connection limit reached * account temporarily restricted * backup limit exceeded These are warning signs. They mean your business is asking more from the hosting environment than the plan is designed to provide. A VPS gives you clearer resource ownership and more control over how those resources are used. ### 4. You need custom software or server configuration Shared hosting is usually designed for standard website hosting. It may not allow: * custom system packages * custom Nginx or Apache configuration * long-running processes * background workers * queue workers * WebSocket servers * Docker * advanced cron jobs * custom database tuning * custom runtime versions * private internal services If your business needs these things, shared hosting becomes limiting. A VPS is the better fit when you need to control the server, not just upload website files. ### 5. Your website is now tied to revenue The hosting decision changes when the site becomes business-critical. Shared hosting may be fine for an informational site. But it becomes risky when the site supports: * lead generation * paid ads * checkout * customer accounts * appointment booking * quote requests * support forms * SaaS onboarding * client portals * internal operations If downtime or slow performance costs real money, you need stronger infrastructure control. A VPS gives you more ownership over reliability, monitoring, backups, updates, and recovery planning. ### 6. You need better security isolation On shared hosting, many users share the same physical server environment. Providers isolate accounts, but the model is still shared. A VPS gives your business a separate operating system environment. That helps when you need: * stronger firewall control * SSH key access * custom security tools * private services * limited open ports * stronger user permissions * cleaner separation from other customers * more control over updates and patches A VPS does not automatically make your business secure. You still need good configuration. But it gives you the control needed to build a stronger security posture. ### 7. You need better backup and recovery control Shared hosting often includes basic backups, but the level of control varies. You may not control: * backup schedule * retention period * restore process * database snapshot timing * off-server storage * backup testing * application-consistent backups For a small business, backups become important when the site contains: * customer data * orders * bookings * uploaded files * form submissions * account data * business records * internal workflows A VPS lets you design a better backup strategy around your actual workload. You can combine provider snapshots, application backups, database dumps, and off-server storage. The important point: > A backup is only useful if you know how to restore it. A VPS gives you more responsibility, but also more control. ### 8. You need staging, testing, or deployment workflows Shared hosting is usually not ideal for modern development workflows. A growing business may need: * staging environment * separate production environment * Git-based deployment * CI/CD * Docker Compose * automated tests * rollback process * private preview environment * controlled release process A VPS makes these workflows easier. You can run a staging VM, test changes safely, then deploy to production with more confidence. For small businesses working with an agency or developer, this can reduce mistakes and downtime. ### 9. You are building more than a website This is the biggest sign. Shared hosting is for websites. A VPS is for workloads. Move when your business needs to run: * web apps * APIs * dashboards * automation tools * databases * background workers * private business software * Docker containers * monitoring services * internal tools * customer portals Once your “website” becomes an application, shared hosting is often the wrong foundation. ## Shared hosting vs VPS comparison table | Factor | Shared hosting | VPS | | ------------------------------ | ------------------- | ------------------------------------------- | | Best for | Simple websites | Websites, apps, APIs, business workloads | | Control | Limited | High | | Server access | Usually restricted | Root or administrator access | | Performance | Shared resources | Allocated VM resources | | Custom software | Limited | Flexible | | Security control | Provider-controlled | Team-controlled | | Backups | Depends on host | Can be designed around workload | | Scaling | Plan upgrade only | Resize, tune, split workloads, add services | | Technical responsibility | Low | Medium to high | | Cost | Lower starting cost | Higher, but more control | | Fit for business-critical apps | Limited | Stronger | | Fit for Docker | Usually no | Yes | | Fit for custom backend | Limited | Yes | The decision is not only about price. It is about whether the hosting model matches the business requirement. ## When you should stay on shared hosting Do not move to a VPS just because it sounds more professional. Stay on shared hosting if: * your website is simple * traffic is low * performance is acceptable * you do not need custom software * you do not have technical support * your site is not business-critical * you only need basic WordPress or static pages * you are not hitting hosting limits * you do not need server-level control * the current setup is stable and cost-effective A VPS gives you more power, but also more responsibility. You need to think about: * updates * firewall rules * backups * monitoring * security patches * web server configuration * database maintenance * access control * recovery planning If no one on your team can manage that, either stay on shared hosting or work with a technical partner. The wrong VPS setup can be worse than a good shared hosting setup. ## When you should move to a VPS Move to a VPS when at least one of these is true: * your site is too slow on shared hosting * your site regularly hits resource limits * downtime affects sales or leads * you need custom backend software * you need Docker or modern app deployment * you need better control over backups * you need stronger isolation * you need staging and production environments * you need custom firewall rules * you need database control * you need root access * your business app cannot fit inside shared hosting limits * your traffic is growing and you need room to scale A strong signal is when you start changing your business plan because of hosting limitations. Examples: * “We cannot launch this feature because hosting does not support it.” * “We cannot run background jobs.” * “We cannot install the package we need.” * “We cannot handle traffic spikes.” * “We do not know if backups are enough.” * “The site is slow but we cannot tune the server.” * “Our developer says the host is limiting the app.” At that point, shared hosting is not saving money. It is slowing the business down. ## The shared-hosting ceiling Most businesses do not outgrow shared hosting overnight. They hit a ceiling gradually. At first, shared hosting feels perfect. ![Shared hosting ceiling infographic showing how a small business website grows from a simple site to higher traffic, more backend needs, resource limits, and eventually a VPS migration.](https://raff-images.s3.raffusercloud.com/shared_hosting_ceiling_vps_migration_infographic_png_bed4bef919.png) Then the business adds more: * more pages * more plugins * more traffic * more forms * more integrations * more customer data * more backend logic * more database activity * more automation * more business dependency Eventually, the hosting environment becomes the constraint. This is the shared-hosting ceiling. You can recognize it when the answer to many problems becomes: ```text The host does not allow that. ``` or: ```text The plan cannot handle that. ``` A VPS removes many of those restrictions. It gives your team a proper server foundation. ## The VPS readiness checklist Before moving from shared hosting to a VPS, check whether your business is ready. You should know: * what website or app will move * which domain will point to the VPS * which CMS or application stack you use * which database you use * how files are stored * how email is handled * what DNS records exist * what SSL certificates are needed * what ports must be open * what backup strategy is required * who will maintain the server * how updates will be handled * how rollback will work if migration fails A VPS migration is not only “copy files to a new server.” It is a hosting architecture change. Plan it properly. ## What to prepare before migrating ### 1. Audit the current website List: * website files * database * plugins * themes * custom code * cron jobs * forms * redirects * DNS records * SSL settings * email settings * third-party integrations You need to know what exists before moving it. ### 2. Separate website hosting from email Many small businesses use the same shared hosting account for website and email. Be careful. Moving the website does not mean you must move email. In many cases, keep business email on a dedicated email provider and move only the website or application to the VPS. Before migration, confirm: * MX records * SPF record * DKIM * DMARC * webmail access * mailbox provider * contact form sending method Do not break business email during a website migration. ### 3. Choose the right VPS size Start with the workload. For a small website or app, you may not need a large server. Consider: * traffic level * CMS or app type * database size * plugin weight * background jobs * caching * expected growth * number of users * storage needs * backup size A simple site can start small. A busy WordPress site, WooCommerce store, Laravel app, Node.js backend, or database-heavy app may need more RAM and CPU. Do not only choose the cheapest plan. Choose the plan that gives your workload enough room to run reliably. ### 4. Plan DNS cutover DNS controls where visitors go. Before migration: * lower TTL if needed * confirm current DNS provider * document existing records * prepare new A record * test the new server before switching * switch during a low-traffic window * monitor after cutover DNS mistakes can make a successful migration look broken. ### 5. Set up security before going live Before pointing traffic to the VPS, configure: * SSH keys * firewall rules * automatic security updates if appropriate * non-root user access * SSL certificates * database access restrictions * strong passwords or key-based authentication * limited open ports * backups * monitoring Do not migrate first and secure later. Production servers should be hardened before public traffic arrives. ### 6. Test before switching traffic Before DNS cutover, test: * homepage * inner pages * forms * login * checkout * database connection * file uploads * redirects * SSL * admin panel * cron jobs * third-party integrations * mobile layout * page speed * error logs A VPS gives more control, but you still need a careful release process. ## What changes after moving to a VPS? Moving to a VPS changes ownership. On shared hosting, the provider manages much of the environment. On a VPS, your team controls more of the environment. That means more power and more responsibility. You become responsible for: * server updates * web server configuration * application runtime * firewall configuration * access control * backups * monitoring * logs * SSL renewal * deployment process * security hygiene This is not a reason to avoid VPS. It is a reason to run it properly. A VPS is a better tool when your business needs control. But control only helps if it is managed. ## Common VPS mistakes small businesses should avoid ### Choosing a VPS with no maintenance plan A VPS is not “set and forget.” Decide who will maintain it. This can be: * internal developer * agency * MSP * freelance sysadmin * technical founder * managed support partner Someone must own updates, backups, and monitoring. ### Moving email without planning Website hosting and email hosting are different problems. Do not accidentally break email by changing DNS records too quickly. ### Opening too many ports Only expose the services that must be public. For most web apps, public ports are usually: * 80 for HTTP * 443 for HTTPS * 22 for SSH, ideally restricted and key-based Databases, admin panels, and internal tools should not be publicly exposed unless there is a clear reason and proper protection. ### Forgetting backups A VPS gives you control, but it also means you need a backup plan. Use a layered approach: * provider snapshots * application backups * database dumps * off-server storage * restore testing Backups are not complete until restore has been tested. ### Migrating without staging Do not make the first test happen in production. Set up the VPS, test the site, then switch DNS. ## Shared hosting to VPS: decision framework Use this simple traffic-light model. ### Green: shared hosting is still fine Stay on shared hosting if: * the website is simple * speed is acceptable * traffic is low * there are no resource limit issues * the site is not business-critical * no custom backend is needed * no technical team is available ### Yellow: start planning a VPS move Start planning if: * traffic is growing * plugins or custom code are increasing * the site is becoming revenue-related * the team needs staging * performance is inconsistent * backups are unclear * the business may add a portal, app, or integration soon ### Red: move to a VPS Move if: * the site regularly slows down or times out * the host throttles your account * revenue is affected by downtime * custom software is blocked * security or isolation requirements increased * your developer cannot deploy properly * you need Docker, background workers, APIs, or app services * shared hosting is blocking business growth This framework keeps the decision practical. Do not move too early for complexity. Do not wait too long when hosting is already hurting the business. ## How Raff VM fits the move from shared hosting to VPS Raff VM is a strong next step when a small business has outgrown shared hosting and needs a proper cloud server. You can use Raff VM for: * WordPress hosting with more control * business websites * Laravel apps * Node.js apps * Python apps * Docker workloads * APIs * customer portals * internal dashboards * databases * staging environments * development servers * automation tools The key difference is control. Instead of being limited to a shared hosting account, you get a cloud VM that your team can configure around the workload. That gives you more room to improve: * speed * reliability * deployment workflow * security rules * backups * operating system control * application stack * database setup * scaling path Raff VM fits small businesses that want a VPS-style cloud server without unnecessary cloud complexity. ## Suggested first VPS setup for a small business website A practical starter setup can look like this: ```text Domain ↓ DNS ↓ VPS public IP ↓ Firewall ↓ Nginx or Apache ↓ Website or app ↓ Database ↓ Backups and monitoring ``` For a simple website, everything may run on one VPS. For a more serious business application, you may later separate: * web server * database * backups * object storage * staging environment * production environment Start simple. Make sure the first setup is secure, backed up, and easy to maintain. Then improve as the business grows. ## Is VPS always faster than shared hosting? Not automatically. A poorly configured VPS can be slower than good shared hosting. Performance depends on: * server resources * CPU quality * RAM * storage type * web server configuration * caching * database tuning * application quality * image optimization * frontend performance * traffic patterns A VPS gives you more control over performance. But you still need to configure it well. For small businesses, the best result usually comes from both: * better infrastructure * better website optimization ## Is VPS more expensive than shared hosting? Usually yes at the starting price level. Shared hosting is often cheaper because many users share the same server environment. A VPS costs more because you get a dedicated virtual environment and more control. But price should be compared against business value. If shared hosting causes slow pages, downtime, lost leads, failed checkout, poor SEO performance, or blocked development, the cheaper plan may not be cheaper in practice. A VPS is worth considering when hosting quality affects revenue, operations, or customer experience. ## Conclusion Shared hosting is a good starting point for many small businesses. It is simple, affordable, and enough for basic websites. But shared hosting is not designed for every stage of business growth. A small business should move from shared hosting to a VPS when the website or application needs more performance, control, reliability, security, custom software, better backups, or room to grow. The decision should not be emotional. Use the signs: * slow performance * traffic spikes * resource limits * custom software needs * revenue dependency * security requirements * backup concerns * staging needs * application workloads If none of those apply, shared hosting may still be enough. If several of them apply, it is time to move. A VPS gives your business a stronger foundation: more control, more flexibility, and a better path from simple website hosting to real cloud infrastructure. For small businesses ready to make that move, Raff VM provides a simple cloud server foundation for websites, apps, Docker workloads, databases, internal tools, and growing business systems. --- ### Kubernetes Cost Optimization: When the Cluster Bill Starts Hurting URL: https://rafftechnologies.com/learn/guides/kubernetes-cost-optimization-startups Description: Learn Kubernetes cost optimization for startups by fixing waste, sizing workloads, and knowing when cluster complexity costs more than it saves. Kubernetes cost optimization is the discipline of reducing cluster spend without making the system slower, riskier, or harder to operate. For startups and small teams, the painful Kubernetes bill usually does not come from one dramatic mistake. It comes from small operational habits that become expensive together: oversized requests, idle nodes, duplicated environments, always-on preview workloads, databases placed in the wrong layer, logs retained without discipline, and clusters adopted before the workload truly needs Kubernetes. For Raff Technologies users, the right question is not only "How do we make Kubernetes cheaper?" The better question is "Should this workload be on Kubernetes yet, and if yes, what should actually run inside the cluster?" This guide updates the Kubernetes cost conversation around the Raff infrastructure path: start simple on [Raff VM](/products/raff-vm), move production data to [Raff Managed Databases](/products/managed-databases) when database operations matter, use [Raff Object Storage](/products/object-storage) for uploads and backup archives, and use [Raff Kubernetes](/products/kubernetes) when orchestration is justified by real deployment, scaling, and service-management needs. Before optimizing Kubernetes, read [Kubernetes vs Docker Compose for Small Teams](/learn/guides/kubernetes-vs-docker-compose-small-teams). Many cluster cost problems start before the cluster exists. ## Kubernetes cost optimization starts before the first cluster The cheapest Kubernetes cluster is not always the one with the best autoscaler. Sometimes it is the cluster you do not create yet. Kubernetes is useful when your team needs cluster-level scheduling, service discovery, rollout controls, self-healing, and consistent workload management across nodes. It is not automatically the right next step after one VM. For a small SaaS team, there are usually four stages before Kubernetes becomes the natural choice: 1. One VM running the app. 2. App VM plus managed database. 3. App VM plus managed database plus object storage. 4. Multi-VM architecture with workers, load balancing, and separated roles. Only after those stages create real coordination problems does Kubernetes start to earn its operational cost. That does not make Kubernetes bad. It makes Kubernetes specific. A cluster should solve a problem that is bigger than a VM-level deployment workflow. If the problem is poor backups, unclear environments, weak CI/CD, oversized infrastructure, or unmeasured workloads, Kubernetes will not automatically fix it. It may make the problem more expensive. ## The cluster bill is usually a symptom When a founder says "our Kubernetes bill is getting painful," the invoice is usually not the root cause. ![Diagram showing Kubernetes cost factors including nodes, storage, environments, monitoring, and operations](https://raff-images.s3.raffusercloud.com/kubernetes_cost_breakdown_small_teams_webp_736101d03c.png) The real causes are usually upstream: - Workloads sized by fear instead of measurements - CPU and memory requests copied from staging into production - Environments running full-time without usage - Node pools designed for imagined future workloads - Autoscaling added before right-sizing - Databases or stateful systems placed inside the cluster too early - Logs, metrics, and traces retained without policy - Preview environments kept alive longer than needed - Teams using Kubernetes when Docker Compose or multi-VM architecture would still be enough The invoice only makes those decisions visible. Kubernetes cost optimization should start with workload honesty. What does the app actually need? Which workloads are idle? Which environments are still useful? Which services belong inside the cluster? Which should live in managed databases, object storage, or separate VMs? That is why this article should not be read as a generic "Kubernetes is expensive" warning. Kubernetes can be the right platform. But it needs operational discipline to stay economical. ## The quick decision framework Use this table before adding another node, autoscaler, environment, or optimization tool. | Situation | Better first move | Why | |---|---|---| | Product is still validating demand | Stay on VM or Docker Compose | Cluster overhead may exceed product value | | One app needs simple hosting | Raff VM | Simpler cost model and operations | | Database is creating operational risk | Managed database | Data protection should be solved before cluster tuning | | Uploads are filling app storage | Object storage | File growth should not drive compute spend | | Workers slow down web traffic | Worker VM or separate workload | Split the noisy role first | | Multiple app replicas are needed | Load balancer or Kubernetes | Choose based on coordination complexity | | Requests are inflated | Right-size requests | Scheduler decisions depend on request values | | Autoscaling increases cost too fast | Fix workload signals first | Autoscaling can scale waste | | Many environments are always on | Reduce environment sprawl | Idle environments quietly raise baseline cost | | Cluster has several teams/namespaces | Add quotas and limits | Shared clusters need cost boundaries | | Team lacks Kubernetes operators | Delay Kubernetes | Complexity becomes a hidden cost | | Cluster is justified | Optimize node pools, requests, autoscaling, and retention | Now Kubernetes tuning is worth the effort | The best cost optimization is not always a Kubernetes setting. Sometimes it is choosing the simpler architecture until the workload proves it needs a cluster. ## Requests and limits decide how expensive scheduling becomes Resource requests and limits are the first place startup Kubernetes cost usually goes wrong. Kubernetes uses requests to decide where Pods should be scheduled. Limits define the maximum amount of a resource a container can use. The Kubernetes documentation explains that if a node has available capacity, a container can use more than its request, while CPU and memory limits are enforced differently by the system: [Kubernetes resource management for Pods and containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). The cost problem is simple: if requests are inflated, the scheduler believes the cluster is fuller than it really is. That leads to: - Lower node utilization - More nodes than necessary - Poor bin packing - Autoscaling decisions based on bad signals - Expensive "safety" that may not reflect real usage A startup might set every app container to request more CPU and memory than it uses because nobody wants a production incident. That feels safe, but it can make the cluster pay for capacity that workloads rarely touch. The better process is: 1. Measure actual CPU and memory usage. 2. Set initial requests from observed behavior. 3. Keep limits deliberate, not copied blindly. 4. Review request-to-usage ratios regularly. 5. Separate workload classes instead of making every service look equally important. A request is not just a technical value. It is a cost signal. ## Autoscaling helps only after workload signals are honest Autoscaling is useful, but it is not magic. The Horizontal Pod Autoscaler adjusts the desired number of replicas for a target workload based on observed metrics such as CPU, memory, or custom metrics: [Kubernetes Horizontal Pod Autoscaling](https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/). That is powerful when the metrics reflect real demand. It is expensive when the metrics are distorted by bad requests, noisy jobs, missing limits, or application behavior that should be fixed first. Autoscaling can create cost problems when: - Minimum replica counts are too high - CPU targets are set without traffic context - Background jobs trigger scaling meant for web traffic - Services scale out because requests are wrong - Node autoscaling responds to inefficient Pod placement - Preview or staging environments autoscale like production - Custom metrics are missing or poorly chosen A useful rule: > Right-size before autoscaling. Then autoscale only what should actually scale. For example, a web API may need horizontal scaling based on request load. A reporting worker may need a separate queue-based scaling policy. A scheduled batch job may not need to run all day. Treating all workloads the same makes autoscaling less precise and more expensive. Autoscaling should follow real demand, not compensate for weak resource discipline. ## Environment sprawl raises the baseline cost Many startup Kubernetes bills grow because every environment becomes permanent. Production is necessary. Staging is usually necessary. But then preview, QA, internal demo, migration test, performance test, and old experiment environments start staying alive. Each environment may feel small, but together they create a baseline cost that exists before users send any traffic. Environment sprawl usually looks like this: ```text Production Staging Preview 1 Preview 2 QA Demo Old test cluster Migration sandbox ``` The cost is not only nodes. It is also storage, logs, metrics, load balancers, IPs, backups, and team attention. A better environment policy asks: - Which environments must run 24/7? - Which can sleep when not used? - Which should be destroyed after a pull request closes? - Which need production-sized resources? - Which need real databases? - Which can use smaller data sets? - Which logs and metrics need long retention? - Who owns cleanup? For small teams, environment policy is often cheaper than advanced node optimization. Do not buy more nodes before deleting workloads that no longer deserve to run. ## Node strategy should match workload classes Node strategy is another place Kubernetes spend can drift. Some teams make every node pool identical. That is simple, but it may force all workloads into the same cost profile. Other teams create too many node pools, which can reduce placement efficiency and make operations harder. The better path is to group by real workload classes. A startup cluster may only need a few categories: | Workload class | Example | Cost goal | |---|---|---| | General app workloads | APIs, web apps, small services | Balanced capacity | | Memory-heavy workloads | Search, analytics, in-memory services | Avoid starving RAM-heavy Pods | | Background/batch workloads | Jobs, reports, imports, exports | Flexible capacity and isolation | | Critical production workloads | Customer-facing services | Predictable placement and reliability | | Non-production workloads | Staging, previews, QA | Lower baseline cost | Anything more detailed should have a strong reason. The point is not to create a complex node taxonomy. The point is to stop mixing workloads with very different cost and reliability profiles when that mixing creates waste. For Raff users, this connects directly to [single VM vs multi-VM SaaS architecture](/learn/guides/single-vm-vs-multi-vm-saas-architecture). Even before Kubernetes, role separation helps teams understand workload classes. Kubernetes should formalize that discipline, not replace it. ## Quotas and limits turn cluster cost into a boundary A shared cluster without quotas is easy to overspend. Kubernetes ResourceQuota objects can limit aggregate resource consumption per namespace, and Kubernetes documentation describes them as a way to address the concern that one team or workload could use more than its fair share of resources in a fixed-size cluster: [Kubernetes Resource Quotas](https://kubernetes.io/docs/concepts/policy/resource-quotas/). LimitRanges can also define default, minimum, and maximum resource constraints inside a namespace: [Kubernetes Limit Ranges](https://kubernetes.io/docs/concepts/policy/limit-range/). For startups, quotas are not only platform controls. They are financial boundaries. Use quotas when: - Multiple teams share a cluster - Preview environments are created often - Staging can accidentally grow too large - One namespace contains experimental workloads - CI/CD jobs run inside the cluster - A team wants to limit blast radius from mistakes - You need clearer cost ownership A simple model: ```text production namespace = protected resources staging namespace = smaller quota preview namespace = strict quota and cleanup policy jobs namespace = controlled batch capacity ``` That prevents "temporary" workloads from becoming permanent budget leaks. ## Databases can make Kubernetes cost worse when placed too early inside the cluster Running databases inside Kubernetes can work, but small teams should be careful. Databases have different requirements from stateless app containers. They need durable storage, backup discipline, restore testing, upgrade planning, monitoring, and careful failure handling. If the team is still learning Kubernetes, putting the production database inside the cluster can increase both cost and risk. A cleaner early pattern is: ```text Kubernetes or app VMs ↓ private access Raff Managed Database ``` This keeps the app workloads in the orchestration layer while database operations live in a database-focused service. Use [Raff Managed Databases](/products/managed-databases) when the team wants PostgreSQL, MySQL, or Redis without operating the database host. Use a self-hosted database VM when full control is needed and the team can handle backups, patches, monitoring, and restore. For the full database decision, read [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) and [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps). Kubernetes cost optimization is easier when the cluster is not also carrying database complexity before the team is ready. ## Object storage prevents file growth from becoming cluster cost User uploads, exports, reports, and media should not force compute scaling. If uploaded files live inside containers, node disks, or application volumes, storage growth can affect scheduling, backups, restore, and cluster cost. For most SaaS apps, the cleaner pattern is to store file metadata in the database and file bodies in object storage. A production pattern looks like this: ```text App workload ↓ Database stores metadata ↓ Object storage stores uploaded files ``` Raff Object Storage starts at $7.00/month for the first 100 GB and is S3-compatible at `s3.raffusercloud.com`. This keeps file growth out of the cluster's compute layer. The app can run on VMs or Kubernetes while durable files live in object storage. Use object storage for: - User uploads - Profile images - Product media - Generated reports - Exports - Attachments - Backup archives - Files shared across app replicas For the full storage decision, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). :::cta Explore Raff Object Storage Use Raff Object Storage for uploads, exports, reports, and backup archives so file growth does not drive cluster compute cost. ::: ## Observability cost needs its own policy Logs, metrics, and traces can quietly become a large part of Kubernetes cost. A cluster creates more observable components: nodes, Pods, containers, services, ingress, jobs, namespaces, events, and application metrics. That visibility is useful, but collecting everything forever is not cost discipline. Small teams should define: - Which logs are required for production debugging? - Which logs can be sampled or shortened? - How long should logs be retained? - Which metrics need alerts? - Which metrics are only dashboard noise? - Which traces are useful enough to keep? - Do staging and previews need the same retention as production? - Who reviews observability spend? Observability is not optional. But it should be intentional. A useful pattern is: | Environment | Logging/metrics policy | |---|---| | Production | Full useful visibility with defined retention | | Staging | Shorter retention and fewer alerts | | Preview | Minimal retention and automatic cleanup | | Experiments | Temporary visibility only | Cost optimization fails when every environment is treated like production forever. ## The real decision is optimize the cluster or simplify the architecture This is the decision many teams skip. If the workload truly needs Kubernetes, optimize the cluster. ![Decision diagram comparing Kubernetes optimization with simplifying architecture on Raff](https://raff-images.s3.raffusercloud.com/optimize_kubernetes_vs_simplify_architecture_webp_1568daa4ce.png) Do that when you need: - Multiple schedulable nodes - Pod-level scaling - Service-level separation - Rolling deployments - Self-healing workloads - Cluster-level release controls - Standardized environment management - Better workload placement - Multi-service coordination In that case, focus on: - Requests and limits - Node strategy - Autoscaling behavior - Environment cleanup - Quotas and limits - Observability retention - Storage boundaries - Database placement - Workload classes But if the system mainly needs one clean production host, better backups, clearer deployments, a managed database, object storage for uploads, or a worker VM, cluster optimization may be solving the wrong problem. Simplify when: - The team spends more time tuning Kubernetes than shipping product - Most workloads run at low traffic - One or two VMs would handle the app safely - The database has not been separated yet - Uploads are still local - CI/CD is weak - Monitoring is unclear - Kubernetes was adopted because it felt more mature The cheapest Kubernetes decision may be admitting that Kubernetes is early. ## Raff-specific cost path On Raff, the goal is not to force every growing team into Kubernetes. The goal is to give teams a staged path. ![Raff cost-aware path from VM to Managed Database, Object Storage, worker VMs, and Kubernetes](https://raff-images.s3.raffusercloud.com/raff_cost_aware_kubernetes_path_webp_ef62522faf.png) A practical cost-aware Raff path looks like this: ### Stage 1: Raff VM Use a [Raff VM](/products/raff-vm) for the app when the product is early or the workload is simple. ```text Raff VM ↓ App + Docker Compose or app runtime ``` This is usually the clearest path for prototypes, MVPs, internal tools, and small production apps. ### Stage 2: Raff VM + Managed Database Move the database out when production data matters. ```text Raff VM for app ↓ private access Raff Managed Database ``` This keeps the app simple while improving database reliability and recovery responsibility. ### Stage 3: Raff VM + Managed Database + Object Storage Move uploads, reports, and exports to object storage. ```text App on Raff VM ↓ Managed Database for metadata ↓ Object Storage for files ``` This prevents file growth from forcing compute growth. ### Stage 4: Worker VM or multiple app VMs Split workers or add load balancing when the workload proves the need. ```text App VM ↓ Worker VM ↓ Managed Database + Object Storage ``` This solves many scaling problems before Kubernetes. ### Stage 5: Raff Kubernetes Move to [Raff Kubernetes](/products/kubernetes) when deployment coordination, service discovery, workload scheduling, and environment consistency are now bigger problems than VM-level simplicity. ```text Raff Kubernetes ↓ App workloads + workers + services ↓ Managed Database + Object Storage ``` This staged approach keeps infrastructure cost tied to actual product maturity. :::cta Explore Raff Kubernetes Use Raff Kubernetes when your workload has outgrown VM-level coordination and needs a cluster operating model. ::: ## The Kubernetes cost checklist Use this checklist before calling a cluster "optimized." - [ ] The team has confirmed Kubernetes is still the right operating model. - [ ] CPU and memory requests are based on observed usage. - [ ] Limits are deliberate and not copied blindly. - [ ] Minimum replica counts are justified. - [ ] HPA settings match real workload behavior. - [ ] Node pools match real workload classes. - [ ] Idle environments are deleted or reduced. - [ ] Preview environments have automatic cleanup. - [ ] Production and staging do not use the same resource policy by default. - [ ] ResourceQuotas are applied where shared usage needs boundaries. - [ ] LimitRanges are used where defaults prevent waste. - [ ] Databases are managed or intentionally placed. - [ ] Stateful workloads have backup and restore plans. - [ ] Durable files live in object storage. - [ ] Logs and metrics have retention policies. - [ ] Backup, snapshot, and object storage costs are included. - [ ] Load balancer and network costs are understood. - [ ] The team reviews cluster spend regularly. - [ ] The cost owner is clear. - [ ] The rollback path to a simpler architecture is understood. If most of this checklist is not true, the cluster may not need advanced optimization yet. It may need discipline. ## Common mistakes to avoid ### Optimizing Kubernetes before validating Kubernetes is needed A cluster can be technically impressive and economically wrong. Before tuning the cluster, confirm that the workload still needs Kubernetes. ### Setting requests by fear Inflated requests make the scheduler reserve more capacity than the workload needs. Measure first, then set requests. ### Treating autoscaling as cost optimization Autoscaling can reduce waste, but it can also scale inefficient workloads faster. Fix workload signals before relying on HPA or node scaling. ### Keeping every environment always on Environment sprawl is one of the simplest ways to raise the baseline bill. Delete, sleep, shrink, or time-limit environments that do not need production-grade capacity. ### Running production databases inside Kubernetes too early Databases inside Kubernetes require storage, backups, restore testing, and operational discipline. Use a managed database or dedicated database VM unless the team is ready to own stateful Kubernetes operations. ### Letting uploads drive compute cost Files should not force larger nodes or more app replicas. Use object storage for durable uploads, exports, media, and reports. ### Ignoring observability retention Logs and metrics are necessary, but retention should match each environment. Preview environments do not need the same retention as production. ## Kubernetes cost optimization is really workload discipline Kubernetes cost optimization is not one trick, one dashboard, or one autoscaler setting. It is the discipline of making the cluster match reality: real traffic, real resource usage, real environments, real workload classes, and real operational needs. Requests and limits should reflect observed behavior. Autoscaling should follow honest signals. Environments should earn their cost. Databases and files should live in the right layers. Observability should be useful without becoming uncontrolled retention. For Raff teams, the smartest cost path is staged. Use [Raff VM](/products/raff-vm) when a VM is enough. Use [Raff Managed Databases](/products/managed-databases) when database operations matter. Use [Raff Object Storage](/products/object-storage) when files should not live in compute. Use [Raff Kubernetes](/products/kubernetes) when your workload has truly outgrown VM-level coordination. Then review [Raff pricing](/pricing) and compare the full operating model, not only the monthly node bill. :::cta Explore Raff Kubernetes Deploy Raff Kubernetes when your team is ready for cluster-level workload management and wants cost discipline from the start. ::: --- ### Secrets Management for Cloud Apps: Env Vars, Vaults, Managed Stores URL: https://rafftechnologies.com/learn/guides/secrets-management-cloud-apps-env-vars-vaults-managed-stores Description: Compare environment variables, vaults, and managed secret stores for cloud apps. Learn when each fits, how to rotate secrets, reduce exposure, and avoid secret sprawl. Secrets management for cloud apps is the practice of storing, delivering, rotating, auditing, and revoking sensitive values such as database passwords, API keys, signing keys, service tokens, SSH private keys, and TLS private keys. The practical decision is not: ```text Where can I put a secret? ``` The better question is: ```text What is the lightest secrets workflow that still lets us rotate, restrict, audit, and recover safely? ``` Use this rule: | Situation | Best starting point | |---|---| | One small app, few secrets, trusted operators | Disciplined environment variables | | Several services, multiple environments, central access control needed | Managed secret store | | Many services, dynamic secrets, strict audit/revocation, multi-cloud policy | Vault-style system | | Kubernetes app with cluster-native delivery | Kubernetes Secrets plus encryption/RBAC, or external secret store | | Docker Swarm service | Docker secrets | | CI/CD deployment secrets | CI/CD secret store or external secrets manager | | Production database credentials | Avoid shared long-lived passwords where possible | The most important point: ```text Environment variables are a delivery mechanism. They are not a complete secrets management system. ``` A mature secrets workflow handles the whole lifecycle: ```text Create → Store → Deliver → Use → Rotate → Revoke → Audit → Recover ``` ## What counts as a secret? A secret is any value that grants access, identity, trust, or privileged capability inside your system. Common examples: - database usernames and passwords; - API keys; - OAuth client secrets; - JWT signing secrets; - session signing keys; - SSH private keys; - TLS private keys; - webhook signing secrets; - cloud access keys; - CI/CD deployment tokens; - container registry credentials; - service-to-service tokens; - encryption keys; - backup access credentials. A secret is different from normal configuration. This is configuration: ```text APP_ENV=production PORT=3000 PUBLIC_BASE_URL=https://example.com ``` This is a secret: ```text DATABASE_PASSWORD=... STRIPE_SECRET_KEY=... JWT_SIGNING_SECRET=... ``` Normal configuration can usually appear in logs, dashboards, and documentation. Secrets should not. ## Why secrets management breaks down Secrets usually start simple. A small app has: ```text DATABASE_URL API_KEY JWT_SECRET ``` Then the system grows: - staging is added; - CI/CD is added; - a second service is added; - contractors get access; - backups are introduced; - logs are centralized; - Kubernetes or Docker enters the stack; - a team member leaves; - an API key leaks; - the database password needs rotation. At that point, the question becomes operational. Common failure patterns: - `.env` files copied between machines; - production secrets reused in staging; - secrets committed to Git; - credentials pasted into Slack, tickets, docs, or screenshots; - CI logs printing secret values; - Docker images containing old credentials; - one database password shared by every service; - no inventory of what secrets exist; - no known owner for each secret; - no tested rotation process; - no audit trail of secret access; - backups containing plaintext secret exports. Secret sprawl is not only a storage problem. It is an ownership, access, rotation, and recovery problem. ## The three main models Most cloud teams choose between three patterns: ```text 1. Environment variables 2. Vault-style systems 3. Managed secret stores ``` These are not mutually exclusive. A common production architecture is: ```text Managed store or vault ↓ Deployment system ↓ Environment variable or mounted file ↓ Application runtime ``` In other words, the app may still read a secret from an environment variable, even if the real source of truth is a vault or managed store. That distinction matters. ## Model 1 — Environment variables Environment variables are the most common starting point for cloud apps. They work across almost every language and framework: - Node.js; - Python; - PHP; - Laravel; - Django; - Rails; - Go; - Java; - .NET; - Docker; - systemd; - CI/CD tools; - PaaS platforms. The Twelve-Factor App popularized storing deploy-specific configuration in the environment, including credentials to external services. The same model also warns against storing deploy-specific config as constants in source code. ## What env vars do well Environment variables are useful because they are: - simple; - language-agnostic; - easy to inject at deploy time; - easy to separate by environment; - supported by most hosting models; - familiar to developers; - good for early-stage apps. For a small app running on one Linux VM, this can be enough if access is controlled. Example: ```bash DATABASE_URL=postgres://app_user:strong-password@10.0.0.5:5432/app REDIS_URL=redis://10.0.0.6:6379 JWT_SECRET=long-random-value ``` Environment variables are especially useful when: - the app has few secrets; - only a small trusted team has server access; - staging and production are cleanly separated; - rotation is manual but still manageable; - there are no strict audit requirements; - the app is not part of a larger regulated platform. ## Where env vars become risky Environment variables are not enough when lifecycle control matters. They do not automatically tell you: - who created the secret; - who viewed the secret; - who changed it; - when it was last rotated; - whether it is reused elsewhere; - which service should be allowed to access it; - whether it should expire; - whether it was included in backups; - whether it appeared in logs; - whether the old value was revoked. Common env var problems: - `.env` files checked into Git by mistake; - secrets copied into local development; - production values reused in staging; - no central secret inventory; - shell history exposure; - debug endpoint exposure; - process inspection risk; - Docker image build leakage; - no safe rotation workflow. The right way to think about env vars: ```text Good delivery mechanism. Weak lifecycle system. ``` ## Best practices for env vars Use environment variables safely by following these rules: 1. Never commit `.env` files. 2. Add `.env`, `.env.*`, and local secret files to `.gitignore`. 3. Keep `.env.example` with names only, not values. 4. Use separate values for dev, staging, and production. 5. Limit SSH and dashboard access to production hosts. 6. Avoid printing env vars in logs. 7. Avoid putting secrets in process arguments. 8. Document who owns each production secret. 9. Keep a rotation runbook. 10. Move to a managed store or vault when rotation/access control becomes painful. A good `.env.example`: ```bash DATABASE_URL= REDIS_URL= JWT_SECRET= PAYMENT_API_KEY= ``` A bad `.env.example`: ```bash DATABASE_URL=postgres://prod_user:real-password@prod-db:5432/app ``` ## Model 2 — Vault-style systems A vault is a dedicated secrets control plane. The best-known example is HashiCorp Vault, but the concept matters more than the specific product. A vault can provide: - centralized secret storage; - authentication; - authorization policies; - audit logging; - dynamic secrets; - lease-based access; - secret rotation workflows; - encryption services; - revocation; - service identity integration. The big change is this: ```text Instead of copying long-lived secrets into apps, services authenticate to the vault and receive allowed secrets under policy. ``` ## What vaults do well Vault-style systems are strongest when secrets have become a platform problem. They help with: - service-specific access policies; - reducing shared credentials; - dynamic database credentials; - short-lived tokens; - audit trails; - revocation; - multi-cloud consistency; - security team review; - policy-as-code style management; - platform-wide secret standards. Example: ```text App service authenticates to Vault ↓ Vault checks identity and policy ↓ Vault returns short-lived database credentials ↓ App connects to database ↓ Credentials expire or are revoked ``` This reduces blast radius. If one service is compromised, it should not automatically expose every credential in the environment. ## The real cost of vaults Vaults are powerful, but they add operational responsibility. You must manage: - vault deployment; - high availability; - storage backend; - unseal/recovery process; - access policies; - authentication methods; - audit logs; - upgrades; - monitoring; - backups; - break-glass access; - incident response. For a small team, a vault can become a critical internal service before the team is ready to operate one. A useful test: ```text Would running Vault reduce more complexity than it adds? ``` If the answer is no, start lighter. ## When Vault is the right call Choose a vault-style system when: - you have many services; - each service needs different access; - shared credentials are becoming dangerous; - dynamic secrets would reduce risk; - audit trails are required; - secrets are used across multiple clouds; - you need short-lived credentials; - security controls must be centralized; - the team can operate a critical internal platform. Do not deploy Vault only because it sounds mature. Deploy it when you are ready to own it. ## Model 3 — Managed secret stores Managed secret stores sit between env vars and self-operated vaults. Examples include cloud-native services such as: - AWS Secrets Manager; - AWS Systems Manager Parameter Store; - Google Secret Manager; - Azure Key Vault; - provider-specific secret stores; - platform secret stores in CI/CD systems. A managed store gives centralized secret storage and access control without making your team operate the secret service itself. ## What managed stores do well Managed stores are often the best fit for small cloud-native teams because they provide: - centralized inventory; - IAM-based access control; - encryption; - audit logs; - API-based retrieval; - rotation support in some cases; - cloud-native integration; - less operational overhead than Vault. They are useful when: - you already live mostly inside one cloud/platform; - you want better control than raw env vars; - you do not want to operate Vault; - IAM access control is enough; - rotation and audit are becoming important; - developers need a standard place to store secrets. A typical pattern: ```text Managed secret store ↓ CI/CD retrieves secret at deploy time ↓ App receives secret as env var or file ``` Or: ```text App authenticates using instance/workload identity ↓ App retrieves secret at runtime ``` ## Limits of managed stores Managed stores are not perfect. Trade-offs: - provider-specific APIs; - cloud identity lock-in; - cross-cloud consistency challenges; - cost per secret/API call in some services; - rotation may require custom integration; - runtime dependency on provider availability; - less flexible dynamic secret model than a full vault. For many small teams, those trade-offs are acceptable. The goal is not theoretical portability. The goal is safer production operations. ## Containers and secrets Containerized apps add extra leak paths. Avoid putting secrets into: - Dockerfiles; - build arguments that end up in image history; - committed Compose files; - public container images; - container labels; - debug layers; - image names or tags; - logs. Bad pattern: ```dockerfile ENV DATABASE_PASSWORD=real-password ``` Better pattern: ```text Secret comes from deployment environment, secret store, or mounted secret file at runtime. ``` Docker Swarm secrets can centrally manage sensitive data and only grant access to services that need it, but Docker notes that Docker secrets are for Swarm services, not standalone containers. For plain Docker Compose on a single VM, be careful: a `secrets:` block may still map to local files depending on the Compose mode. Do not assume it gives the same security model as Swarm or Kubernetes. ## Kubernetes secrets Kubernetes Secrets are designed for small sensitive values such as passwords, tokens, and keys. They let you keep secrets out of application code and Pod specs. But Kubernetes Secrets need configuration discipline. Kubernetes documentation warns that Secrets are stored unencrypted in etcd by default and that API or etcd access can expose them. The docs recommend enabling encryption at rest, configuring least-privilege RBAC, restricting Secret access to specific containers, and considering external secret store providers. For Kubernetes, use these rules: - enable encryption at rest for Secrets; - restrict Secret access with RBAC; - avoid giving broad namespace access; - do not let every workload read every Secret; - prefer mounted files over env vars when rotation behavior matters; - avoid storing secrets in Helm values files committed to Git; - review who can create Pods in a namespace; - consider external secret operators or CSI drivers when secrets need to come from a managed store. A Kubernetes Secret is useful. It is not automatically secure by default. ## CI/CD secrets CI/CD is one of the most common places secrets leak. Pipelines often need: - deploy keys; - registry tokens; - cloud credentials; - SSH keys; - database migration credentials; - webhook tokens; - package repository tokens. Rules for CI/CD: 1. Store secrets in the CI/CD secret store or external manager. 2. Never print secrets in logs. 3. Mask values where possible. 4. Use short-lived credentials when possible. 5. Avoid broad cloud admin keys. 6. Separate dev/staging/prod deployment credentials. 7. Rotate tokens when team members leave. 8. Restrict who can modify pipelines. 9. Avoid secrets in pull requests from untrusted forks. 10. Keep deployment credentials separate from human credentials. A pipeline with production secrets is production infrastructure. Treat it that way. ## Comparison: env vars vs vaults vs managed stores | Criteria | Environment variables | Vault-style system | Managed secret store | |---|---|---|---| | Setup complexity | Low | High | Medium | | Operational overhead | Low | High | Low to medium | | Central inventory | Weak | Strong | Strong | | Access policy | Weak to medium | Strong | Medium to strong | | Auditability | Limited | Strong | Strong | | Rotation support | Manual/custom | Strong | Medium to strong | | Dynamic secrets | No | Yes | Limited/provider-specific | | Multi-cloud consistency | Medium | Strong | Weak to medium | | Best fit | Small/simple apps | Mature platforms | Cloud-native small teams | | Main risk | Secret sprawl | Platform overhead | Provider lock-in | | Skill requirement | Low | High | Medium | | Incident response | Manual | Strong | Medium to strong | No option is universally best. The right answer depends on maturity. ## Practical decision framework ## Choose environment variables when: - you run one or two applications; - the number of secrets is small; - production access is limited; - deployment is simple; - rotation is still manageable; - audit requirements are low; - the team is small and trusted; - you can keep secrets out of Git and logs. Environment variables are a good first step when paired with discipline. They become risky when used as the only long-term secrets system. ## Choose a managed secret store when: - you need central storage; - you want access control without operating Vault; - secrets are growing across services; - rotation is becoming important; - you already depend on one cloud or platform; - IAM fits your access model; - audit logs matter; - your team wants a practical middle ground. For many small teams, this is the best next step after env vars. ## Choose a vault when: - secrets management is a platform problem; - many services need different policy boundaries; - dynamic secrets reduce meaningful risk; - short-lived credentials are important; - audit and revocation are required; - you operate across multiple clouds or environments; - the team can manage a critical internal control plane. Vault is the strongest option, but it is not the lightest. ## Recommended maturity path For most small teams: ```text Stage 1: Disciplined env vars Stage 2: Separate dev/staging/prod values Access-controlled deployment process Secret inventory Stage 3: Managed secret store Rotation runbooks Audit logs Stage 4: Vault-style platform Dynamic secrets Strong policies Centralized audit and revocation ``` This path avoids over-engineering on day one while still moving toward a stronger security model. ## Secret rotation strategy A rotation strategy answers: - what rotates; - how often; - who owns it; - what depends on it; - how to deploy the new value; - how to revoke the old value; - how to roll back; - how to verify success. For every production secret, document: ```text Name: Owner: Used by: Environment: Source of truth: Rotation frequency: Rotation steps: Rollback steps: Last rotated: Emergency contact: ``` ## Safe rotation pattern A safe rotation usually looks like this: ```text 1. Create new secret value. 2. Add new value without removing old value. 3. Deploy apps that can use new value. 4. Verify traffic works. 5. Revoke old value. 6. Monitor errors. 7. Update inventory. ``` Do not rotate by deleting the old value first. That creates avoidable downtime. ## Least privilege for secrets Each service should access only the secrets it needs. Bad pattern: ```text All apps use one shared production database password. ``` Better pattern: ```text api-service gets api_db_user. worker-service gets worker_db_user. analytics-service gets analytics_readonly_user. ``` Benefits: - smaller blast radius; - easier revocation; - clearer ownership; - better audit trails; - safer rotation; - fewer surprise dependencies. Least privilege applies to humans too. Not every developer needs read access to production secret values. ## Secret inventory A small secret inventory can be simple. Start with a table: | Secret | Environment | Owner | Used by | Source of truth | Rotation | |---|---|---|---|---|---| | DATABASE_URL | production | Platform | API | Managed store | 90 days | | JWT_SECRET | production | Backend | API | Managed store | On incident | | STRIPE_SECRET_KEY | production | Payments | API | Provider + store | On staff change/incidents | | S3_ACCESS_KEY | staging | Platform | Worker | Managed store | 90 days | This is not bureaucracy. It is how you avoid discovering during an incident that nobody knows what a credential does. ## Backup and recovery Secrets management must include recovery. Ask: - How do we restore the secret store? - Who has break-glass access? - Where are recovery keys stored? - Are backups encrypted? - Are backups access-controlled? - Are old secrets duplicated in backup exports? - Can we recover without exposing every secret to every admin? - How do we rotate after restore? - How do we revoke after compromise? Do not create casual plaintext exports of all secrets. Backups should protect the secret management system without multiplying exposure. ## Incident response when a secret leaks If a secret leaks: 1. Identify which secret leaked. 2. Determine where it was exposed. 3. Revoke or rotate it. 4. Deploy the new value. 5. Check logs for misuse. 6. Search repositories, images, tickets, and logs for copies. 7. Remove exposed copies where possible. 8. Review access scope. 9. Document the incident. 10. Improve prevention. Do not only delete the secret from Git and move on. If a secret was committed, assume it may have been copied. Rotate it. ## Common mistakes ## Mistake 1 — Treating `.env` as the secret source of truth A `.env` file may be a delivery mechanism, but it should not become the only uncontrolled production secret store. ## Mistake 2 — Reusing production secrets in staging Staging should never unlock production resources. Use separate credentials. ## Mistake 3 — Giving every developer production secret access Access should follow need, not curiosity. Use deployment systems and role-based access. ## Mistake 4 — No rotation plan If rotation feels impossible, the system is too tightly coupled. Design rotation before the emergency. ## Mistake 5 — Secrets in Docker images Never bake secrets into container images. Images move through registries, caches, CI systems, and developer machines. ## Mistake 6 — Assuming Kubernetes Secrets are encrypted by default Kubernetes warns that Secrets are stored unencrypted in etcd by default unless encryption at rest is enabled. Configure Kubernetes Secrets intentionally. ## Mistake 7 — Ignoring logs Secrets can leak through: - error logs; - request logs; - debug logs; - CI logs; - crash dumps; - APM traces. Mask and redact sensitive fields. ## Mistake 8 — No owner for each secret Every production secret needs an owner. Without ownership, rotation and incident response stall. ## Mistake 9 — Over-engineering too early A solo app does not always need a full vault. Start with disciplined controls, then mature. ## Mistake 10 — Under-engineering too long If you have many services, contractors, production incidents, audits, and manual rotations, raw env vars are no longer enough. ## How these choices apply on Raff Raff does not force one secrets architecture. That is useful because different teams need different maturity levels. ## Small app on one Raff VM For a single app on a Raff Linux VM: ```text App on VM ↓ systemd / Docker / app runtime ↓ environment variables ``` This can be acceptable if: - `.env` files are not committed; - SSH access is limited; - production and staging values are different; - file permissions are tight; - backups are controlled; - rotation is documented; - logs do not print secrets. ## Growing app with staging and production When you add staging, workers, CI/CD, background jobs, and private services, move toward centralization. Pattern: ```text Secret inventory ↓ Managed secret store or vault ↓ CI/CD or deployment agent ↓ Runtime env vars or mounted files ↓ Separate dev/staging/prod values ``` This reduces copy-paste and makes rotation easier. ## Multi-service app on private networking For apps split across VMs: ```text Web VM Worker VM Database VM Internal services Private network ``` Use separate credentials per service. Example: ```text web_db_user worker_db_user readonly_reporting_user backup_user ``` Do not give every service the same database admin password. Pair secrets management with private networking and firewall rules. A secret should not be the only line of defense. ## Kubernetes workloads For Kubernetes workloads, treat Secrets as one layer. Use: - encryption at rest; - RBAC least privilege; - namespace boundaries; - service accounts; - external secret stores when needed; - careful Helm/GitOps handling; - secret rotation workflows; - audit logging. Do not put production secrets into public Helm values files. Do not assume base64 encoding is encryption. ## Raff API keys and automation Raff API keys should be treated as production secrets. Use: - separate keys for different automation tasks; - project-scoped access where possible; - clear naming; - expiration dates; - rotation; - revocation when team members leave; - no keys in Git; - no keys in screenshots; - no keys in shared docs. Automation keys are secrets. Treat them like database passwords. ## Recommended checklist Before production, confirm: - secrets are not in code; - `.env` files are ignored by Git; - dev, staging, and production use different values; - each secret has an owner; - production access is limited; - CI/CD secrets are masked; - rotation is documented; - backups do not create uncontrolled plaintext secret exports; - logs redact sensitive values; - container images do not contain secrets; - Kubernetes Secrets are encrypted and access-controlled if used; - API keys have expiration and revocation process; - old secrets are removed after rotation; - incident response steps are known. ## What Raff recommends For most small cloud app teams: 1. Start with disciplined env vars only if the app is small. 2. Separate dev, staging, and production secrets early. 3. Keep secrets out of Git, images, logs, and tickets. 4. Create a simple secret inventory. 5. Use a managed secret store when centralization and rotation matter. 6. Use Vault when dynamic secrets and policy control justify the operational load. 7. Rotate secrets with a safe two-phase process. 8. Use private networking and firewalls so secrets are not your only boundary. 9. Treat Raff API keys as production secrets. 10. Keep backups and recovery materials secure. The goal is not to buy the most advanced tool. The goal is to reduce exposure while keeping the system operable. ## Conclusion Secrets management is not one tool. It is a lifecycle. Environment variables are a useful starting point, but they do not solve inventory, rotation, audit, revocation, or least privilege by themselves. Managed secret stores are often the right next step for small cloud teams because they centralize control without making the team operate a full secrets platform. Vault-style systems are strongest when secrets become a platform problem: dynamic credentials, short-lived access, strict audit, multiple services, and stronger policy boundaries. The best choice is the lightest model that still lets your team answer these questions: ```text Where does each secret live? Who can access it? Which services use it? How do we rotate it? How do we revoke it? How do we recover it? How do we prove what happened? ``` If you can answer those clearly, your secrets strategy is on the right path. :::cta Explore Security Build cloud apps on infrastructure designed for controlled access, private networking, backups, and production-ready security practices. ::: ## Sources - The Twelve-Factor App — Config - OWASP Secrets Management Cheat Sheet - Kubernetes Documentation — Secrets - Docker Documentation — Manage sensitive data with Docker secrets - Date last verified: 2026-07-08 --- ### Serverless Functions vs VMs: What Small Teams Should Choose URL: https://rafftechnologies.com/learn/guides/serverless-functions-vs-vms-small-teams Description: Learn when small teams should use serverless functions or VMs for apps, cron jobs, webhooks, storage events, and background work on Raff. Serverless functions vs VMs is not a question of old infrastructure versus new infrastructure. It is a question of operating model. A serverless function is best when a small piece of code should run because something happened: an HTTP request arrived, a cron schedule fired, a file landed in object storage, or a one-off task needs to run. A VM is best when your team needs a full server environment: a long-lived app process, custom packages, persistent services, system-level control, or predictable always-on capacity. For Raff Technologies users, the practical answer is usually not "functions or VMs forever." The better answer is: use [Raff Functions](/products/serverless-functions) for event-driven work and use [Raff VM](/products/raff-vm) when the workload needs a full box. Many production systems use both. At Raff, we see the same pattern often: teams start by putting every task on one VM because it is simple. That works until background jobs, cron tasks, webhooks, image processing, API callbacks, and cleanup scripts start competing with the main app. Serverless functions help when those jobs should scale or run independently. VMs remain the right home for the main application when it needs a stable runtime and full operating-system control. This guide explains when a small team should use serverless functions, when a VM is still the cleaner choice, and how to combine both without making the architecture harder than the product needs. ## Serverless functions and VMs solve different operations problems A VM gives you a complete server environment. You choose the operating system, install packages, run services, manage processes, configure networking, store files, run containers, and keep the environment alive. This is useful when the workload behaves like an application server, database host, worker machine, or self-managed runtime. A serverless function gives you a smaller deployment unit. You ship code and configuration. The platform handles the runtime, scaling behavior, trigger wiring, and execution environment. This is useful when the workload behaves like a task: handle this request, process this file, run this scheduled job, send this webhook, resize this image, or transform this payload. The difference is not only technical. It changes how the team thinks. | Question | Serverless function | VM | |---|---|---| | What runs? | A function or small service | A full server environment | | When does it run? | On trigger or demand | Continuously or manually controlled | | Who manages the OS? | Platform | Your team | | How does it scale? | Per function or trigger | By VM sizing or additional VMs | | What is the cost shape? | Usage-based | Capacity-based | | What is best hosted there? | HTTP handlers, cron, webhooks, event tasks | Apps, databases, containers, persistent workers | | What can go wrong? | Timeout, cold start, trigger limits, stateless design issues | Patch burden, idle cost, noisy services, manual scaling | | Best buyer question | "Can this task run only when needed?" | "Does this workload need a whole environment?" | Neither model is universally better. The right choice depends on what the workload is, how often it runs, how much control it needs, and what the team can operate safely. ## The quick decision framework Use this first. ![Decision matrix comparing Raff Functions and Raff VM for small team workloads](https://raff-images.s3.raffusercloud.com/serverless_functions_vs_vm_decision_matrix_webp_d031cd6670.png) A useful rule: > Use a function when the unit of work is clear. Use a VM when the environment is the product. If the application needs a stable server, a VM is usually cleaner. If the work is event-driven and isolated, a function may reduce operations work. ## Use serverless functions when work is event-driven Serverless functions are strongest when work starts because something happened. Good function workloads include: - Webhook receivers - Image resizing - PDF generation - File conversion - Scheduled cleanup - Email sending - Object storage event processing - API callbacks - Lightweight HTTP APIs - Data enrichment - One-off future tasks - Batch transforms - ETL steps - Notification fanout - Form submission handling - Report generation The pattern is simple: ![Architecture diagram showing HTTP cron object storage and one-off triggers running through Raff Functions](https://raff-images.s3.raffusercloud.com/raff_functions_event_driven_architecture_webp_f28cb55a8e.png) This is cleaner than keeping a VM awake only to run a small task every few minutes. Raff Functions supports HTTP live URLs with automatic TLS, timezone-aware cron schedules, one-off future runs, and object-storage events such as bucket uploads with prefix filters. That makes functions a natural fit for tasks that do not need a full server process. :::cta Explore Raff Functions Use Raff Functions for HTTP handlers, cron jobs, object-storage events, and one-off tasks that should run only when needed. ::: ## Use VMs when the workload needs a full environment A VM is still the better choice when the workload needs a complete server. Use a VM when you need: - A long-running web app - A Docker Compose environment - Custom system packages - Full SSH access - A specific Linux distribution - Persistent local services - Manual process control - Long-lived TCP connections - Custom network configuration - Sidecar services - Self-hosted databases or queues - Full filesystem control - Background workers that run constantly - Predictable always-on capacity - Existing deployment scripts built around servers A VM is especially useful when the team wants to keep architecture simple. For example, an early SaaS app may run perfectly on one Raff VM: ```text Raff VM ↓ App runtime or Docker Compose ↓ Nginx reverse proxy ↓ Systemd services ↓ Database or external managed database ``` That setup is often easier to understand, debug, and operate than splitting every task into separate functions too early. A function is not a replacement for every server. It is a better fit for certain kinds of work. ## The cost model is different VM cost is mostly capacity-based. You choose a server size and pay for the capacity while it exists. If your app is busy all day, that can be efficient. If the VM sits idle most of the time, you still pay for the reserved capacity. Function cost is mostly usage-based. You pay when code runs, usually based on runtime resources. This can be efficient for spiky, occasional, or event-driven work. It can become less attractive when the workload is constantly running or when it needs a large runtime environment for long periods. Raff Functions bills on two meters: memory and active CPU. Requests and egress are free, and a spend cap is on by default. Raff also provides a monthly free tier of 100,000 GB-seconds and 10,000 vCPU-seconds. This makes Raff Functions useful for teams that want cost to follow execution instead of server uptime. But cost comparison should always match the workload. | Workload shape | Cost risk on VM | Cost risk on function | |---|---|---| | Rare scheduled job | Paying for idle capacity | Usually low | | Spiky webhook traffic | Overprovisioning or manual scaling | Usage spikes need spend control | | Always-on app server | Efficient if fully used | May be less natural | | Heavy batch job | VM may need temporary scale-up | Duration and memory must be planned | | File processing after uploads | VM can become noisy | Good fit if runtime is bounded | | Constant worker queue | Predictable VM may be simpler | High continuous usage may add up | A function is not automatically cheaper. It is cheaper when usage-based execution matches the workload. A VM is not automatically wasteful. It is efficient when the workload uses the capacity consistently. ## Runtime and portability matter Serverless platforms can create lock-in when the handler format, event structure, deployment model, or runtime assumptions are proprietary. For small teams, portability matters because the codebase is still changing. The team may move between local development, VMs, containers, and functions as the architecture matures. Raff Functions is designed around standard handlers: - Python FastAPI / ASGI - Node.js standard `http` - TypeScript - JavaScript Web Fetch - Go `net/http` - Any language through a Dockerfile escape hatch That matters because the code should not need a major rewrite just to move in or out of a functions environment. A good portability rule: > The closer a function looks like normal application code, the easier it is to maintain. This is especially useful when a team begins on a VM, extracts one task into a function, and later decides whether that task should remain a function, become a worker, or move into Kubernetes. ## Cron jobs are a natural functions use case Cron jobs often start small and become messy. One script runs every night. Then another runs every hour. Then a cleanup job runs every five minutes. Then a billing job, report job, import job, and notification job appear. Eventually, the main app VM becomes responsible for too many background tasks. Functions are a clean fit for many scheduled jobs because they run only when needed. Good cron-function candidates include: - Deleting temporary files - Sending daily reports - Syncing external APIs - Checking expired subscriptions - Rotating short-lived tokens - Creating invoices - Running light data cleanup - Updating cached summaries - Checking failed webhook retries - Processing small recurring imports A VM-based cron job is still fine when the script needs local system access, shares a complex app environment, or runs constantly enough that a server process is simpler. The decision is not "cron is old, functions are new." The decision is whether the scheduled work deserves a full server environment. For a deeper background-work comparison, connect this article with [Cron Jobs vs Queues vs Workflow Automation](/learn/guides/cron-jobs-queues-workflow-automation-background-work). ## Webhooks are usually better isolated Webhooks are one of the best reasons to use functions. A webhook endpoint usually receives an external event, validates the request, writes a record, triggers work, and returns quickly. It does not usually need the whole application server environment. A function can isolate webhook handling from the main app: ```text External service ↓ Raff Function webhook endpoint ↓ Validate signature ↓ Write event to database or queue ↓ Return response ``` This is useful for: - Stripe-style billing events - GitHub events - CRM callbacks - Email delivery callbacks - Form submissions - Monitoring alerts - Marketplace events - Automation workflows - Third-party API notifications The benefit is operational isolation. A webhook spike does not need to hit the main application server directly. The function can validate, normalize, and pass work to the right place. For production, webhooks still need clear rules: - Validate signatures - Return quickly - Store event IDs - Make processing idempotent - Handle retries - Avoid doing heavy work inside the request path - Send long work to a queue or worker - Log enough context for debugging Functions make webhook routing easier, but correctness still depends on application design. ## Databases and files should live outside functions Functions should not become a hidden database. A function should usually read or write durable data through a proper data layer: ```text Function ↓ Managed database for records ↓ Object storage for files ``` Use a database for: - Users - Accounts - Orders - Payments - Audit logs - App state - Job status - Metadata - Durable business records Use object storage for: - Uploads - Images - Exports - Reports - Generated files - Backups - Media - Attachments - Artifacts Raff Functions can bind to Raff Managed Databases and Raff Object Storage with scoped credentials. This keeps functions stateless while data lives in the right service. This matters because serverless code should be easy to scale, retry, and replace. If files or critical state live inside the execution environment, the architecture becomes fragile. For related reading, use [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage) and [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps). ## Long-running functions change the batch decision Traditional serverless decisions often break around duration. A small handler is easy. A long AI inference, ETL process, file conversion, export, import, or streaming task is harder. Some teams move these tasks to a VM only because the functions platform has a short timeout. Raff Functions supports timeouts up to 1 hour by default and up to 24 hours on request. That does not mean every long job should be a function. It means the decision can be based on architecture instead of an artificial duration ceiling. Use a long-running function when: - The job is triggered by an event - The job can run independently - The environment is not too heavy - Progress and failures are visible - Output is written to database or object storage - The job does not need a full VM - The team wants usage-based execution Use a VM when: - The job runs constantly - The environment is large or custom - The task needs full OS control - The worker depends on long-lived local state - Multiple processes coordinate on the same machine - Manual debugging through SSH is important - Capacity-based cost is simpler For example: | Job | Function fit | VM fit | |---|---|---| | Resize uploaded images | Strong | Also possible | | Generate a monthly PDF report | Strong | Possible | | Run a constant queue worker | Depends | Strong | | Train a long-running custom ML process | Depends | Stronger if environment is complex | | Process rare CSV imports | Strong | Possible | | Run a browser automation worker all day | Depends | Often VM | | Nightly cleanup script | Strong | Possible | Longer function timeouts are useful, but the team should still design around retries, failure visibility, and idempotency. ## VMs remain better for persistent services Some workloads want to stay alive. A web server listens continuously. A database maintains state. A queue worker may run all day. A reverse proxy handles routing. A Docker Compose stack may contain several services that expect stable networking and local process control. Those workloads are natural on a VM. A VM is also better when the team wants to inspect the environment directly: ```text ssh into server check logs restart service inspect process change config run migration debug network ``` That direct control is not always elegant, but it is useful for small teams. Many early production apps benefit from a simple server that the developer understands deeply. Serverless functions reduce server management for event-driven work. VMs reduce platform abstraction for full-environment workloads. Both forms of simplicity are valid. The mistake is choosing one model for every workload. :::cta Deploy a Raff VM Use Raff VM when your application needs a full Linux environment, Docker Compose, SSH access, persistent processes, or custom server control. ::: ## The strongest small-team architecture often uses both For many SaaS apps, the best architecture is mixed. A simple production architecture might look like this: ![Raff architecture diagram showing VM Managed Database Object Storage and Functions working together](https://raff-images.s3.raffusercloud.com/raff_functions_vm_mixed_architecture_webp_892b28db8a.png) This keeps the main app stable while moving event-driven work out of the server. Examples: | Use case | Main home | Why | |---|---|---| | Customer-facing app | VM | Stable runtime and full control | | Database | Managed database | Durable state and managed operations | | Uploads | Object storage | Files should not live in compute | | Image resize | Function | Runs after upload event | | Billing webhook | Function | Isolated external event handling | | Daily report | Function | Scheduled task without server cron | | Heavy constant worker | VM | Predictable always-on workload | | API callback | Function | Event-driven and isolated | | Admin dashboard | VM | Part of core app | This approach avoids the two common extremes: - Putting every background task on the app VM - Splitting the app into functions before the product needs that complexity A good architecture should make the product easier to operate next month, not just more modern today. ## Raff-specific path from VM to functions A cost-aware Raff path can be staged. ### Stage 1: One Raff VM Start with one VM when the app is early. ```text Raff VM ↓ App + background jobs + simple cron ``` This is clear and easy to operate. ### Stage 2: Move durable data out Move the database to Raff Managed Databases when data reliability and operations matter. ```text Raff VM ↓ Raff Managed Database ``` This separates compute from persistent records. ### Stage 3: Move files out Move uploads, reports, media, and generated files to Raff Object Storage. ```text App VM ↓ Managed Database for metadata ↓ Object Storage for files ``` This prevents file growth from forcing VM changes. ### Stage 4: Extract event-driven tasks into functions Move webhooks, cron, file processing, and one-off jobs into Raff Functions. ```text Raff Function ↓ Managed Database ↓ Object Storage ``` This reduces background-job pressure on the app VM. ### Stage 5: Use more infrastructure only when needed If workloads keep growing, add worker VMs or Kubernetes when coordination justifies it. ```text Raff VM + Raff Functions ↓ Worker VMs or Raff Kubernetes when needed ``` This path lets infrastructure grow with the product instead of forcing a big platform decision too early. :::cta View Raff Pricing Compare Raff VM and Raff Functions pricing before choosing capacity-based or usage-based infrastructure for your workload. ::: ## Common mistakes to avoid ### Moving the whole app to functions too early A full SaaS app is often easier to run on a VM at first. Functions are excellent for event-driven pieces, but splitting every route, job, and process into functions can make debugging harder before the team has enough traffic to justify it. ### Keeping every background task on the main VM The opposite mistake is letting the main app server run everything. If cron jobs, webhooks, file processing, reports, and cleanup scripts compete with the customer-facing app, functions can help isolate the work. ### Forgetting that functions should be stateless Functions should write durable records to a database and durable files to object storage. Do not depend on local runtime state for business-critical data. ### Ignoring timeouts and retries Even with longer execution windows, functions need failure handling. Design for retries, idempotency, duplicate events, and clear logs. ### Comparing only monthly price Compare operating model, not only sticker price. A VM may be cheaper for constant usage. A function may be cheaper for spiky tasks. The real question is which model reduces both infrastructure cost and operations cost. ### Creating too many tiny services Every new deployment unit adds monitoring, naming, security, environment variables, ownership, and debugging work. Extract functions when there is a clear operational reason. ### Using functions to hide poor architecture If the database is slow, uploads are stored in the wrong place, or jobs lack retry logic, functions will not automatically fix the design. Fix the architecture underneath. ## Serverless functions vs VMs comes down to workload shape Serverless functions and VMs are both useful for small teams. They solve different problems. Use serverless functions when work is event-driven, isolated, scheduled, bursty, or triggered by HTTP, cron, object storage, or one-off events. Use VMs when the app needs a full environment, long-lived processes, custom packages, persistent services, Docker Compose, SSH access, or predictable always-on capacity. For Raff teams, the cleanest path is usually mixed: [Raff VM](/products/raff-vm) for the main application, [Raff Managed Databases](/products/managed-databases) for durable records, [Raff Object Storage](/products/object-storage) for files, and [Raff Functions](/products/serverless-functions) for event-driven work that should run independently. Choose the model that makes the workload easier to operate for the next 6-12 months. :::cta Explore Raff Functions Use Raff Functions when your workload is event-driven, scheduled, or triggered by HTTP, storage events, or one-off tasks. ::: --- ### Serverless Function Pricing: CPU, Memory, Requests, and Egress URL: https://rafftechnologies.com/learn/guides/serverless-function-pricing-cpu-memory-egress Description: Learn how serverless function pricing works for CPU, memory, requests, egress, cron jobs, webhooks, storage events, and Raff Functions. Serverless Function Pricing: CPU, Memory, Requests, and Egress Serverless function pricing should be easy to estimate before a small team deploys code. The problem is that many serverless bills are not simple. One platform may charge for requests, memory duration, CPU allocation, egress, logs, warm instances, build minutes, gateway traffic, or add-on observability. A workload that looked cheap in development can become harder to forecast when traffic, response size, logging, or runtime duration changes. Raff Technologies takes a simpler approach with [Raff Functions](/products/serverless-functions): memory and active CPU are the two metered numbers. Requests and egress are free, a spend cap is on by default, and every account gets a monthly free tier for function usage. This guide explains how to think about serverless function pricing before deployment: what memory means, what active CPU means, why requests and egress can make other platforms harder to predict, and how small teams should estimate function cost for webhooks, cron jobs, storage events, batch jobs, and small APIs. If you are still deciding whether the workload belongs on functions or a VM, read [Serverless Functions vs VMs: What Small Teams Should Choose](/learn/guides/serverless-functions-vs-vms-small-teams) first. ## Serverless pricing has two different cost shapes Serverless pricing usually follows the shape of execution. Instead of choosing a fixed VM size and paying for it while it exists, a function platform bills around how often the function runs and how much resource it uses during execution. That can be excellent for spiky, scheduled, or event-driven work. It can be less ideal when the workload is always busy, requires a heavy runtime, or runs for long periods without interruption. There are two main cost shapes: | Cost shape | Best fit | Risk | |---|---|---| | Usage-based | Spiky requests, webhooks, cron jobs, storage events, one-off tasks | Cost changes with invocation volume and duration | | Capacity-based | Always-on apps, constant workers, persistent services | You pay for reserved capacity even when idle | Functions are not automatically cheaper than VMs. VMs are not automatically wasteful. The right question is: > Does this workload benefit from paying only while it runs? For example, an image-resize job that runs only when users upload files is a strong function candidate. A queue worker that runs at high utilization all day may be easier to forecast on a VM or Kubernetes worker. Serverless pricing is strongest when the workload has a clear beginning, clear ending, and idle periods. ## The Raff Functions pricing model Raff Functions uses two metered numbers: 1. Memory 2. Active CPU ![Diagram showing Raff Functions pricing with memory and active CPU metered while requests egress cron logs and spend cap are included](https://raff-images.s3.raffusercloud.com/raff_functions_pricing_model_breakdown_b9c280bcc8.png) Requests and egress are free. Cron scheduling, logs, and metrics are included. A spend cap is on by default. Raff also includes a monthly free tier of: - 100,000 GB-seconds - 10,000 vCPU-seconds The published Raff Functions rates are: | Meter | Price | |---|---:| | Memory | $0.0000035 per GB-second | | Active CPU | $0.000020 per vCPU-second | | Requests | Free | | Egress | Free | | Cron scheduling | Included | | Logs and metrics | Included | The simple version: ```text Function cost = billable memory GB-seconds + billable active CPU seconds ``` This matters because many teams can reason about two numbers more easily than five or six billing lines. The important distinction is that memory is based on the provisioned memory over the wall-clock lifetime of the instance, while active CPU is billed only while code is actually on CPU. Waiting on I/O should not behave the same as CPU-heavy work. That makes the model easier to reason about for common function workloads: - Webhooks that wait on external APIs - Storage events that process files - Cron jobs that call databases - Small APIs with short execution time - ETL jobs with mixed CPU and I/O - AI or batch jobs that need longer execution windows :::cta Explore Raff Functions Use Raff Functions when you want serverless pricing based on memory and active CPU, with free requests and free egress. ::: ## Memory pricing means duration still matters Memory pricing is based on GB-seconds. A GB-second combines two things: 1. How much memory the function is provisioned with 2. How long the function instance runs A simple way to estimate memory usage is: ```text memory GB-seconds = memory in GB × duration in seconds × invocations ``` Example: ```text Invocations: 1,000,000 per month Memory: 256 MB = 0.25 GB Average duration: 200 ms = 0.2 seconds Memory GB-s = 0.25 × 0.2 × 1,000,000 = 50,000 GB-s ``` If this is the only memory usage for the month, it fits inside the 100,000 GB-s monthly free tier. The most important cost levers are: - Invocation count - Average duration - Memory setting - Whether the function scales into multiple concurrent instances - Whether optional warm instances are enabled Do not set memory by guesswork forever. Start with a reasonable value, then review usage. Too little memory may slow the function down. Too much memory may raise memory GB-second usage without improving runtime. For small teams, the practical goal is not always the lowest memory number. The goal is the best balance between runtime, reliability, and cost. ## Active CPU pricing separates compute from waiting Active CPU pricing is useful because not all function time is equal. Some functions spend most of their time doing CPU work: - Image processing - PDF generation - Compression - Data transformation - Encryption - CPU-heavy parsing - AI inference - Video or audio preprocessing Other functions spend much of their time waiting: - Calling an external API - Waiting for a database response - Reading or writing object storage - Waiting on a webhook response - Performing lightweight request routing A function that waits on I/O should not necessarily be priced like a function burning CPU the whole time. That is why Raff separates memory and active CPU. Memory measures the provisioned runtime footprint. Active CPU measures CPU time while the code is actually on CPU. A rough mental model: ```text wall-clock duration = how long the function instance exists active CPU time = how much CPU the code actually consumes ``` This is especially relevant for webhook handlers and API integrations. A billing webhook may receive an event, validate a signature, write a row, call another API, and return. The wall-clock time may include waiting, but the active CPU time may be lower. For cost planning, identify whether the workload is CPU-heavy or I/O-heavy. | Workload | Likely pricing driver | |---|---| | Image resizing | Active CPU + memory | | Webhook receiver | Invocations + memory, usually lower CPU | | API proxy | Invocations + I/O waiting | | PDF generation | CPU + memory + duration | | Cron cleanup | Duration + database access | | CSV import | Duration + memory + CPU | | ETL transform | CPU + duration | | Object storage metadata task | Invocations + short duration | | AI inference | CPU + memory + duration | The more CPU-heavy the function, the more active CPU becomes the key number. ## Requests and egress change the predictability of serverless bills Requests and egress can make serverless bills harder to forecast. A request fee charges based on how many times the function is invoked. That may seem small per request, but it becomes another moving part. Egress charges based on outbound data transfer. That can be especially hard to forecast when response sizes, downloads, media files, or API payloads grow. Raff Functions keeps requests and egress free for the functions product. That means teams do not need to model these function-specific cost lines: - Request count fees - Outbound egress from function responses - Cron trigger fees - Basic logs and metrics as a separate product bill This is useful for workloads like: - Webhooks with unpredictable retry behavior - Public API endpoints with many small requests - Object-storage event handlers - Report download preparation - Image transformation endpoints - Automation callbacks - Scheduled API syncs - Developer tools and internal APIs Free requests do not mean cost does not change. Memory and active CPU can still increase with usage. But removing request and egress fees makes the bill easier to reason about. For a small team, fewer billing dimensions are often more valuable than a tiny discount on one meter. ## Estimate cost before deployment Before deploying a function, estimate the workload with five inputs: 1. Monthly invocations 2. Average duration 3. Memory setting 4. Active CPU behavior 5. Response size or egress pattern On Raff, response size does not add function egress charges, but it still helps the team understand workload shape. A function returning tiny webhook responses is different from a function returning large generated files. Large files should often be stored in [Raff Object Storage](/products/object-storage) and returned through object storage patterns instead of direct function responses. A simple estimate table: | Input | Example | |---|---:| | Invocations per month | 3,000,000 | | Average duration | 180 ms | | Memory | 128 MB | | Memory GB-s | 67,500 GB-s | | Active CPU estimate | 33,750 vCPU-s | | Requests | Free | | Egress | Free | With the monthly free tier applied: ```text Memory: 67,500 GB-s - 100,000 free GB-s = $0.00 Active CPU: 33,750 vCPU-s - 10,000 free vCPU-s = 23,750 billable vCPU-s 23,750 × $0.000020 = $0.475 ``` This is a simplified planning example. Real usage depends on actual runtime, memory setting, CPU behavior, concurrency, and workload mix. The important point is that a small team can estimate the main cost drivers before deployment. :::cta View Raff Pricing Compare Raff Functions pricing with Raff VM pricing when deciding between usage-based and capacity-based infrastructure. ::: ## Common workload examples Different function workloads behave differently. ### Webhook receiver A webhook receiver is usually a strong serverless fit. ```text External service → Function → Database or queue → Quick response ``` Cost drivers: - Invocation count - Signature validation time - Database write time - Retry volume - Logging volume Optimization: - Return quickly - Store event ID - Avoid heavy work inside the request - Send longer work to a queue, function, or worker - Keep response payload small ### Image resize after upload Image resizing is often CPU-heavy. ```text Object Storage upload → Function → Resize → Object Storage output ``` Cost drivers: - Number of uploads - Image size - Processing time - Memory requirement - CPU time Optimization: - Resize only required sizes - Store outputs in object storage - Avoid reprocessing existing images - Use metadata to track completed variants ### Scheduled cleanup job Cron jobs are usually easy to estimate. ```text Cron schedule → Function → Database cleanup or API sync ``` Cost drivers: - Schedule frequency - Average duration - Database/API response time - Memory setting Optimization: - Reduce unnecessary frequency - Batch safely - Use indexes - Avoid scanning full tables - Log summaries, not every row ### Long-running ETL or batch task Batch functions need careful planning. ```text Trigger → Function → Transform data → Database/Object Storage ``` Cost drivers: - Duration - Memory - Active CPU - Retry behavior - Output size - Failure recovery Optimization: - Make tasks idempotent - Split very large jobs into chunks - Store intermediate results safely - Track progress in a database - Use object storage for files and artifacts ### Lightweight API endpoint Small APIs can be a strong fit when traffic is spiky. ```text HTTP request → Function → API response ``` Cost drivers: - Invocation count - Average duration - Memory - Cold start sensitivity - External API waiting time Optimization: - Keep handler small - Avoid unnecessary dependencies - Use standard handlers - Keep secrets and bindings clean - Consider warm instances only for latency-critical paths ## When a VM may cost less A VM may be cheaper or cleaner when the workload is always running. For example, if a worker processes jobs all day with steady CPU usage, a VM can be easier to forecast. The team pays for capacity and keeps using it. A function can still work, but the usage-based model may not provide the same benefit when there is little idle time. Use [Raff VM](/products/raff-vm) when: - The workload runs constantly - The app needs a full Linux environment - Docker Compose is the deployment model - SSH debugging matters - Custom packages are required - Several services must run together - The workload needs persistent local processes - Capacity-based monthly pricing is easier to plan - The team wants server-level control A pricing decision should include operations. A VM may require more patching, process management, and scaling decisions. A function may require more attention to triggers, stateless design, runtime limits, retries, and event behavior. The cheaper bill is not always the cheaper operating model. For the architecture decision, read [Cloud VM vs App Platform for Startups](/learn/guides/cloud-vm-vs-app-platform-startups) and [Production VPS Checklist Before Launching a SaaS App](/learn/guides/production-vps-checklist-saas-app). ## Spend caps matter for small teams A spend cap is not a small feature. It is a financial safety guard. Serverless workloads can grow quickly because functions are easy to trigger. A webhook retry storm, bad cron loop, public API spike, broken client, or repeated object-storage event can create more execution than expected. Raff Functions has a spend cap on by default. When the cap is reached, functions pause instead of creating a runaway bill. That matters for small teams because the team may not have a dedicated infrastructure finance process. A default cap helps prevent cost surprises while the product is still learning traffic patterns. A good operating rule: - Set a cap before production traffic. - Monitor usage during the first week. - Review 5-minute usage windows after launch. - Raise the cap only after expected traffic is understood. - Treat sudden usage increases as product and security signals. Spend caps do not replace monitoring, but they create a safer default. ## Logs and metrics should not become a second bill Observability is part of function operations. A team needs to know: - How many times the function ran - How long it took - Whether it failed - Which trigger caused it - Which request produced which logs - Whether p95 latency changed - Whether errors increased - Whether cold starts matter - Whether retries are happening Raff Functions includes logs and metrics for every invocation, with live log tail, search, level filters, 14-day retention, count, p50, p95, and error rate per function. This matters because some serverless systems become hard to forecast when the function bill is only one part of the real operating cost. If logs, metrics, tracing, and alerting require a separate paid setup, the total bill can feel different from the compute estimate. For small teams, included observability reduces the number of add-ons needed to operate the function safely. ## Warm instances should be used intentionally Scale-to-zero is one of the strongest serverless cost advantages. When a function is idle, it does not need to keep a full server running. Raff Functions scales to zero, and optional warm instances are available at 30% of the memory rate for latency-critical paths. That creates a decision: | Path | Best for | |---|---| | Scale to zero | Most webhooks, cron jobs, file events, internal tools | | Warm instances | Latency-sensitive public APIs or user-facing endpoints | Do not keep every function warm by default. Warm instances can improve latency, but they also change the cost shape because some capacity stays ready. Use them only when latency matters enough to justify the always-ready baseline. A good pattern: - Keep webhooks scale-to-zero unless latency is customer-critical. - Keep cron jobs scale-to-zero. - Keep file event processors scale-to-zero. - Consider warm instances for user-facing APIs with strict latency needs. - Revisit warm settings after measuring p50 and p95 latency. ## Pricing should influence architecture, not distort it Pricing should guide architecture, not force unnatural design. Do not split a simple application into ten functions only because the first estimate looks cheap. Each function adds deployment, ownership, logs, environment variables, secrets, testing, and failure modes. Also do not keep every background task on one VM just because the VM already exists. If scheduled jobs and webhooks are slowing the main app, the "free" capacity may be costing user experience and developer time. A good Raff architecture often looks mixed: ```text Raff VM = main app Raff Managed Database = durable records Raff Object Storage = uploads and files Raff Functions = event-driven tasks ``` This keeps each workload in the right cost model. Use functions for work that starts and ends cleanly. Use VMs for full environments and persistent services. Use managed databases for durable records. Use object storage for files and artifacts. ## Serverless pricing checklist Before deploying a production function, answer these questions: - [ ] What triggers the function? - [ ] How many invocations per month are expected? - [ ] What is the average duration? - [ ] What is the p95 duration? - [ ] How much memory does the function need? - [ ] Is the workload CPU-heavy or I/O-heavy? - [ ] Does it need warm instances? - [ ] Does it write durable records to a database? - [ ] Does it store files in object storage? - [ ] Is retry behavior controlled? - [ ] Is the function idempotent? - [ ] What happens if the trigger fires repeatedly? - [ ] What spend cap should be set? - [ ] Who owns the function? - [ ] What logs and metrics should be reviewed? - [ ] Should this run as a VM worker instead? The last question is important. A function is not the right answer just because the platform supports it. ## Common pricing mistakes to avoid ### Comparing only compute price Compute is only one part of the operating model. Requests, egress, logs, metrics, warm instances, retries, and development workflow can change the real cost. ### Ignoring duration A function that runs twice as long may cost roughly twice as much on duration-based meters. Optimize slow database calls, external API waits, and unnecessary dependency loading. ### Overprovisioning memory More memory can improve performance for some workloads, but it should be measured. Do not keep oversized memory settings if runtime does not improve. ### Treating every endpoint as a function Some apps are easier on a VM. Use functions for clear event-driven units of work, not as a default replacement for all application structure. ### Forgetting retry storms Webhook retries, failed jobs, or repeated storage events can create unexpected invocation volume. Design idempotency and set spend caps. ### Returning large files directly from functions Large files should often live in object storage. Use functions to authorize, transform, or generate metadata, then store artifacts in object storage when appropriate. ### Keeping warm instances everywhere Warm instances are useful for latency-sensitive functions, but they add baseline cost. Use them selectively. ## Serverless function pricing should be predictable before launch Small teams should not discover their function bill after production traffic arrives. Estimate invocation volume, duration, memory, active CPU behavior, and whether the workload truly benefits from usage-based execution. On Raff Functions, the model is intentionally narrow: memory and active CPU are metered, while requests and egress are free. The monthly free tier, included logs and metrics, and default spend cap make it easier to start safely. Use [Raff Functions](/products/serverless-functions) for event-driven tasks, webhooks, cron jobs, object-storage events, and one-off work. Use [Raff VM](/products/raff-vm) when the workload needs a full Linux environment, persistent services, Docker Compose, SSH access, or capacity-based cost planning. Then check [Raff pricing](/pricing) and compare the workload shape before choosing the deployment model. :::cta Explore Raff Functions Estimate your function cost before deployment with memory and active CPU as the two metered numbers. ::: --- ### Long-Running Serverless Functions for AI, ETL, and Batch Jobs URL: https://rafftechnologies.com/learn/guides/long-running-serverless-functions-ai-etl-batch Description: Learn when to use long-running serverless functions for AI, ETL, batch, cron, and storage events, and when Raff VM is a better fit. Long-running serverless functions are functions designed for workloads that need minutes or hours to complete instead of a short request-response window. For small teams, this matters because not every background task fits into a tiny handler. AI inference, document processing, file conversion, ETL jobs, exports, imports, streaming tasks, and data cleanup can run longer than a normal web request. Traditionally, teams moved those jobs to a VM or worker server because their serverless platform had strict duration limits or pricing that became difficult to forecast. Raff Technologies gives teams another option with [Raff Functions](/products/serverless-functions): run event-driven jobs as functions with timeouts up to 1 hour by default and up to 24 hours on request. The same product also supports HTTP live URLs, timezone-aware cron schedules, one-off future runs, object-storage events, standard handlers, logs and metrics, and pricing based on memory plus active CPU. This guide explains when a long-running serverless function makes sense, when a VM or worker server is still better, and how to design AI, ETL, and batch jobs so they remain observable, retryable, and cost-aware. If you are still comparing deployment models, read [Serverless Functions vs VMs: What Small Teams Should Choose](/learn/guides/serverless-functions-vs-vms-small-teams) and [Serverless Function Pricing: CPU, Memory, Requests, and Egress](/learn/guides/serverless-function-pricing-cpu-memory-egress) first. ## Long-running functions change the serverless decision Serverless functions are often associated with short tasks: webhooks, API handlers, cron jobs, and quick file events. ![Diagram showing AI ETL batch file processing cron and object storage workloads running on long-running Raff Functions](https://raff-images.s3.raffusercloud.com/long_running_functions_workload_map_webp_4d3de92f99.png) That is still a strong use case. But many real SaaS tasks do not finish in a few seconds. Examples include: - AI inference - ETL jobs - Batch imports - CSV processing - PDF generation - Image or media processing - Large report exports - Data enrichment - Web scraping jobs - Scheduled database cleanup - Object-storage file processing - Long third-party API syncs - Streaming or chunked responses - Customer data migration tasks When serverless duration is too short, teams often create a second system: a worker VM, queue worker, batch container, or Kubernetes job. That can be the right decision, but it also adds another operational layer. Long-running functions reduce that pressure. If a job is event-driven, isolated, and can write progress or output to a durable service, it may not need a full worker server. The question is not only "Can a function run this long?" The better question is: > Can this long task run safely as an isolated, observable, retryable function? If yes, long-running functions can simplify the architecture. ## The quick decision framework Use this table before choosing a long-running function, VM, worker, or Kubernetes job. | Workload | Better default | Why | |---|---|---| | AI inference triggered by request or event | Long-running function | Event-driven and bounded | | Nightly ETL job | Function or worker VM | Depends on runtime, duration, and dependencies | | Always-on queue worker | VM or Kubernetes | Constant work may fit capacity-based compute | | Large file conversion after upload | Function | Storage event can trigger isolated processing | | Long report export | Function | Output can be written to object storage | | Continuous stream processor | VM or Kubernetes | Persistent process may be cleaner | | One-time migration | Function if bounded; VM if manual control is needed | Choose by debugging and runtime needs | | Webhook with heavy downstream processing | Function plus queue/worker | Return quickly and process separately | | CPU-heavy batch job all day | VM or Kubernetes | Always-on compute may be easier to forecast | | Short scheduled cleanup | Function | Cron trigger and scale-to-zero fit well | | Complex multi-step workflow | Function chain, queue, or workflow tool | Needs state and failure handling | | Job needing SSH debugging | VM | Full server access helps investigation | A useful rule: > Use a long-running function when the task is event-driven and bounded. Use a VM when the environment must stay alive. Long duration alone does not decide the architecture. Workload shape does. ## Good long-running function candidates A long-running function works best when the job has a clear input, clear output, and clear completion point. ### AI inference AI inference can take longer when models, prompts, files, or external APIs are involved. A function can receive the request, run the inference step, write the result to a database or object storage, and return a status or output. ```text Trigger ↓ Raff Function ↓ AI inference or model/API call ↓ Database status + Object Storage output ``` This is useful when inference is occasional, user-triggered, or bursty. ### ETL jobs ETL tasks extract data, transform it, and load it somewhere else. A function can run on a schedule or one-off trigger, process a bounded dataset, and write results to a database or object storage. ```text Cron schedule ↓ Function extracts data ↓ Function transforms records ↓ Database or Object Storage receives output ``` This works best when the ETL job can be chunked or bounded. ### File processing after upload Object-storage events are a natural trigger for long-running functions. ```text File uploaded ↓ Object Storage event ↓ Function processes file ↓ Output saved to Object Storage ↓ Metadata saved to database ``` Examples: - Resize images - Convert PDFs - Parse CSV files - Generate thumbnails - Extract metadata - Validate uploaded files - Compress or transform assets ### Batch exports and reports Large reports should not block the main application server. A function can generate the report, store it in object storage, and update the database when the report is ready. ```text User requests export ↓ Function generates file ↓ Object Storage stores report ↓ Database stores status and download link ``` This keeps the web app responsive while the longer job runs independently. ## When a VM or worker is still better Long-running functions do not replace every worker server. ![Decision diagram comparing long-running Raff Functions with Raff VM for bounded jobs and always-on workers](https://raff-images.s3.raffusercloud.com/long_running_functions_vs_vm_decision_webp_76f096910d.png) Use a VM, worker VM, or Kubernetes worker when the job needs: - Constant processing - Always-on queue consumption - SSH debugging - Complex system packages - Heavy local dependencies - Persistent local state - Long-lived TCP connections - Custom networking - GPU or specialized host access - Manual inspection during runtime - Several processes coordinating together - A stable filesystem across jobs - Capacity-based cost control A constant worker may be cleaner on a [Raff VM](/products/raff-vm): ```text Raff VM ↓ Worker process ↓ Queue ↓ Managed Database + Object Storage ``` That pattern is still valid when work is continuous. If the worker is busy all day, usage-based function execution may not be the simplest or cheapest operating model. A long-running function is strongest when the workload starts from a clear trigger and can finish independently. A VM is strongest when the service itself needs to keep running. :::cta Deploy a Raff VM Use Raff VM when long-running work needs SSH access, custom packages, persistent services, or always-on worker capacity. ::: ## Design long-running functions around durable state Long-running functions should not keep important state only in memory. A job may run for minutes or hours. During that time, the platform, network, external API, database, or code path can fail. The function needs a way to resume, retry, or at least explain what happened. ![Architecture diagram showing Raff Function with Managed Database for job state and Object Storage for input and output files](https://raff-images.s3.raffusercloud.com/long_running_function_durable_state_architecture_webp_85fde9f792.png) Use durable state for: - Job status - Job ID - Input location - Output location - Start time - Last progress marker - Failure reason - Retry count - User/account ownership - Result metadata - Audit trail A simple model: ```text Database = job status and metadata Object Storage = input and output files Function = execution logic ``` That keeps the function stateless enough to retry and observable enough to debug. A good job table might track: | Field | Purpose | |---|---| | job_id | Unique job identifier | | account_id | Tenant or customer owner | | status | queued, running, succeeded, failed | | input_uri | Object storage path or source reference | | output_uri | Result file path | | progress | Optional percentage or step marker | | attempts | Retry count | | error_message | Safe failure summary | | started_at | Runtime visibility | | finished_at | Completion visibility | The function should not be the only place that knows whether the job succeeded. ## Store files and artifacts outside the function Long-running functions often handle files. Do not depend on local function storage as the final home for generated files, uploads, or artifacts. Use [Raff Object Storage](/products/object-storage) for durable outputs. Good object-storage outputs include: - Generated PDFs - Exported CSV files - Processed images - Model output files - ETL artifacts - Validation reports - Import logs - Compressed archives - Transformed media - Batch results A clean file-processing pattern: ```text Input file in Object Storage ↓ Function reads input ↓ Function writes output ↓ Database stores metadata ``` This makes the job easier to retry. If a function fails after writing partial output, the database can mark the job failed and the next run can decide whether to overwrite, resume, or write a new object. For related storage decisions, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## Make long-running jobs idempotent Idempotency means the same job can run more than once without creating duplicate or corrupted results. This is important for long-running functions because retries can happen. Users may click the same action twice. External APIs may send duplicate events. A function may fail after doing part of the work. A job may be restarted manually. A long-running job should answer: - Can the same job ID run twice safely? - Can the same input file be processed twice? - Can the output object be overwritten safely? - Does the database update use a unique key? - Are duplicate webhooks ignored? - Are partial outputs cleaned up? - Can the job resume from a checkpoint? - Is a failed job distinguishable from an unfinished job? Common idempotency techniques: | Technique | Use | |---|---| | Job IDs | Prevent duplicate job creation | | Unique database constraints | Prevent duplicate records | | Output paths with versioning | Avoid overwriting the wrong file | | Status transitions | Control running, succeeded, failed states | | Checkpoints | Resume large jobs | | Input hashes | Detect repeated file processing | | Retry counters | Prevent infinite retries | A long-running function should be designed as if it may run again. That mindset prevents many production issues. ## Break very large work into chunks A single long-running function can be useful, but not every job should be one huge run. If a task processes 5 million rows, thousands of files, or a large customer dataset, chunking may be safer. Chunking helps with: - Retry behavior - Partial progress - Memory control - Parallelism - Cost visibility - Failure isolation - Time-window control - Debugging A chunked pattern: ```text Parent job ↓ Create chunk jobs ↓ Function processes each chunk ↓ Database tracks progress ↓ Final function merges or marks complete ``` Chunking is useful for: - Large CSV imports - Customer data migrations - ETL batches - Backfills - Image sets - Search index rebuilds - Report generation - AI batch inference Do not chunk too early for small jobs. Chunk when the job size makes retries or progress tracking important. A good rule: > If restarting from zero would hurt, add checkpoints or chunks. ## Use cron for scheduled long-running jobs Cron triggers are useful when long work happens on a schedule. Raff Functions supports timezone-aware cron schedules, which can fit recurring jobs such as: - Nightly ETL - Daily reports - Weekly summaries - Hourly syncs - Cleanup jobs - Expired subscription checks - Data warehouse exports - Cache refreshes - Security scans - Scheduled file processing A scheduled long-running function should still be bounded. Before running it daily, define: - Expected runtime - Maximum runtime - Input size - Output location - Failure notification path - Retry behavior - Duplicate-run prevention - Whether overlapping runs are allowed - Whether the job can skip if the last run is still active For example: ```text Daily 02:00 ↓ Check whether previous job is still running ↓ Create new job record ↓ Process dataset ↓ Write output ↓ Mark job succeeded or failed ``` Cron is simple. Production cron needs guardrails. ## Use object-storage events for file-driven jobs Object-storage events are useful when work should start after a file arrives. Examples: - User uploads a video - Customer uploads a CSV - App writes a PDF for processing - Backup archive lands in a bucket - External system drops files into a prefix - Image upload needs thumbnails - Import folder receives a new file A good pattern: ```text Object uploaded to bucket prefix ↓ Raff Function starts ↓ Function validates file ↓ Function processes file ↓ Function writes output to Object Storage ↓ Function updates database status ``` Use prefix filters to avoid triggering functions on every object in a bucket. For example, input files can land under: ```text incoming/ ``` and outputs can be written to: ```text processed/ ``` This prevents output files from retriggering the same function by accident. File-driven jobs should also validate file type, size, tenant ownership, and expected schema before processing. ## Logs and metrics are part of long-running function design Long-running functions need more than "it failed." A job that runs for 20 minutes should produce enough visibility to answer: - When did it start? - What input did it process? - Which customer/account owned the job? - Which step is running? - How many records were processed? - What external dependency was slow? - What failed? - Was the failure safe to retry? - Did the function write any output? - How long did each phase take? Raff Functions includes logs and metrics for every invocation, with live log tail, search and level filters, 14-day retention, count, p50, p95, and error rate per function. For long-running jobs, log at important boundaries: ```text job_started input_validated chunk_started chunk_completed output_written database_updated job_completed job_failed ``` Avoid logging sensitive data. Log identifiers, counts, timings, and safe error summaries. Good logs make long-running functions safer because the team can understand progress without SSH access. ## Cost planning for long-running functions Long-running functions need cost planning before launch. The main cost inputs are: - Invocation count - Average duration - Memory setting - Active CPU time - Optional warm instance behavior - Retry frequency - Data read and write patterns - Whether work can be chunked Raff Functions bills memory and active CPU. Requests and egress are free. That means the cost conversation should focus on runtime size and compute behavior. Ask: - Is the job CPU-heavy or I/O-heavy? - Does more memory reduce runtime? - Does the job wait on external APIs? - Can the job be split into smaller chunks? - How often will it run? - What happens during retries? - What spend cap should protect the account? - Would a VM be cheaper if the job runs constantly? A long-running function can be cost-effective for bursty or scheduled jobs. A VM may be cleaner for work that runs all day. For the full pricing discussion, read [Serverless Function Pricing: CPU, Memory, Requests, and Egress](/learn/guides/serverless-function-pricing-cpu-memory-egress). :::cta View Raff Pricing Compare Raff Functions and Raff VM pricing before choosing a long-running function or always-on worker. ::: ## Security and access should be scoped per job Long-running functions often touch sensitive systems: databases, object storage, customer files, internal APIs, or third-party credentials. Do not give every function broad access. Use scoped access for: - Database credentials - Object storage buckets - API tokens - Environment variables - Customer-specific data - Internal service endpoints A file-processing function should not automatically have access to every bucket. A reporting function should not automatically have write access to unrelated systems. An ETL function should not expose credentials through logs. Raff Functions supports bindings to Raff Managed Databases and Raff Object Storage with scoped credentials. Use those bindings to keep each function's access focused on what the job actually needs. For production, also define: - Who can deploy the function - Who can view logs - Who can change triggers - Who can rotate credentials - Who owns the spend cap - Who receives failure alerts Long-running jobs often have wider impact than small handlers. Treat their access accordingly. ## A practical Raff architecture for long-running functions A strong Raff architecture keeps compute, state, and files separated. ```text HTTP / cron / object-storage event ↓ Raff Function ↓ Raff Managed Database = job status and durable records ↓ Raff Object Storage = input and output files ↓ Raff VM or Kubernetes = optional always-on workers ``` This architecture gives each layer a clear job: | Layer | Responsibility | |---|---| | Raff Function | Executes the event-driven task | | Managed Database | Stores status, metadata, records, and progress | | Object Storage | Stores files, artifacts, and outputs | | Raff VM | Runs persistent workers or full server environments | | Kubernetes | Runs orchestrated services when cluster coordination is needed | A small team does not need all layers on day one. Start with the simplest version: ```text Raff Function ↓ Database ↓ Object Storage ``` Add a VM or Kubernetes only when the workload becomes constant, complex, or coordination-heavy. ## Common mistakes to avoid ### Treating a long function like a web request A job that runs for minutes or hours needs status tracking, progress, and failure handling. Do not make users wait on a browser tab for a long operation. ### Storing output only inside the function Generated files should go to object storage. Job metadata should go to a database. The function should not be the final storage layer. ### Forgetting retries and duplicate runs Long-running jobs can fail after partial progress. Design job IDs, status transitions, idempotent writes, and retry rules before production. ### Processing huge datasets as one block If restarting from zero would be painful, split the work into chunks. Chunking improves retry behavior and progress visibility. ### Running constant work as functions without checking cost If the job runs all day, a VM or Kubernetes worker may be simpler and easier to forecast. ### Logging too much or too little Logs should show progress and failures without exposing secrets or customer data. Log job IDs, step names, counts, timings, and safe summaries. ### Giving every function broad credentials Scope credentials to the database, bucket, API, or service the function actually needs. Long-running jobs often have more access than small handlers, so access control matters. ## Long-running functions should simplify the workload A long-running function is useful when it removes operational weight without hiding complexity. Use long-running Raff Functions for AI inference, ETL, file processing, scheduled jobs, imports, exports, and batch work when the task is event-driven, bounded, observable, and writes durable state to the right layer. Use [Raff VM](/products/raff-vm) or Kubernetes when the workload is constant, needs a full server environment, requires SSH debugging, or depends on persistent local services. The safest pattern is simple: let [Raff Functions](/products/serverless-functions) execute the task, let [Raff Managed Databases](/products/managed-databases) store job state and records, and let [Raff Object Storage](/products/object-storage) store files and artifacts. Then choose the model your team can operate reliably for the next 6-12 months. :::cta Explore Raff Functions Use Raff Functions for long-running AI, ETL, batch, cron, and object-storage jobs that should run independently. ::: --- ### Cron Jobs on Serverless Functions vs Cron on a VM URL: https://rafftechnologies.com/learn/guides/serverless-cron-jobs-vs-vm-cron Description: Learn when to run cron jobs on serverless functions or VMs, with examples for scheduled tasks, reports, syncs, retries, and Raff Functions. Cron jobs on serverless functions vs cron on a VM is really a question about ownership, reliability, visibility, and workload shape. A cron job is a scheduled task. It might run every minute, every hour, every night, every Monday, or on a custom business schedule. Small teams use cron jobs for cleanup, billing checks, reports, API syncs, cache refreshes, imports, exports, and background maintenance. The problem is not cron itself. The problem is where the scheduled work should live. For Raff Technologies users, there are two clean paths: use [Raff Functions](/products/serverless-functions) when the scheduled job is event-driven, bounded, stateless, and should run only when needed; use [Raff VM](/products/raff-vm) when the scheduled job depends on a full server environment, local packages, SSH debugging, persistent services, or existing VM-based application code. This guide explains when serverless cron is the better fit, when VM cron is still the simpler choice, and how to design scheduled jobs so they do not silently become production risk. If you are still comparing the broader models, read [Serverless Functions vs VMs: What Small Teams Should Choose](/learn/guides/serverless-functions-vs-vms-small-teams) first. ## Cron jobs are simple until they become production infrastructure Cron starts as a convenience. A developer adds one scheduled script: ```text 0 2 * * * run-nightly-cleanup ``` Then the product grows. Soon the server has jobs for: - Daily reports - Subscription checks - Invoice generation - Email digests - Expired session cleanup - Cache refreshes - Third-party API syncs - Failed webhook retries - CSV imports - Object storage cleanup - Data warehouse exports - Search index updates - Security checks - Backup verification At that point, scheduled work is no longer a small helper. It is part of the production system. A production cron job needs answers: - Where does it run? - Who owns it? - What happens if it fails? - What happens if it runs twice? - What happens if the previous run is still active? - Where are logs stored? - How is success measured? - How are credentials scoped? - How is runtime cost controlled? - Should this be a function, VM job, worker, or queue? The scheduling syntax is the easy part. The operating model is the real decision. ## The quick decision framework Use this table before deciding between serverless cron and VM cron. ![Decision matrix comparing serverless cron jobs on Raff Functions with cron jobs on Raff VM](https://raff-images.s3.raffusercloud.com/serverless_cron_vs_vm_cron_decision_matrix_webp_05a2249837.png) | Scheduled job | Better default | Why | |---|---|---| | Short cleanup task | Serverless function | Runs only when needed | | Nightly API sync | Serverless function | Scheduled, bounded, easy to isolate | | Daily report generation | Serverless function | Output can go to object storage | | Job that needs local app files | VM cron | Runs inside existing server environment | | Job that needs SSH debugging | VM cron | Direct server inspection helps | | Job that runs every minute all day | Depends | Function if bounded; VM if effectively always-on | | Job that uses custom system packages | VM cron | Full OS control is easier | | File processing after upload | Function trigger or cron function | Better separated from app server | | Database maintenance script | VM or managed database tooling | Depends on access and risk | | Long ETL job | Long-running function or worker VM | Choose by duration, dependencies, and control | | Queue retry processor | Worker VM or function | Depends on retry pattern and volume | | Security scan | Function or VM | Depends on target and required tools | A useful rule: > Use serverless cron when the schedule starts a bounded task. Use VM cron when the task depends on the server environment. Cron should not be chosen because "the VM already exists." It should be chosen because it is the right place for that scheduled workload. ## Serverless cron is best for bounded scheduled work Serverless cron is a good fit when a job has a clear start, clear finish, and no need to keep a server alive between runs. Good examples include: - Send daily email digest - Sync an external API every hour - Clean expired temporary records - Refresh a cached summary - Generate a weekly report - Check failed webhook retries - Rotate short-lived tokens - Run a scheduled import - Process small batches - Create invoice drafts - Validate uploaded files on a schedule - Update usage counters - Export data to object storage The architecture is simple: ```text Cron schedule ↓ Raff Function ↓ Managed Database / Object Storage / API ``` The function runs because the schedule fires. It finishes. Then it disappears until the next run. That has clear benefits: - No idle server process - No shared app-server resources - Separate logs per invocation - Easier isolation from the main app - Lower risk of cron jobs slowing web traffic - Clear trigger ownership - Better fit for spiky or occasional scheduled tasks Raff Functions supports timezone-aware cron schedules, so jobs can be configured around the business schedule instead of only server-local assumptions. :::cta Explore Raff Functions Use Raff Functions for scheduled jobs that should run independently without keeping a VM process alive. ::: ## VM cron is still useful when the server environment matters VM cron is not outdated. It is still the right choice when the scheduled task belongs inside a full server environment. Use VM cron when the job needs: - Local application code - Existing server packages - Shell scripts already deployed on the VM - Full filesystem access - SSH debugging - Custom binaries - Local Docker Compose services - Internal tools installed on the server - Server-level network configuration - A job that coordinates with local services - Always-on worker behavior - Manual inspection during incidents A VM cron pattern looks like this: ```text Raff VM ↓ cron schedule ↓ local script or app command ↓ database / files / external API ``` This can be the simplest solution for early SaaS apps. If the app already runs on one VM and the job is closely tied to that app environment, server cron may be easier to maintain than creating a separate function too early. The risk is that VM cron can become invisible. Jobs may run on a server that only one developer understands. Logs may live in local files. Failures may not alert anyone. Scripts may accumulate without ownership. Jobs may compete with the web app for CPU, memory, or disk. VM cron is fine. Hidden VM cron is not. ## Scheduled work should not slow the main app One of the strongest reasons to move cron jobs into functions is isolation. On a single VM, scheduled jobs can compete with the main application: ```text Web app ↓ shares CPU / memory / disk with Cron jobs ``` This is usually fine for small tasks. It becomes risky when jobs are CPU-heavy, memory-heavy, or unpredictable. Warning signs: - Web requests slow down during scheduled jobs - Nightly reports increase CPU or disk load - API syncs cause memory spikes - Cleanup jobs lock database rows - Cron scripts produce large logs - File exports fill local disk - Several jobs start at the same time - The team avoids running jobs during business hours - Cron failures are discovered by customers When scheduled work starts affecting user experience, separate it. A serverless cron function can run outside the main app server: ```text Raff Function ↓ scheduled job ↓ database / object storage ``` A worker VM can also be the right separation layer: ```text App VM ↓ Worker VM with cron or queue processor ↓ database / object storage ``` The right choice depends on whether the work is occasional and bounded or constant and environment-heavy. ## Cron jobs need idempotency Idempotency means a job can run more than once without creating duplicate or corrupted results. This matters for both function cron and VM cron. ![Checklist infographic showing production cron job requirements including idempotency overlap control logs retries credentials and durable output](https://raff-images.s3.raffusercloud.com/production_cron_safety_checklist_webp_17a92fd6e1.png) Scheduled tasks can run twice because: - A retry happens - A developer manually reruns a job - A deployment restarts a worker - Two environments share the same schedule - The previous run has not finished - The schedule was copied into another service - A time-zone or daylight-saving change creates confusion A cron job should answer: - Can this job run twice safely? - Does it use a unique job ID? - Does the database prevent duplicate records? - Can it resume from a checkpoint? - Does it know if a previous run is still active? - Does it skip, queue, or overlap when a prior run is active? - Does it write output with a stable or versioned path? - Does it update status only after output is complete? For example, invoice generation should not create duplicate invoices if it runs twice. A report export should not overwrite the wrong file. A cleanup job should not delete data outside the expected window. A safe pattern: ```text Create job record ↓ Check if job already completed ↓ Run work ↓ Write output ↓ Mark job complete ``` Cron is scheduling. It is not correctness. The application must handle correctness. ## Overlapping jobs are a real production risk A job that runs every 5 minutes may take 7 minutes during peak load. Now the next scheduled run starts while the previous run is still active. That can cause: - Duplicate processing - Database lock contention - API rate-limit issues - Object overwrite conflicts - Excess memory use - Confusing logs - Incorrect status - Higher function cost - Slower app performance Before production, decide how overlapping runs should behave. | Overlap policy | What it means | Good for | |---|---|---| | Skip | If previous run is active, do nothing | Cleanup jobs, periodic syncs | | Queue | Run after current job finishes | Important sequential jobs | | Parallelize | Allow multiple runs | Independent chunks or per-tenant jobs | | Fail fast | Mark as failed and alert | Jobs that should never overlap | | Lock | Use database or distributed lock | Critical jobs with strict exclusivity | For small teams, skip or lock is often enough. A simple database lock or job status check can prevent many incidents: ```text if existing_job.status == "running": skip new run else: start new run ``` For high-volume background processing, a queue may be better than cron alone. Cron can create jobs, while workers process them. For related background-work design, read [Cron Jobs vs Queues vs Workflow Automation](/learn/guides/cron-jobs-queues-workflow-automation-background-work). ## Logs and metrics decide whether cron is trustworthy A scheduled job without logs is a guess. A production cron job should show: - When it started - When it finished - Whether it succeeded - Whether it failed - How long it ran - Which input it processed - How many records changed - Which external API failed - Whether it retried - Whether it skipped because another run was active - Which output file or record was produced VM cron often fails here because logs are stored in local files or shell output. That can work, but only if the team has a consistent pattern. Function cron can make this easier because each invocation has its own runtime logs and metrics. Raff Functions includes logs and metrics for every invocation, with live log tail, search and level filters, 14-day retention, invocation count, p50, p95, and error rate per function. That is useful for scheduled jobs because the team can answer: ```text Did the 09:00 job run? Did it fail? How long did it take? Did it get slower this week? Did error rate change? ``` Cron is only reliable if the team can observe it. ## Credentials should be scoped to the scheduled task Cron jobs often need privileged access. They may read customer records, call billing APIs, write reports, delete old data, rotate credentials, or access object storage. That makes credential scope important. Do not give every scheduled job broad credentials. A report job may need read access to specific database tables and write access to a specific object-storage prefix. A cleanup job may need write access to a narrow set of records. A sync job may need one external API token. Good credential rules: - Use separate credentials per job when possible - Avoid sharing root credentials - Keep secrets out of code - Rotate credentials when ownership changes - Do not print secrets in logs - Scope object-storage keys to the required bucket or prefix - Scope database users by job responsibility - Remove credentials when a job is retired Raff Functions can bind to Raff Managed Databases and Raff Object Storage with scoped credentials. VM cron can also be secured, but the team must manage server-level files, environment variables, secret rotation, and access control carefully. Scheduled jobs are often trusted. That is exactly why they should be scoped. ## Store files in object storage, not the cron environment Scheduled jobs often create files: - Daily reports - CSV exports - Invoices - Backup summaries - Import results - PDF reports - Data validation logs - Generated artifacts - Compressed archives Do not treat the function runtime or app VM as the final file store. Use [Raff Object Storage](/products/object-storage) for durable files and use the database for metadata. A clean scheduled-report pattern: ```text Cron schedule ↓ Function or VM job generates report ↓ Object Storage stores file ↓ Database stores status and output_uri ``` This keeps files separate from compute. It also makes retry behavior clearer. If the job fails, the database can mark the job failed. If the job succeeds, the database can point to the exact output object. For related reading, use [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## Cost planning for scheduled work Cron cost depends on job frequency, duration, and resource use. A job that runs once per day for 10 seconds is very different from a job that runs every minute for 45 seconds. For function cron, estimate: - Runs per month - Average duration - Memory setting - Active CPU behavior - Retry frequency - Whether the job overlaps - Whether it needs warm instances - Whether it produces large files For VM cron, estimate: - VM size - Whether the VM already runs the main app - CPU/memory pressure during jobs - Whether jobs force a larger VM - Disk usage from logs or files - Operations time - Whether a separate worker VM is needed A simple comparison: | Job shape | Cost-friendly model | |---|---| | Runs once per day | Function | | Runs once per hour | Function | | Runs every minute but finishes quickly | Depends | | Runs constantly | VM or Kubernetes worker | | Uses heavy CPU for hours daily | Compare both | | Needs full app environment | VM | | Triggers on file upload | Function | | Produces files | Function or VM + object storage | Raff Functions bills memory and active CPU, with requests and egress free. Raff VM uses capacity-based pricing. Choose based on how the scheduled work behaves, not only on which tool feels newer. :::cta View Raff Pricing Compare Raff Functions and Raff VM pricing before deciding where scheduled jobs should run. ::: ## A practical Raff cron architecture A small team can use a staged approach. ![Raff architecture diagram showing cron schedules running on Raff Functions with Managed Database Object Storage and VM cron option](https://raff-images.s3.raffusercloud.com/raff_scheduled_jobs_architecture_webp_b1e204e8d1.png) ### Stage 1: VM cron inside one app server Early on, one VM may be enough. ```text Raff VM ↓ App + cron jobs ↓ Database ``` This is simple, but watch for resource contention and invisible failures. ### Stage 2: Move files and durable outputs out Scheduled jobs should write durable files to object storage. ```text Raff VM cron ↓ Database status ↓ Object Storage output ``` This prevents local disk from becoming a hidden dependency. ### Stage 3: Move bounded scheduled jobs into functions When cron jobs are independent and bounded, move them to Raff Functions. ```text Raff Function ↓ Managed Database ↓ Object Storage ``` This isolates scheduled work from the main app server. ### Stage 4: Use worker VMs for constant background work If scheduled work becomes constant or queue-based, move it to a worker VM. ```text App VM ↓ Worker VM ↓ Managed Database + Object Storage ``` This keeps the main app responsive while preserving full server control for background processing. ### Stage 5: Use Kubernetes only when coordination justifies it If many services, workers, schedules, and environments need orchestration, Kubernetes may become useful. ```text Kubernetes workloads ↓ CronJobs / workers / services ↓ Managed Database + Object Storage ``` Do not jump to Kubernetes only because cron jobs grew. First separate the workload cleanly. ## Serverless cron checklist Use this checklist before moving scheduled jobs to production. - [ ] The job has one clear owner. - [ ] The schedule is documented. - [ ] The time zone is explicit. - [ ] The job can run twice safely or has a lock. - [ ] Overlap behavior is defined. - [ ] Failure behavior is defined. - [ ] Retry behavior is defined. - [ ] Logs show start, finish, duration, and result. - [ ] The job writes durable state to a database if needed. - [ ] Generated files go to object storage. - [ ] Credentials are scoped. - [ ] Secrets are not logged. - [ ] Runtime cost is estimated. - [ ] Spend cap or usage guardrail is set. - [ ] The job can be disabled safely. - [ ] There is a manual rerun process. - [ ] The job does not slow the main app. - [ ] The team knows when to use a VM worker instead. The difference between a harmless cron job and a production incident is usually not syntax. It is the missing operating rules. ## Common mistakes to avoid ### Letting cron jobs become invisible If nobody knows which jobs run, when they run, and where they log, the system is fragile. Document schedules and owners. ### Running heavy jobs on the main app VM If scheduled work slows user-facing traffic, move it to a function, worker VM, or separate system. ### Ignoring time zones A job that runs at the wrong business hour can break billing, reports, notifications, or customer workflows. Use explicit time-zone configuration. ### Allowing overlapping runs accidentally Jobs that run longer than their schedule interval can overlap. Use locks, skip rules, or queues. ### Storing reports on local disk Generated files should live in object storage with metadata in a database. Local disk should not become the hidden archive. ### Using broad credentials Scheduled jobs often have powerful access. Scope credentials to the exact database, bucket, API, or action the job needs. ### Assuming function cron is always cheaper Serverless cron is strong for bounded scheduled work. VM cron or a worker VM may be better for constant, heavy, or environment-dependent work. ## Cron should run where the workload belongs Cron is only the trigger. The real decision is where the scheduled work should execute. Use [Raff Functions](/products/serverless-functions) for scheduled jobs that are bounded, independent, event-driven, and do not need a full server environment. Use [Raff VM](/products/raff-vm) when the job depends on local packages, SSH debugging, persistent services, Docker Compose, or a full application server. The clean Raff pattern is simple: scheduled job logic runs in the right compute layer, durable state lives in [Raff Managed Databases](/products/managed-databases), and generated files live in [Raff Object Storage](/products/object-storage). That keeps cron from becoming a hidden operational risk. Start with the simplest place that keeps the job observable, safe to retry, and easy to operate for the next 6-12 months. :::cta Explore Raff Functions Use Raff Functions for timezone-aware cron jobs that should run independently from your main app server. ::: --- ### Webhooks on Serverless Functions: When to Use Functions Instead of VMs URL: https://rafftechnologies.com/learn/guides/serverless-functions-for-webhooks Description: Learn when to use serverless functions for webhooks, when VMs are better, and how to design webhook retries, logs, security, and storage. Webhooks on serverless functions are useful when an external system needs to notify your application without sending that traffic directly to your main app server. A webhook is an event delivered over HTTP. Payment processors, Git platforms, CRMs, email providers, monitoring tools, automation platforms, and internal systems use webhooks to tell your app that something happened. The receiving endpoint should validate the event, return quickly, store enough state, and move heavier work out of the request path. For Raff Technologies users, [Raff Functions](/products/serverless-functions) is a strong fit for webhook handling because each function can have an HTTP live URL with automatic TLS, logs and metrics for each invocation, standard handlers, free requests and egress, and a spend cap on by default. A [Raff VM](/products/raff-vm) is still the better fit when the webhook handler depends on a full server environment, local app code, Docker Compose, persistent services, or SSH debugging. This guide explains when to put webhooks on serverless functions, when to keep them on a VM, and how to design webhook architecture so retries, duplicate events, secrets, logs, and downstream work do not become production risk. If you are still comparing the broader models, read [Serverless Functions vs VMs: What Small Teams Should Choose](/learn/guides/serverless-functions-vs-vms-small-teams) first. ## Webhooks are event-driven by nature A webhook starts because something happened somewhere else. ![Architecture diagram showing external webhooks received by Raff Functions with validation database state and downstream processing](https://raff-images.s3.raffusercloud.com/webhook_serverless_function_architecture_53cb6e875a.png) Examples: - A payment succeeded - A subscription failed - A GitHub pull request opened - An email bounced - A CRM contact changed - A monitoring alert fired - A form was submitted - A customer uploaded a file - A marketplace order changed - An automation workflow reached a step - A third-party API finished a task This is exactly the kind of workload serverless functions are designed to handle. A webhook does not usually need a full server. It needs an HTTP endpoint that can receive the event, validate it, store it, and trigger the next step. A clean webhook pattern looks like this: ```text External service ↓ Webhook endpoint ↓ Validate signature ↓ Store event or status ↓ Trigger background work ↓ Return quickly ``` The endpoint should not try to do everything during the request. If the downstream work is heavy, move it to a queue, another function, a worker VM, or a background workflow. A webhook endpoint is often small, but it can have a large production impact. That is why isolation, visibility, and retry design matter. ## The quick decision framework Use this table before deciding where a webhook should run. ![Decision diagram comparing webhooks on Raff Functions with webhooks on Raff VM](https://raff-images.s3.raffusercloud.com/serverless_webhooks_vs_vm_webhooks_decision_641f48bcd0.png) | Webhook situation | Better default | Why | |---|---|---| | Lightweight event receiver | Serverless function | Event-driven and isolated | | Payment webhook | Serverless function with durable database writes | Needs fast acknowledgement and idempotency | | Git or CI webhook | Serverless function | Triggered by external event, easy to isolate | | CRM or form webhook | Serverless function | Usually bounded and HTTP-based | | Email delivery callback | Serverless function | High-volume callbacks should not hit the main app | | Webhook starts heavy processing | Function plus queue or worker | Return quickly, process separately | | Webhook needs local app files | VM | Depends on full server environment | | Webhook needs SSH debugging | VM | Direct inspection may matter | | Webhook shares Docker Compose services | VM | Local service dependencies are easier | | Webhook traffic is constant and heavy | Function or VM, compare cost | Workload shape decides | | Webhook needs custom system packages | VM or Dockerfile function | Choose based on dependency complexity | | Webhook writes files | Function plus object storage | Files should not live in the function runtime | A useful rule: > Use a function when the webhook is an event boundary. Use a VM when the webhook is tightly coupled to the server environment. Most webhook receivers are event boundaries. That makes serverless functions a natural starting point. ## Why serverless functions fit webhook receivers A webhook endpoint has a few simple responsibilities: 1. Receive the HTTP request 2. Validate the sender 3. Store or update durable state 4. Trigger any downstream work 5. Return a response quickly This maps well to serverless functions. With Raff Functions, a webhook can run as a standard HTTP handler. Raff Functions supports HTTP live URLs with automatic TLS, standard handlers such as Python FastAPI / ASGI, Node.js standard `http`, JavaScript Web Fetch, TypeScript, Go `net/http`, and a Dockerfile escape hatch for other languages. That matters because webhook code should be easy to understand and easy to move. A handler that looks like normal application code is easier to test, maintain, and migrate later. Serverless functions are especially useful for webhooks because they can: - Stay isolated from the main app server - Scale with webhook bursts - Avoid keeping a server awake for occasional events - Produce per-invocation logs and metrics - Return quickly - Use scoped credentials - Trigger downstream work - Reduce pressure on the main app VM - Keep third-party event traffic separate from user traffic :::cta Explore Raff Functions Use Raff Functions for webhook endpoints that should run independently from your main app server. ::: ## When webhooks should stay on a VM A function is not always the right home. Keep webhook handling on a VM when the endpoint depends heavily on the server environment. Use a VM when the webhook handler needs: - Existing local application code - Docker Compose services - Local queues or services - Custom binaries - Full filesystem access - SSH debugging - Persistent local state - Long-lived processes - Internal server-only tools - Complex network configuration - Manual inspection during incidents - Tight coupling to the main app routing layer A VM-based webhook pattern looks like this: ```text External service ↓ Nginx or app server on Raff VM ↓ Application route ↓ Database / queue / local service ``` That can be the simplest architecture when the app is early and webhook traffic is low. If the entire app already runs on one Raff VM, adding one webhook route to the same app may be perfectly reasonable. The risk appears when external event traffic starts affecting the user-facing app. If webhook retries, signature verification, third-party spikes, or downstream processing slow the main app, isolate the webhook. ## Return quickly and process later Webhook senders usually expect a fast response. If your endpoint takes too long, the sender may retry. If the sender retries while your app is still processing the previous event, duplicate work can happen. A safer pattern is: ```text Webhook request ↓ Validate sender ↓ Write event record ↓ Return 2xx response ↓ Process asynchronously ``` The asynchronous step can be: - Another function - A queue worker - A worker VM - A scheduled retry job - A background task - A workflow tool The key is to separate acknowledgement from heavy processing. Do not make the webhook request wait while you: - Generate reports - Send many emails - Process files - Run long AI inference - Sync large datasets - Call several slow APIs - Perform large database updates - Build export files For long work, use [Long-Running Serverless Functions for AI, ETL, and Batch Jobs](/learn/guides/long-running-serverless-functions-ai-etl-batch) or move the work to a worker VM. A webhook should normally say: "I received the event." It should not do the entire business workflow inside the HTTP request. ## Validate signatures before trusting events Webhook endpoints must not trust every incoming request. Most webhook providers support a signing mechanism, shared secret, token, or header-based verification. The endpoint should validate that the request came from the expected sender before processing it. A webhook validation flow: ```text Receive request ↓ Read signature header ↓ Reconstruct signed payload ↓ Verify with secret ↓ Reject if invalid ↓ Process if valid ``` For production, define: - Which header contains the signature - Which secret verifies the request - Whether timestamps are checked - Whether replay protection is needed - What status code invalid requests receive - Whether invalid requests are logged - Whether logs avoid exposing secrets - How secrets are rotated Do not put webhook secrets directly in code. Use environment variables or secret management. Raff Functions supports environment variables and masked secrets, so the handler can read configuration without exposing it in the source file. Signature validation should happen before any database write that changes state. ## Idempotency prevents duplicate webhook damage Webhook duplicates are normal. A provider may retry after a timeout. A network issue may hide the response. A user may trigger the same event twice. A deployment may process the same stored event again. A failed function may be retried. The endpoint must treat duplicate events as expected. Idempotency means the same event can be processed more than once without causing duplicate or corrupted results. Use these techniques: | Technique | Use | |---|---| | Store provider event ID | Detect duplicates | | Unique database constraint | Prevent duplicate inserts | | Status transitions | Avoid repeating completed work | | Idempotency key | Link repeated requests to one action | | Output path versioning | Prevent overwriting wrong artifacts | | Retry counter | Stop infinite loops | | Event log table | Keep audit trail | | Job table | Track downstream processing | A simple webhook event table can store: | Field | Purpose | |---|---| | event_id | Provider event ID | | provider | Stripe, GitHub, CRM, email vendor, etc. | | event_type | Kind of event | | account_id | Tenant or customer owner | | received_at | Arrival time | | status | received, processing, completed, failed | | attempts | Processing attempts | | payload_hash | Duplicate detection | | error_message | Safe failure summary | A webhook handler should check whether the event already exists before creating new business records. For example: ```text if event_id already exists: return success else: store event and continue ``` Duplicate protection is not optional for payment, billing, order, account, or subscription webhooks. ## Store the event before doing heavy work A reliable webhook handler should save the event or the important state before doing slow work. This creates a recovery path. If the function fails after receiving the webhook, the system can still know what arrived. If downstream work fails, a scheduled retry job or worker can inspect failed events and retry them safely. A good pattern: ```text Validate request ↓ Write event record ↓ Return response ↓ Process event ↓ Update event status ``` This is better than doing all work in memory. For example, a billing webhook should not only update subscription state directly. It should also record the provider event ID and processing status. That gives the team an audit trail if a customer asks why their subscription changed. Raff Managed Databases can store webhook events, job status, and durable business records. Raff Object Storage can store larger payloads, generated files, exports, or artifacts when the webhook leads to file work. The function should execute the logic. Durable state should live in the database or object storage layer. ## Use object storage for webhook artifacts Some webhooks lead to files. Examples: - A form submission includes an attachment - A document-signing provider sends a completed PDF - A media provider sends a processed file - A report needs to be generated after an event - A customer uploads a file through a third-party service - A marketplace sends order documents - An import job starts after a webhook Do not store those files inside the function runtime. A clean pattern: ```text Webhook arrives ↓ Function validates event ↓ Function stores metadata in database ↓ Function stores files/artifacts in Object Storage ``` Use [Raff Object Storage](/products/object-storage) for: - Attachments - Generated reports - Provider payload archives - Export files - Signed documents - Processed media - Import artifacts - Debug-safe event samples - Long-term audit files The database should store metadata and object paths, not the full file body unless there is a specific reason. For the storage decision, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## Logs and metrics make webhook failures visible Webhook failures can be hard to see because they happen between systems. A customer may say a payment succeeded, but the app did not update. A CRM may show a contact changed, but your product did not receive it. An email provider may retry events, but your app may not show why. A webhook endpoint needs visibility. Track: - Invocation count - Error rate - p50 and p95 latency - Invalid signature count - Duplicate event count - Retry count - Event type distribution - Provider response status - Database write failures - Slow downstream calls - Failed processing status Raff Functions includes logs and metrics for every invocation, with live log tail, search, level filters, 14-day retention, count, p50, p95, and error rate per function. For webhook logs, use safe structured messages: ```text webhook_received provider=stripe event_id=evt_123 type=invoice.paid webhook_validated provider=stripe event_id=evt_123 webhook_duplicate provider=stripe event_id=evt_123 webhook_processing_started event_id=evt_123 webhook_processing_completed event_id=evt_123 duration_ms=214 webhook_processing_failed event_id=evt_123 reason=database_timeout ``` Do not log secrets, full payment details, tokens, or sensitive customer payloads. Good webhook logs should help the team answer what happened without exposing private data. ## Retry behavior should be designed Webhooks involve at least two retry systems: 1. The provider may retry delivery. 2. Your system may retry downstream processing. Those should not be confused. Provider retries are about delivery. Your system retries are about business processing. A good design separates them: ```text Provider retry ↓ Function receives duplicate event ↓ Event ID already exists ↓ Return success ``` and: ```text Stored event has failed processing status ↓ Retry worker or function runs later ↓ Processing succeeds or fails again ``` Decide: - Which errors should return non-2xx? - Which errors should return 2xx but mark processing failed? - How many internal retries are allowed? - What backoff strategy is used? - Who is alerted after final failure? - How are failed events replayed? - Can one event block others? - Can processing run twice safely? For many webhooks, the endpoint should return quickly after storing the event. If processing fails after that, handle retries internally. This avoids making the third-party provider responsible for your internal processing workflow. ## Security boundaries matter more for public endpoints A webhook URL is public by design. That means it needs stronger boundaries than an internal-only function. Use these controls: - Validate signatures or tokens - Reject unknown providers - Use HTTPS - Keep secrets out of code - Avoid logging sensitive payloads - Rate-limit where appropriate - Store only necessary payload data - Scope database credentials - Scope object-storage credentials - Use separate functions for unrelated providers - Monitor invalid request patterns - Disable retired webhook endpoints - Rotate secrets after incidents or ownership changes Raff Functions provides HTTP live URLs with automatic TLS, masked secrets, and scoped bindings to Raff Managed Databases and Raff Object Storage. Use those features to keep each webhook narrow. A payment webhook should not share the same broad credentials as a file-processing webhook. A CRM webhook should not have access to unrelated object-storage buckets. A Git webhook should not have database write access unless it actually needs it. Small teams often move fast by using one credential everywhere. That becomes dangerous when the endpoint is public. ## Pricing for webhook functions Webhook cost depends on invocation volume, duration, memory, and active CPU. Webhooks are often short and I/O-heavy. They validate a signature, write a database record, maybe call one API, and return. That can fit usage-based serverless pricing well. Raff Functions bills memory and active CPU. Requests and egress are free. That matters for webhooks because retries and event bursts can increase request counts quickly. Estimate: - Events per month - Retry rate - Average duration - Memory setting - Active CPU time - Whether downstream work happens inside the request - Whether the function calls slow external APIs - Whether payloads are large - Whether heavy work is moved out of the request path A webhook that only validates and stores an event is usually easier to forecast than one that performs long downstream processing during the request. For cost planning, read [Serverless Function Pricing: CPU, Memory, Requests, and Egress](/learn/guides/serverless-function-pricing-cpu-memory-egress). :::cta View Raff Pricing Compare Raff Functions and Raff VM pricing before deciding where public webhook traffic should run. ::: ## A practical Raff webhook architecture A strong Raff webhook architecture keeps the public endpoint isolated and durable state outside the function. ```text External provider ↓ Raff Function webhook URL ↓ Signature validation ↓ Raff Managed Database = event state and business records ↓ Raff Object Storage = files and artifacts ↓ Worker VM or function = downstream processing ``` Each layer has a job: | Layer | Responsibility | |---|---| | Raff Function | Receives, validates, stores, and acknowledges webhook | | Managed Database | Stores event IDs, status, metadata, and business records | | Object Storage | Stores files, attachments, reports, or artifacts | | Worker VM or another function | Handles slow downstream processing | | Logs and metrics | Shows delivery, latency, errors, and retry behavior | This pattern works for: - Billing webhooks - Git provider webhooks - Email delivery callbacks - CRM event callbacks - Form submissions - Marketplace events - Automation workflows - Monitoring alerts Start with one function per provider or per major event family. Avoid one giant webhook function that handles every provider and every event type unless there is a strong reason. ## When to use one function or multiple webhook functions A team can handle webhooks in one function or split them. Use one webhook function when: - Events come from one provider - Event types are closely related - Shared validation logic is useful - Traffic is low - The code remains easy to understand - The same credentials and data access are needed Use multiple webhook functions when: - Providers are unrelated - Security boundaries differ - Credentials should be separate - One provider has high traffic - Event handling logic is large - Different teams own different integrations - Different runtime settings are needed - Failure isolation matters A practical split: ```text billing-webhook git-webhook email-webhook crm-webhook file-event-webhook ``` This keeps ownership clear. Do not split too early into dozens of tiny functions if the team cannot operate them. Split when security, traffic, ownership, or complexity justify it. ## Webhook readiness checklist ![Checklist infographic showing webhook production safety requirements including signatures idempotency retries logs scoped credentials and durable state](https://raff-images.s3.raffusercloud.com/production_webhook_safety_checklist_aa4017d055.png) Before launching a production webhook function, check: - [ ] The webhook provider is identified. - [ ] The endpoint uses HTTPS. - [ ] Signature or token validation is implemented. - [ ] Secrets are stored outside code. - [ ] Invalid signatures are rejected. - [ ] Provider event ID is stored. - [ ] Duplicate events are handled safely. - [ ] The endpoint returns quickly. - [ ] Heavy work is moved out of the request path. - [ ] Event status is stored in a database. - [ ] Files and artifacts go to object storage. - [ ] Retry behavior is defined. - [ ] Internal processing failures are visible. - [ ] Logs do not expose secrets or sensitive payloads. - [ ] Metrics are reviewed after launch. - [ ] Credentials are scoped per function. - [ ] The function has an owner. - [ ] The spend cap is reviewed. - [ ] There is a manual replay process for failed events. - [ ] The team knows when to move work to a VM worker. Production webhooks are small endpoints with large consequences. Treat them accordingly. ## Common mistakes to avoid ### Doing too much inside the webhook request Validate, store, and acknowledge quickly. Move heavy work to a function, queue, worker VM, or background process. ### Skipping signature validation A public URL must not trust every incoming request. Verify the sender before changing data. ### Ignoring duplicate events Webhook providers can retry events. Store event IDs and make processing idempotent. ### Storing only in memory If the function fails, in-memory state disappears. Store event status and durable records in a database. ### Logging sensitive payloads Webhook payloads can contain customer, payment, or private integration data. Log identifiers and safe summaries, not secrets. ### Using one broad credential for every webhook Public endpoints should have narrow credentials. Scope database and object-storage access to what each function needs. ### Keeping webhook traffic on the main app when it causes incidents If webhook spikes or retries slow the customer-facing app, isolate the endpoint. Serverless functions are often a cleaner boundary. ## Webhooks should be isolated, fast, and durable Webhook handlers look small, but they sit at an important boundary between your app and external systems. Use [Raff Functions](/products/serverless-functions) when the webhook is event-driven, should scale independently, should return quickly, and does not need a full server environment. Use [Raff VM](/products/raff-vm) when the webhook depends on local application code, Docker Compose, SSH debugging, custom packages, or persistent server-side services. The strongest Raff pattern is to receive the webhook in a function, validate the sender, store event state in [Raff Managed Databases](/products/managed-databases), store files or artifacts in [Raff Object Storage](/products/object-storage), and move heavy processing into a follow-up function, queue, or worker VM. That keeps webhook traffic away from the main app, makes failures visible, and gives the team a safer retry path. :::cta Explore Raff Functions Use Raff Functions for public webhook endpoints that need fast acknowledgement, logs, metrics, scoped credentials, and independent scaling. ::: --- ### Portable Serverless Handlers: Avoiding Lambda Lock-In URL: https://rafftechnologies.com/learn/guides/portable-serverless-handlers-avoid-lock-in Description: Learn how portable serverless handlers reduce Lambda lock-in, keep functions easier to move, and support standard runtimes on Raff Functions. Portable serverless handlers are function handlers written in standard application formats instead of provider-specific request and response shapes. For small teams, portability matters because the first serverless decision is rarely the last one. A webhook may start on one platform, move into a VM, become a worker, run behind a container, or later move into Kubernetes. If the function code is tied too tightly to one provider's handler signature, event format, SDK, deployment model, or logging system, a simple move can become a rewrite. Raff Technologies designed [Raff Functions](/products/serverless-functions) around standard handlers: Python FastAPI / ASGI, Node.js standard `http`, TypeScript, JavaScript Web Fetch, Go `net/http`, and a Dockerfile escape hatch for other runtimes. The goal is simple: write code that looks like normal application code, not a proprietary function format. This guide explains what serverless lock-in looks like, how portable handlers reduce migration risk, when provider-specific code is still acceptable, and how small teams should structure serverless functions so they can move between Raff Functions, VMs, containers, and other infrastructure without rebuilding the application from scratch. If you are still deciding whether a workload belongs on Functions or a VM, read [Serverless Functions vs VMs: What Small Teams Should Choose](/learn/guides/serverless-functions-vs-vms-small-teams) first. ## Serverless lock-in usually starts small Serverless lock-in does not usually start as a big architectural decision. ![Comparison diagram showing proprietary serverless handlers versus portable standard handlers](https://raff-images.s3.raffusercloud.com/portable_handler_vs_proprietary_handler_webp_d22d3da3ed.png) It starts with one handler: ```python def lambda_handler(event, context): ... ``` or one platform-specific request object, one proprietary event payload, one storage binding, one logging API, one deployment file, or one local development workaround. That may be fine for a prototype. But if the function becomes important, those small choices become migration work. Lock-in can appear in several layers: | Layer | What lock-in looks like | |---|---| | Handler format | Function depends on a provider-specific event and response structure | | Runtime assumptions | Code only works inside one hosted runtime | | Trigger format | HTTP, cron, queue, and storage events use non-portable shapes | | SDK usage | Business logic calls provider SDKs directly everywhere | | Deployment model | Build, config, and routing exist only in one platform | | Logs and metrics | Observability depends on provider-specific tools | | Secrets and bindings | Credentials are injected in a way that cannot move | | Local development | Function cannot run locally without emulating the provider | The risk is not that a team can never move. The risk is that moving becomes expensive at exactly the moment the workload is already important. A portable handler does not eliminate all platform work. It reduces the amount of business logic tied to one platform. ## The quick decision framework Use this table before writing a new serverless function. | Situation | Better pattern | Why | |---|---|---| | HTTP webhook endpoint | Standard HTTP handler | Easier to test, move, and run locally | | Small public API | Standard framework route | Keeps code close to normal app code | | Cron job | Normal function plus explicit input | Avoids platform-only event assumptions | | Object storage event | Thin adapter around standard logic | Keeps business logic portable | | Existing Lambda import | Convert to standard handler when possible | Reduces future migration work | | Language outside common runtimes | Dockerfile handler | Keeps runtime choice flexible | | Provider-specific feature is essential | Isolate provider code | Keep lock-in at the edge | | Business logic calls cloud APIs | Wrap those calls behind small modules | Avoids scattering platform dependency | | Function may move to VM later | Keep environment and config explicit | Makes server migration easier | | Prototype with no reuse expected | Provider-specific handler is acceptable | Speed may matter more than portability | A useful rule: > Put provider-specific code at the edge. Keep business logic in portable modules. That one rule prevents many future rewrites. ## Standard HTTP handlers are easier to move HTTP is the most portable shape for many serverless workloads. A webhook receiver, small API, callback endpoint, form handler, or internal tool can usually be expressed as normal HTTP code: ```text Request ↓ Validate input ↓ Call business logic ↓ Return response ``` That maps naturally to common application frameworks. Raff Functions supports standard handler formats such as Python FastAPI / ASGI, Node.js standard `http`, JavaScript Web Fetch, TypeScript, and Go `net/http`. That means the code can look like normal server code instead of a provider-specific event processor. For example, the portable shape is: ```text HTTP request in HTTP response out ``` The less portable shape is: ```text Provider event object in Provider response object out ``` The difference matters when the team wants to: - Run the same handler locally - Move the route to a VM - Put the route into a container - Test it with normal HTTP tooling - Share code with the main app - Avoid provider-specific mock events - Keep junior developers productive - Reduce migration complexity later A standard HTTP handler is not only cleaner. It is easier to reason about. :::cta Explore Raff Functions Use Raff Functions when you want standard HTTP handlers without learning a proprietary function format. ::: ## Adapters keep platform-specific code at the edge Sometimes a function must receive a provider-specific event. ![Architecture diagram showing a thin adapter converting provider events into portable serverless business logic](https://raff-images.s3.raffusercloud.com/serverless_thin_adapter_architecture_webp_556b20cdb1.png) That is common for: - Storage events - Queue events - Scheduled events - Legacy Lambda events - Provider-specific webhook formats - Internal platform triggers The key is to use a thin adapter. A thin adapter converts the platform event into a normal internal input. Then the business logic runs independently. Bad pattern: ```text Provider event ↓ Business logic mixed with provider event fields ↓ Provider response ``` Better pattern: ```text Provider event ↓ Adapter extracts normal input ↓ Portable business logic ↓ Adapter returns platform response ``` Example structure: ```text handler.py # provider/platform edge service.py # portable business logic repository.py # database access storage.py # object storage wrapper ``` This way, a migration only changes `handler.py` and maybe a small binding layer. The core logic remains the same. That matters for SaaS teams because many early functions become business-critical later. A billing webhook, export processor, file converter, or AI task should not be impossible to move because all logic is tangled with one event object. ## Portable functions need portable configuration Code is only one part of portability. A function also needs configuration: - Environment variables - Secrets - Memory - Timeout - Scaling limits - Trigger type - Database connection - Object storage bucket - API keys - Region - Log level - Feature flags If configuration exists only inside one provider dashboard, moving the function becomes harder. A portable approach: ```text Code reads named environment variables Secrets are documented Bindings are explicit Timeout and memory are recorded Trigger behavior is described Local development has an example .env ``` For example: ```text DATABASE_URL OBJECT_STORAGE_BUCKET WEBHOOK_SECRET LOG_LEVEL MAX_BATCH_SIZE ``` Those names can be reused across Raff Functions, local development, Docker containers, and VMs. Raff Functions supports environment variables, masked secrets, and bindings to Raff Managed Databases and Raff Object Storage with scoped credentials. Use those features, but still keep the function's required configuration clear in the repository. A function that cannot be configured outside the dashboard is not fully portable. ## Avoid spreading provider SDK calls through business logic Provider SDKs are sometimes necessary. A function may need to read object storage, call a queue, fetch secrets, publish events, or write logs. That is fine. The problem is scattering provider-specific SDK calls across the entire codebase. Better pattern: ```text business logic ↓ small interface/module ↓ provider-specific SDK ``` Example: ```text storage.save_report(file) database.update_job_status(job_id, status) notifications.send_email(user_id, template) ``` The business logic should not need to know which platform stores the file or how the credential is injected. This helps when moving between: - Raff Functions - Raff VM - Docker containers - Kubernetes jobs - local development - another function platform The internal wrapper can change. The business workflow stays readable. For a small team, this is not overengineering. It is a lightweight boundary that keeps migrations possible. ## Lock-in is not always bad, but it should be intentional Not every provider-specific feature is a mistake. Sometimes the best decision is to use the platform feature because it saves time, improves reliability, or gives a capability the team would not build itself. Provider-specific code may be acceptable when: - The function is small and temporary - The feature saves significant engineering time - The team has no realistic migration need - The workload is internal only - The provider feature is central to the product - The lock-in is documented and accepted - The code is isolated enough to replace later The problem is accidental lock-in. Accidental lock-in happens when a team writes code quickly without noticing that the function now depends on one provider's event structure, response shape, secret model, deployment workflow, and logs. A useful decision: ```text If lock-in saves time, document it. If lock-in touches business logic, isolate it. If lock-in is accidental, remove it early. ``` Portability is not an ideology. It is a risk control. ## Raff's portable-handler model Raff Functions is built around standard handlers rather than a Raff-specific function signature. ![Runtime map showing Raff Functions supporting standard handlers and portable deployment paths](https://raff-images.s3.raffusercloud.com/raff_functions_portable_runtime_map_webp_51749ac122.png) Supported patterns include: - Python FastAPI / ASGI - Node.js standard `http` - TypeScript - JavaScript Web Fetch - Go `net/http` - Dockerfile for other languages or custom runtimes That matters because the same application patterns are familiar outside the functions platform. A Python FastAPI handler can be easier to run locally. A Node `http` handler is a standard server shape. A Web Fetch handler follows a common request/response model. A Go `net/http` handler maps to normal Go server code. A Dockerfile escape hatch means the team is not blocked if the runtime needs something custom. Raff also supports importing AWS Lambda functions and converting them toward a cleaner, portable handler with a reviewable diff. That is useful when the team already has Lambda code but wants to reduce proprietary handler dependency over time. The goal is not to pretend all platforms are identical. The goal is to keep your function code close to standard application code. ## What a portable function structure looks like A portable function should separate four concerns: 1. Handler 2. Business logic 3. Data access 4. Platform bindings Example structure: ```text functions/ billing-webhook/ main.py service.py database.py storage.py README.md ``` The files have different jobs: | File | Responsibility | |---|---| | `main.py` | HTTP route or function entry | | `service.py` | Business logic | | `database.py` | Durable state access | | `storage.py` | File/artifact access | | `README.md` | Required env vars, triggers, timeout, owner | The handler should stay thin: ```text Receive request ↓ Validate input ↓ Call service function ↓ Return response ``` The service should not know whether it is running on Raff Functions, a VM, or a container. It should receive normal inputs and return normal outputs. That structure makes the function easier to test and easier to move. ## Portable handlers make local testing easier Local testing is one of the most practical benefits of portability. A function written as normal HTTP code can often be tested with: - curl - browser requests - Postman - normal unit tests - framework test clients - Docker - local environment variables A function tied to a proprietary event object often needs mock event JSON, context objects, and provider-specific local emulation. That extra complexity slows development. A portable test path looks like this: ```text Run handler locally ↓ Send normal HTTP request ↓ Assert response ↓ Test business logic separately ``` This is especially useful for: - Webhooks - API endpoints - form handlers - image processors - report generators - scheduled jobs with explicit inputs - file-processing functions A small team should not need a full cloud emulator to test simple business logic. ## Portability helps VM and Kubernetes migration later Some functions should stay functions. Others may move later. A webhook might start as a function, then become part of the main app. A batch function might grow into a worker VM. A file processor might later run as a Kubernetes job. A small API might become a full service. Portable handlers make those changes easier. A migration path might look like this: ```text Raff Function ↓ Docker container ↓ Raff VM ↓ Kubernetes workload ``` or: ```text Raff VM route ↓ Raff Function ↓ Worker VM ``` The direction can change. What matters is whether the code is trapped in one platform model. If the function's core logic is just a normal module, the team can move the runtime without rewriting the product behavior. For broader infrastructure decisions, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) and [Kubernetes vs Docker Compose for Small Teams](/learn/guides/kubernetes-vs-docker-compose-small-teams). ## Trigger portability needs extra care HTTP handlers are the easiest to make portable. Non-HTTP triggers need more care. Common trigger types include: - Cron schedules - Object storage events - One-off future runs - Queue events - Webhooks - Database events - Internal events A portable trigger design should define a normal input shape for business logic. For example, an object storage event can be converted into: ```json { "bucket": "uploads", "key": "incoming/report.csv", "account_id": "acct_123" } ``` Then the service function can process that object without knowing the original provider event shape. A cron job can pass a simple input: ```json { "job_name": "daily-report", "run_date": "2026-07-20" } ``` A one-off job can pass: ```json { "job_id": "job_123", "input_uri": "s3://bucket/input.csv" } ``` The platform event can be different. The internal job input should be stable. This is the difference between portable business logic and provider-dependent glue. ## Database and storage bindings should stay narrow Functions often need access to databases and object storage. That access should be narrow and explicit. A portable function should not depend on one giant credential that gives broad access to everything. It should define exactly what it needs: - Which database - Which schema or table - Which object storage bucket - Which prefix - Which read/write permissions - Which API token - Which environment variables - Which tenant or account scope Raff Functions can bind to Raff Managed Databases with scoped per-function credentials and to Raff Object Storage with scoped S3 keys per bucket. That helps reduce the blast radius of each function. But portability still depends on how the application code uses those bindings. Good pattern: ```text Function reads DATABASE_URL and STORAGE_BUCKET Business logic calls database.py and storage.py Credentials stay outside code ``` Bad pattern: ```text Business logic depends on provider-specific binding object everywhere ``` Use the platform binding to inject access. Use your own small module to keep the code clean. ## Observability should be portable enough to understand Logs and metrics are part of the function's operating model. Raff Functions includes logs and metrics for every invocation, including live log tail, search and level filters, 14-day retention, count, p50, p95, and error rate per function. That is useful, but the log content should still be understandable outside one platform. Use structured, safe log messages: ```text webhook_received provider=stripe event_id=evt_123 job_started job_id=job_456 type=image_resize job_completed job_id=job_456 duration_ms=842 job_failed job_id=job_456 reason=object_not_found ``` Avoid logs that only make sense inside one provider's context object. Good logs should help the team debug the function whether it runs on Raff Functions, a VM, or another runtime. Log the business event, not only the platform event. ## A practical portability checklist Use this checklist before shipping a production serverless function. - [ ] The handler uses a standard framework or standard HTTP shape where possible. - [ ] Provider-specific event parsing is isolated in a thin adapter. - [ ] Business logic lives outside the handler file. - [ ] Database access is wrapped in a small module. - [ ] Object storage access is wrapped in a small module. - [ ] Environment variables are documented. - [ ] Secrets are not hardcoded. - [ ] The function can run locally with documented inputs. - [ ] Required memory and timeout are recorded. - [ ] Trigger type and schedule are documented. - [ ] Logs use safe business identifiers. - [ ] The function does not require a proprietary SDK in core logic. - [ ] Output files go to object storage. - [ ] Durable state goes to a database. - [ ] Provider-specific features are documented if used. - [ ] Migration assumptions are clear. - [ ] The team knows when to move the workload to a VM or Kubernetes. The checklist is not about making every function cloud-agnostic forever. It is about avoiding unnecessary rewrites. ## Common mistakes to avoid ### Putting business logic inside a proprietary handler A provider event object should not shape the whole codebase. Parse the event at the edge, then call portable business logic. ### Depending on a provider SDK everywhere SDKs are fine at the boundary. Do not scatter provider-specific calls across the entire workflow. ### Hiding configuration in the dashboard Environment variables, secrets, memory, timeout, and triggers should be documented in the repository. ### Making local testing too hard If a simple webhook or API handler requires a full cloud emulator to test, the function may be too tightly coupled. ### Assuming portability means no platform features Portability does not mean refusing useful features. Use platform features intentionally and isolate them when possible. ### Forgetting data portability Code is not the only lock-in. Data, files, logs, secrets, and deployment workflow also affect portability. ### Splitting too early Do not turn one simple function into too many abstraction layers. Use simple boundaries: handler, service, database, storage, configuration. ## Portable handlers keep future options open Serverless is most useful when it makes work easier to run, not when it traps the team inside one provider's event model. Use portable handlers for webhooks, small APIs, cron jobs, storage events, and batch tasks when the function may grow, move, or become business-critical. Keep provider-specific code at the edge. Keep business logic in normal modules. Store durable state in a database and files in object storage. Document configuration, triggers, timeouts, and secrets. For Raff teams, the natural pattern is to use [Raff Functions](/products/serverless-functions) for standard handlers, [Raff VM](/products/raff-vm) when the workload needs a full server, [Raff Managed Databases](/products/managed-databases) for durable records, and [Raff Object Storage](/products/object-storage) for files and artifacts. That gives the team flexibility without sacrificing a clean production operating model. :::cta Explore Raff Functions Deploy standard serverless handlers on Raff Functions without learning a proprietary function format. ::: --- ### Object Storage Events on Serverless Functions: File Processing Without Workers URL: https://rafftechnologies.com/learn/guides/object-storage-events-serverless-functions-file-processing Description: Learn how to use object storage events with serverless functions for upload processing, prefix filters, retries, status tracking, and Raff workflows. That matters for SaaS teams because file work often begins as a simple app-server feature and later becomes production pressure. A user uploads a CSV, image, PDF, export, backup, or document. The app needs to validate it, resize it, convert it, scan it, extract metadata, create a thumbnail, update a database record, or trigger a downstream workflow. If all of that work runs inside the main app server, uploads can slow the product down. Raff Technologies gives teams a cleaner path with [Raff Functions](/products/serverless-functions): one standard handler can be wired to HTTP, cron, one-off runs, or object-storage events such as bucket uploads with prefix filters. [Raff Object Storage](/products/object-storage) can store the input and output files, while [Raff Managed Databases](/products/managed-databases) can store metadata, job status, and durable records. This guide explains when to use object storage events with serverless functions, when a VM worker is still better, and how to design file-processing workflows that are retryable, observable, and safe for production. If you are still deciding where uploads should live, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage) first. ## File uploads should not overload the app server File uploads often look harmless at the beginning. ![Architecture diagram showing object storage uploads triggering Raff Functions with database status and processed output](https://raff-images.s3.raffusercloud.com/object_storage_event_function_processing_flow_37d779fbe7.png) A small app lets users upload: - Profile images - Attachments - CSV imports - PDFs - Reports - Product images - Documents - Audio or video files - Backup archives - Data exports - Signed files - Generated artifacts Then the app starts doing work after each upload: - Validate file type - Read metadata - Resize images - Generate thumbnails - Convert formats - Parse CSV rows - Extract text - Scan or classify content - Create previews - Update database records - Send notifications - Trigger imports - Write processed output That work can compete with the customer-facing app for CPU, memory, disk, and database connections. A safer production pattern is: ```text User upload ↓ Object Storage ↓ Storage event ↓ Raff Function ↓ Processed output + database metadata ``` The app handles user flow. Object storage holds files. The function handles file work. The database records status and metadata. This keeps upload processing out of the main request path. ## The quick decision framework Use this table before deciding between object-storage events, VM workers, app-server processing, or Kubernetes jobs. | File workflow | Better default | Why | |---|---|---| | Image thumbnail generation | Object storage event + function | Event-driven and bounded | | CSV import after upload | Function or worker VM | Depends on file size and duration | | PDF metadata extraction | Function | File-driven and isolated | | Large video processing | VM or Kubernetes worker | Heavy runtime and long processing may need full environment | | Small file validation | Function | Quick and independent | | Virus scanning | Function or VM worker | Depends on tooling and runtime | | Customer export generation | Function or worker VM | Depends on duration and frequency | | Backup archive validation | Function | Triggered by new object | | Continuous file pipeline | VM or Kubernetes | Always-on processing may fit workers | | File task needs SSH debugging | VM | Full server control helps | | File task needs custom binaries | Dockerfile function or VM | Choose by dependency complexity | | File task writes many outputs | Function + object storage | Keep files out of compute | A useful rule: > Use object-storage events when the file is the trigger. Use a worker VM when the processing environment is the product. If a task starts because a file landed in a bucket, a function is often the cleanest first option. ## Object storage events are strongest for bounded file work Object-storage events work best when a file appears and a bounded task should run. Good candidates include: - Resize uploaded images - Generate thumbnails - Convert documents - Extract PDF metadata - Parse uploaded CSV files - Validate file schema - Check file size and MIME type - Create report previews - Store import status - Move files from incoming to processed - Notify users when processing finishes - Update search metadata - Trigger a follow-up workflow A function can receive an event, read the uploaded object, process it, write output back to object storage, and update the database. Example: ```text incoming/avatar.png ↓ Raff Function starts ↓ Create 128px, 512px, and 1024px versions ↓ Write outputs to processed/avatars/ ↓ Update database with image paths ``` That design is easier to scale than doing image processing inside the web request. The user upload can finish quickly, and the app can show a processing state until the function completes. :::cta Explore Raff Functions Use Raff Functions for object-storage events that should process files without slowing your main app server. ::: ## Prefix filters prevent accidental loops Prefix filters are important for file-processing workflows. ![Diagram showing object storage prefix filters with incoming processed failed and archive folders to prevent function trigger loops](https://raff-images.s3.raffusercloud.com/object_storage_prefix_filter_workflow_b492e76ec2.png) Without a prefix filter, a function may trigger on every object in a bucket. That can cause accidental loops. For example, the function reads an uploaded image and writes a thumbnail. If the thumbnail lands in the same bucket and also triggers the function, the function may process its own output. A safer pattern uses prefixes: ```text incoming/ processed/ failed/ archive/ ``` For example: ```text incoming/customer-file.csv ↓ triggers function processed/customer-file-normalized.csv ↓ does not trigger same function ``` A prefix-based design can separate file stages: | Prefix | Purpose | |---|---| | `incoming/` | New user uploads | | `processing/` | Optional temporary work area | | `processed/` | Completed outputs | | `failed/` | Failed or quarantined inputs | | `archive/` | Long-term storage | | `exports/` | Generated files for download | | `thumbs/` | Generated image variants | Raff Functions supports object-storage events such as bucket uploads with prefix filters. Use that feature to make event scope explicit. Do not let output files retrigger the same workflow unless that behavior is intentional. ## Store job status in a database An object-storage event tells you a file arrived. It does not replace application state. A file-processing workflow should store status in a database so the app can show progress and recover from failures. A simple status model: | Field | Purpose | |---|---| | file_id | Internal file record | | account_id | Tenant or customer owner | | input_key | Original object path | | output_key | Processed output path | | status | uploaded, processing, processed, failed | | attempts | Retry count | | error_message | Safe failure summary | | metadata | Size, type, row count, image dimensions | | created_at | Upload time | | processed_at | Completion time | A clean flow: ```text Upload starts ↓ App creates database record ↓ File lands in object storage ↓ Function processes event ↓ Function updates database record ``` The app should not depend only on whether a file exists in a bucket. It should have a durable record that explains the file's current state. This is especially important for SaaS apps with tenants, permissions, billing, imports, compliance, or customer-visible processing status. ## Make file processing idempotent Object-storage events can be delivered more than once. Users can upload the same file twice. A function can fail halfway through and retry. A developer can manually replay a job. File-processing functions must be idempotent. That means the same file event can run more than once without corrupting data or creating duplicate outputs. Use these techniques: | Technique | Use | |---|---| | File ID | Track each upload | | Object key | Identify input path | | Content hash | Detect repeated content | | Status transitions | Avoid reprocessing completed files | | Output key versioning | Prevent overwriting the wrong output | | Database constraints | Prevent duplicate records | | Attempt counter | Limit retry loops | | Processing lock | Prevent concurrent processing | | Failed prefix | Separate files that need review | Example: ```text if file.status == "processed": return success else: process file and update status ``` This is better than assuming every event is unique. Idempotency is not only a backend concern. It protects users from duplicate imports, duplicate notifications, duplicate invoices, or broken file state. ## Return durable outputs to object storage The function runtime should not be the final home for generated files. Use object storage for: - Thumbnails - Converted files - CSV exports - Report PDFs - Processed images - Import result files - Validation reports - Transformed documents - Batch artifacts - Generated archives A good output pattern: ```text incoming/report.csv ↓ processed/report-normalized.csv ↓ database output_key = processed/report-normalized.csv ``` The database stores metadata and object keys. Object storage stores the actual files. This keeps compute stateless and makes retries safer. If a function fails, the app can inspect the database status and object storage paths to decide what happened. For broader storage design, read [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk). ## When a VM worker is still better Not every file-processing job should be a function. Use a VM worker when the processing environment matters more than the event trigger. ![Decision diagram comparing Raff Functions and Raff VM workers for object storage file processing](https://raff-images.s3.raffusercloud.com/object_storage_functions_vs_worker_vm_decision_95d329face.png) A [Raff VM](/products/raff-vm) may be better when the workflow needs: - SSH debugging - Large system packages - Persistent local cache - Long-running workers - Constant queue processing - Heavy CPU all day - Several coordinated processes - Large local temporary storage - Manual inspection during incidents - Custom binaries or complex toolchains - Existing Docker Compose services - Stateful processing environment - Predictable capacity-based cost A VM worker pattern: ```text Object Storage ↓ Queue or database job table ↓ Worker VM ↓ Object Storage + database update ``` This is useful for continuous pipelines, large media processing, or workloads where developers need direct server access. A function is best when the job starts and ends cleanly. A VM worker is best when the processing environment must stay alive. :::cta Deploy a Raff VM Use Raff VM when file processing needs SSH debugging, custom binaries, persistent services, or always-on worker capacity. ::: ## Long-running file jobs need extra design Some file tasks take longer than expected. Examples: - Large CSV imports - AI document processing - Multi-page PDF conversion - Large report generation - Video or audio conversion - Many image variants - Large archive validation - Customer data migration Raff Functions supports timeouts up to 1 hour by default and up to 24 hours on request, which makes longer file jobs possible as functions. But long-running file jobs still need guardrails: - Job status in database - Progress markers - Retry limits - Idempotent output paths - Chunking for large inputs - Safe failure messages - Logs at each stage - Spend cap review - Clear owner - Manual replay path If restarting from zero would be painful, split the work into chunks. Example: ```text large-import.csv ↓ Function validates file ↓ Create chunk jobs ↓ Process chunks ↓ Write result summary ``` For deeper long-running design, read [Long-Running Serverless Functions for AI, ETL, and Batch Jobs](/learn/guides/long-running-serverless-functions-ai-etl-batch). ## Logs and metrics make file events trustworthy File events can fail in quiet ways. A file may upload successfully, but processing may fail. A function may write output but fail to update the database. A bad file may retry repeatedly. A user may wait for an import that never completes. A file-processing function should log: - File ID - Account or tenant ID - Input object key - File size - Detected file type - Processing stage - Output object key - Row count or image dimensions - Validation errors - Retry attempt - Completion status - Safe failure reason Example log shape: ```text file_event_received file_id=file_123 key=incoming/report.csv file_validation_passed file_id=file_123 size_mb=12 file_processing_started file_id=file_123 file_output_written file_id=file_123 output_key=processed/report.csv file_processing_completed file_id=file_123 duration_ms=8421 ``` Raff Functions includes logs and metrics for every invocation, with live log tail, search and level filters, 14-day retention, count, p50, p95, and error rate per function. Use logs to explain the workflow without exposing sensitive file content. ## Security and tenant boundaries matter File uploads often contain sensitive data. A file-processing function should not have broad access to every bucket, every prefix, or every database table unless there is a clear reason. Use scoped access: - Only required bucket - Only required prefix - Separate input and output paths - Narrow database permissions - Tenant-aware file records - Safe logs - Secrets outside code - Validation before processing - Access checks before user download Raff Functions can bind to Raff Object Storage with scoped S3 keys per bucket and Raff Managed Databases with scoped per-function credentials. Use those scoped bindings to limit each function's access. For SaaS apps, also check tenant boundaries: - Does the file record belong to the right account? - Is the output path tenant-specific? - Can one tenant guess another tenant's file key? - Does the app authorize downloads through database metadata? - Are temporary files cleaned up? - Are failed files quarantined? A function should not process a file only because the object exists. It should confirm that the file belongs to the expected account and workflow. ## Cost planning for object-storage events Object-storage event cost depends on how often files arrive and how expensive processing is. Estimate: - Uploads per month - Average file size - Average processing duration - Memory setting - Active CPU behavior - Retry frequency - Number of output files - Whether work can be chunked - Whether processing is CPU-heavy or I/O-heavy - Whether large files should use a VM worker Raff Functions bills memory and active CPU. Requests and egress are free for functions. Raff Object Storage has its own storage and egress pricing, so file retention and download patterns still matter. A function can be cost-effective for bursty file events. A VM worker may be easier to forecast if processing runs constantly. A practical rule: | Workload shape | Cost-friendly model | |---|---| | Occasional uploads | Function | | Bursty file events | Function with spend cap | | Short processing | Function | | Long but bounded processing | Long-running function | | Continuous file pipeline | VM or Kubernetes worker | | Heavy media processing all day | VM or Kubernetes worker | | Large durable file storage | Object Storage | For the function cost model, read [Serverless Function Pricing: CPU, Memory, Requests, and Egress](/learn/guides/serverless-function-pricing-cpu-memory-egress). :::cta View Raff Pricing Compare Raff Functions and Object Storage pricing before building file-processing workflows. ::: ## A practical Raff object-event architecture A clean Raff architecture separates upload, processing, state, and output. ```text User or system uploads file ↓ Raff Object Storage incoming/ prefix ↓ Raff Function triggered by storage event ↓ Raff Managed Database updates status and metadata ↓ Raff Object Storage processed/ prefix stores output ↓ App notifies user or shows result ``` Each layer has a clear job: | Layer | Responsibility | |---|---| | App | User upload flow, authorization, status UI | | Object Storage | Input files, outputs, artifacts, archives | | Raff Function | Validation, processing, conversion, metadata extraction | | Managed Database | File records, job status, tenant ownership, output paths | | Worker VM | Optional always-on processing for heavy or constant workloads | | Logs and metrics | Visibility into success, duration, errors, and retries | This pattern works for: - SaaS app uploads - CSV imports - image processing - PDF processing - report generation - document automation - backup validation - media workflows - data enrichment - internal file pipelines Start with the simplest event-driven path. Add queues, worker VMs, or Kubernetes when the workflow becomes continuous or coordination-heavy. ## Object-storage event checklist Before launching a production file-processing function, check: - [ ] The input bucket and prefix are defined. - [ ] The output prefix is separate from the input prefix. - [ ] The function cannot accidentally process its own output. - [ ] The app creates a database file record. - [ ] The function updates status and metadata. - [ ] File type and size are validated. - [ ] Tenant ownership is checked. - [ ] Duplicate events are handled safely. - [ ] The function is idempotent. - [ ] Retry behavior is defined. - [ ] Failed files have a status or prefix. - [ ] Logs include file ID, key, stage, and result. - [ ] Logs do not expose sensitive file content. - [ ] Credentials are scoped to the required bucket or prefix. - [ ] Large jobs have chunking or progress markers. - [ ] Cost is estimated before launch. - [ ] The team knows when to use a worker VM instead. This checklist prevents file-processing functions from becoming hidden production risk. ## Common mistakes to avoid ### Triggering on every object in a bucket Use prefix filters. Do not let processed outputs retrigger the same function by accident. ### Processing files inside the web request User uploads should not wait for heavy processing. Upload the file, create a record, trigger processing, and show status. ### Storing outputs only in the function runtime Generated files should go back to object storage. The database should store metadata and output paths. ### Ignoring duplicate events Storage events can repeat. Use file IDs, object keys, hashes, and database status to prevent duplicate processing. ### Giving the function broad storage access Scope credentials to the required bucket or prefix. A file processor should not have access to unrelated storage. ### Skipping tenant ownership checks A SaaS app should confirm that a file belongs to the expected tenant before processing or exposing results. ### Using functions for constant heavy processing without checking cost If the pipeline runs all day, a worker VM or Kubernetes job may be cleaner and easier to forecast. ## File events should turn uploads into workflows Object-storage events are useful because they turn a file upload into a clear workflow. Use [Raff Functions](/products/serverless-functions) when file processing is event-driven, bounded, isolated, and should not slow the main app server. Use [Raff Object Storage](/products/object-storage) for input files, outputs, artifacts, and archives. Use [Raff Managed Databases](/products/managed-databases) for file records, tenant ownership, status, metadata, and output paths. Use [Raff VM](/products/raff-vm) when file processing needs a persistent worker, SSH debugging, custom binaries, or always-on capacity. The safest Raff pattern is simple: uploads land in object storage, a function processes the event, the database records state, and outputs go back to object storage. That keeps file workflows clean, observable, and easier to scale without overloading the app server. :::cta Explore Raff Functions Use Raff Functions with Object Storage events to process uploads, files, and artifacts outside your main app server. ::: --- ### Storage and Recovery Architecture for Production Apps URL: https://rafftechnologies.com/learn/guides/storage-recovery-architecture-production-apps Description: Learn how to design production app storage and recovery with VM disks, volumes, object storage, backups, and restore testing. Storage and recovery architecture is the way a production app separates runtime, persistent data, durable files, backups, and restore paths before something fails. For small teams, this matters because storage decisions often happen accidentally. The first VM holds the app, the database, user uploads, generated reports, logs, backup exports, and temporary files. That can work at the beginning, but it creates risk as the product grows. A full disk can bring down the app. A bad deployment can mix runtime failure with data recovery. A missing restore path can turn a simple incident into long downtime. Raff Technologies gives teams separate building blocks for this problem: [Raff VM](/products/raff-vm) for compute and app runtime, [Raff Volumes](/products/volumes) for disk-like persistent storage, [Raff Object Storage](/products/object-storage) for durable file objects, and [Raff Data Protection](/products/data-protection) for snapshots, automated backups, retention, and recovery workflows. This guide is intentionally architectural. It is not a generic block storage explainer, a backup definition article, or a step-by-step restore tutorial. It answers one practical question: **what should live where so a production app can grow and recover cleanly?** If you need the narrower storage decisions first, read [Block Storage Volumes for Databases, Containers, and App Data](/learn/guides/block-storage-volumes-databases-containers-app-data), [When to Add a Volume Instead of Resizing a VM Disk](/learn/guides/add-volume-vs-resize-vm-disk), and [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms). ## Production storage should be separated by responsibility A production app should not treat every byte as the same kind of data. The operating system, app runtime, database files, user uploads, generated reports, backup exports, logs, and temporary processing files all behave differently. A clean architecture separates storage by responsibility: ![Architecture diagram showing VM disk Raff Volumes Object Storage Data Protection and restore testing responsibilities](https://raff-images.s3.raffusercloud.com/production_storage_responsibility_map_webp_76b0f2f098.png) This separation makes the system easier to reason about. When something fails, the team can answer: - What failed? - What data is affected? - What is rebuildable? - What must be restored? - Which recovery point should be used? - Which storage layer owns the data? - What can be safely deleted? - What must be protected? The goal is not to add complexity. The goal is to avoid making one VM disk responsible for every production concern. A production app should separate runtime, persistent data, durable files, and recovery points before failure forces the decision. ## The quick architecture framework Use this table as the starting point. ![Decision matrix comparing VM disk block volumes object storage and data protection for production apps](https://raff-images.s3.raffusercloud.com/storage_decision_architecture_matrix_webp_9e0be0e171.png) | Workload or data type | Better default | Why | |---|---|---| | Operating system | VM disk | Part of the server runtime | | App packages and runtime | VM disk | Rebuildable with the server | | App configuration | VM disk or secret/config system | Must be documented and recoverable | | PostgreSQL or MySQL data directory | Managed database or block volume | Needs durable database storage | | Docker persistent data | Block volume | Needs filesystem persistence | | User uploads | Object storage | Should live outside the VM lifecycle | | Generated reports | Object storage | Durable file objects should be separate | | Media files | Object storage | Easier to retain and share | | Temporary processing workspace | VM disk or block volume | Depends on size and lifetime | | Backup exports | Object storage | Retained artifacts should not depend on the VM | | VM snapshots | Data protection | Short-term recovery points | | Automated backups | Data protection | Scheduled recovery history | | Restore evidence | Runbook and test notes | Proof that recovery works | A useful rule: > VM disk is for runtime. Volumes are for disk-like data. Object storage is for durable files. Backups are for recovery points. This rule is not perfect, but it prevents many early architecture mistakes. ## VM disk is for runtime, not everything The VM system disk should mostly support the server runtime. It usually holds: - Operating system - System packages - App runtime - Deployment files - Local service files - Some logs - Temporary files - Basic configuration That is a reasonable job for the VM disk. The problem begins when the VM disk also becomes the long-term home for: - Database data - User uploads - Media library - Backup archives - Generated reports - Persistent container data - Large imports - File-processing workspace - Long-term logs - Everything the app ever writes That mix creates recovery confusion. If the VM disk fails or needs to be restored, the team has to recover runtime and data together. If uploads grow quickly, the team may resize the whole VM. If logs fill the disk, the database may be affected. If the VM must be rebuilt, file migration becomes harder. Use the VM disk for what can be rebuilt or redeployed. A healthy VM disk model: ```text VM system disk ↓ OS Packages App runtime Service definitions Local logs with retention Temporary files with cleanup ``` A risky VM disk model: ```text VM system disk ↓ OS App runtime Database Uploads Reports Archives Logs forever Backups Temporary processing ``` The second model works until it suddenly does not. ## Block volumes are for disk-like persistent data Block storage volumes are useful when the workload needs disk behavior but should not live on the VM system disk. Common volume use cases include: - Database data directories - Docker persistent data - Self-hosted service data - App-generated local files - Processing workspace - Search index data - Stateful container directories - Media-processing scratch space - Development environment storage - Workload-specific persistent paths A volume gives the data a clearer boundary. ```text Raff VM ↓ System disk = OS and app runtime ↓ Raff Volume = database files, container state, app data, workspace ``` This helps when storage grows faster than compute. For example, a VM may still have enough CPU and RAM, but its database data may need more disk. Adding a volume can solve the storage problem without turning every disk issue into a VM sizing decision. A volume is especially useful when: - Data should be separated from the OS - Storage should grow independently from compute - A mount path should have a clear owner - Disk usage needs specific alerts - Snapshots should target a specific data area - The team needs clearer restore planning - Containers need persistent state - A self-hosted database needs a dedicated data directory A volume is not a dumping ground. It should have a purpose, mount path, owner, and recovery policy. :::cta Explore Volumes Use Raff Volumes when production data needs disk-like persistent storage that can grow separately from compute. ::: ## Object storage is for durable file objects Object storage is usually the better home for files that should not depend on one VM. Use object storage for: - User uploads - Product images - Profile images - Documents - PDFs - Generated reports - Export files - Import files - Media files - Backup archives - Static assets - Artifacts - Files accessed by workers or functions A common production pattern: ```text App VM ↓ Managed Database stores metadata ↓ Object Storage stores files ``` The database stores records, permissions, and object keys. Object storage stores the actual files. This avoids turning the app server into a long-term file server. Object storage is usually better when files need to: - Survive VM rebuilds - Be shared across services - Be retained independently - Be accessed by workers or functions - Avoid filling the system disk - Scale beyond one app server - Store archives or generated artifacts A volume can still help with temporary file processing. Example: ```text Object Storage input ↓ Worker VM with attached volume for processing ↓ Object Storage output ↓ Database metadata ``` Use object storage for durable files. Use volumes for active disk-like work. For the upload decision, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## Managed databases can remove storage operations Not every database should be self-hosted on a VM and volume. A self-hosted database gives the team control, but it also gives the team operational responsibility. The team must plan: - Disk layout - Backups - Restore testing - Replication - Upgrades - Monitoring - Connection limits - Storage growth - Failure recovery - Security and access controls A managed database can move much of that operational burden away from the app VM. A practical decision: ```text Need maximum database control? ↓ Self-host on VM with dedicated volume Want less database operations work? ↓ Use managed database ``` For many small teams, [Raff Managed Databases](/products/managed-databases) may be the cleaner default once the application handles real users. A volume-based database is not wrong. It just needs an owner and a recovery plan. For the detailed decision, read [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases). ## Snapshots and backups are recovery points, not architecture Snapshots and backups are part of recovery architecture, but they are not the whole architecture. A snapshot can help recover from a bad change. A backup can provide scheduled recovery history. Object storage archives can retain exported files or database backups. But none of those alone tells the team what data belongs where or how to restore the service. A clean model: ```text Storage architecture ↓ Defines what lives where Data protection ↓ Creates recovery points Restore testing ↓ Proves those recovery points work ``` Use snapshots for: - Pre-deploy recovery points - Pre-migration recovery points - Short-term rollback - Risky configuration changes - Fast operational recovery Use backups for: - Scheduled recovery history - Longer retention - Disaster recovery - Production safety - Recovering from deletion or corruption Use object storage archives for: - Exported database backups - Retained reports - Backup artifacts - Compliance-style archives - Files that should live outside the VM Raff Data Protection supports snapshots, automated backups, retention options, replicated storage, and recovery workflows. Use it as part of a full recovery plan, not as a substitute for storage design. :::cta Explore Data Protection Protect production VMs with snapshots, automated backups, retention policies, and recovery workflows. ::: ## Restore testing proves the architecture works A backup strategy is incomplete until restore has been tested. The team should know whether it can restore: - VM boot - SSH access - App service - Database state - Attached volumes - Object storage access - Firewall rules - Private network routes - DNS or test hostname - Secrets and credentials - Logs and monitoring - Cleanup path A tested restore answers the question: ```text Can we get this app back into a usable state? ``` That is different from asking whether a snapshot or backup exists. A restore test should usually happen in an isolated temporary environment: ```text Production VM ↓ Snapshot or backup ↓ Temporary restore VM ↓ Private verification ↓ Document result ↓ Delete test resources ``` This protects production while proving the recovery path. For the detailed checklist, read [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms). ## Example architecture for a small SaaS app A simple SaaS app often needs four storage layers. ```text Raff VM ↓ App runtime and API server Managed Database ↓ Users, accounts, records, billing state Object Storage ↓ Uploads, reports, exports, attachments Data Protection ↓ Snapshots, backups, restore testing ``` This is a clean architecture because each layer has a clear job. The VM runs the app. The database stores records. Object storage stores files. Data protection creates recovery points. Restore testing proves the path back. This is usually better than: ```text One VM disk ↓ App + database + uploads + reports + backups + logs ``` That single-disk model is simple at first, but it creates scaling and recovery problems later. A SaaS team should move uploads and generated files out of the VM disk early. The database should either be managed or clearly separated. The app server should remain replaceable. ## Example architecture for a Docker app A Docker app needs extra care because containers are easy to recreate. A practical Docker layout: ```text Raff VM ↓ Docker Compose runtime Raff Volume ↓ Persistent container data Object Storage ↓ Uploads, reports, media files Data Protection ↓ Snapshots, backups, restore tests ``` Use a volume when containers need persistent filesystem data. Examples: - Database container data - Self-hosted app data - Plugin state - Search index data - Queue state - Stateful service directories Use object storage when files should not depend on the container host. Examples: - User uploads - Reports - Exports - Media - Backup archives A Docker app can be simple, but storage must be intentional. Rebuilding containers should not delete important data. ## Example architecture for a database-heavy app A database-heavy app has stricter recovery needs. A self-hosted database model: ```text Raff VM ↓ Database service Raff Volume ↓ Database data directory Data Protection ↓ Snapshots around risky changes Database backups ↓ Exported backups retained separately ``` This model can work when the team wants database control. But the team must still handle: - Database-aware backups - Restore testing - Disk usage alerts - Replication if needed - Upgrade planning - Corruption recovery - Access controls - Retention rules A managed database model: ```text Raff VM ↓ App runtime Managed Database ↓ Database records and operations Object Storage ↓ Backup exports or data artifacts where needed ``` This model is often cleaner when the team wants less database operations work. Use volume-based databases for control. Use managed databases for operational simplicity. ## Example architecture for an upload-heavy app Upload-heavy apps should not keep user files on the VM disk for long. A cleaner model: ```text User upload ↓ App VM validates request ↓ Object Storage stores file ↓ Managed Database stores metadata and permissions ↓ Worker or function processes file if needed ``` This helps when the app has: - Images - PDFs - CSV files - Customer documents - Report exports - Audio or video - Backups or generated artifacts If files need processing, use temporary compute and write the final output back to object storage. ```text Object Storage input ↓ Raff Function or worker VM ↓ Temporary processing space ↓ Object Storage output ↓ Database status update ``` This keeps durable files outside the VM lifecycle. For file-triggered workflows, read [Object Storage Events on Serverless Functions: File Processing Without Workers](/learn/guides/object-storage-events-serverless-functions-file-processing). ## Example architecture for a worker-heavy app Some apps depend on background workers. ![Raff production recovery architecture showing VM Managed Database Volumes Object Storage Data Protection and restore testing](https://raff-images.s3.raffusercloud.com/raff_production_recovery_architecture_webp_2be55f919c.png) Examples: - Queue workers - Report generators - Media processors - Import processors - AI or ETL jobs - Scheduled jobs - Webhook processors - File conversion tasks A worker-heavy architecture might look like this: ```text App VM ↓ Receives user requests Database or queue ↓ Stores work state Worker VM or Raff Function ↓ Processes jobs Raff Volume ↓ Temporary disk-like workspace when needed Object Storage ↓ Inputs, outputs, archives Data Protection ↓ Recovery points and restore testing ``` Use functions when jobs are event-driven and bounded. Use worker VMs when the processing environment needs persistent services, custom binaries, SSH debugging, or always-on capacity. Storage should follow the job. If the job needs temporary disk, use a volume. If the job creates durable files, use object storage. If the job updates records, use the database. ## Cost planning should include recovery cost Storage cost is not only active disk size. A production architecture should include: - VM disk - Attached volumes - Object storage - Snapshots - Backups - Backup retention - Restore test resources - Temporary processing storage - Database storage - Logs and monitoring - Engineering time A cheap layout can become expensive during an incident. For example: ```text Low monthly cost: Everything on one VM disk Possible incident cost: Long restore time Unclear data ownership Mixed app and database recovery Large backup size Manual file recovery Customer downtime ``` A better cost question: ```text What does it cost to recover this app? ``` Sometimes the cleaner architecture costs a little more each month but reduces operational risk. Sometimes a simple single-VM layout is enough for an early product. The decision should be intentional. ## Storage and recovery checklist Use this checklist before calling an app production-ready. ### Runtime - [ ] VM disk is mostly OS, packages, app runtime, and controlled logs. - [ ] App deployment can be repeated. - [ ] Service startup is documented. - [ ] Secrets and configuration are recoverable. - [ ] Temporary files have cleanup rules. ### Persistent data - [ ] Database storage location is clear. - [ ] Container data location is clear. - [ ] Volumes have owners and mount paths. - [ ] Disk usage alerts are planned. - [ ] Data growth is estimated. - [ ] Unused volumes are deleted. ### Files and objects - [ ] User uploads are not trapped on the VM disk. - [ ] Reports, exports, and media have clear storage. - [ ] Object storage keys are stored in the database where needed. - [ ] File permissions are enforced by the app. - [ ] Backup archives are stored outside the VM when needed. ### Protection - [ ] Snapshot policy is defined. - [ ] Backup policy is defined. - [ ] Retention policy is defined. - [ ] Database-aware backups are planned. - [ ] Object storage archives are retained where needed. - [ ] Critical recovery points are named clearly. ### Recovery - [ ] Restore objective is documented. - [ ] RPO and RTO targets are understood. - [ ] Restore test has been performed. - [ ] App health was verified after restore. - [ ] Database state was verified after restore. - [ ] Object storage access was verified after restore. - [ ] Network access was verified after restore. - [ ] Restore timing was recorded. - [ ] Runbook was updated. ## Common mistakes to avoid ### Putting everything on the VM disk This is simple at first, but it mixes runtime, data, files, logs, and recovery into one place. Separate data when growth or recovery matters. ### Using volumes for uploads by default User uploads are usually better in object storage. Use volumes when the workload needs disk behavior. ### Treating snapshots as architecture Snapshots create recovery points. They do not decide what should live on the VM disk, volume, or object storage. ### Forgetting database-aware backups A VM-level recovery point may not be enough for database recovery. Production databases need database-aware backup planning. ### Never testing restores A backup that has never been restored is an assumption. Restore testing turns the assumption into evidence. ### Keeping backup archives on the same VM If the VM fails, archives stored only on that VM may not help. Retained backup artifacts should often live outside the VM. ### Adding storage without ownership Every volume, bucket, backup, and restore path should have an owner. Unowned storage becomes forgotten infrastructure. ## Production architecture should be recoverable by design Storage architecture and recovery architecture should be designed together. Use [Raff VM](/products/raff-vm) for compute and runtime. Use [Raff Volumes](/products/volumes) when a workload needs disk-like persistent storage. Use [Raff Object Storage](/products/object-storage) for uploads, reports, media, backup archives, and durable file objects. Use [Raff Data Protection](/products/data-protection) for snapshots, automated backups, retention policies, and recovery workflows. Use restore testing to prove that those choices work together. The goal is not to build the most complex architecture. The goal is to make sure each layer has a clear job. When a production app fails, the team should not need to guess where the data lives, which backup matters, or how to bring the service back. A recoverable architecture is one the team can explain, test, and repeat. :::cta Explore Data Protection Use Raff Data Protection to protect production VMs with snapshots, automated backups, retention policies, and recovery workflows. ::: --- ### Reverse Proxy vs Load Balancer: Differences, Use Cases & Architecture URL: https://rafftechnologies.com/learn/guides/reverse-proxy-vs-load-balancer Description: Compare reverse proxies and load balancers across L4/L7 routing, TLS, health checks, failover, session state, scaling, and production architecture. A reverse proxy and a load balancer can sit in the same traffic path—and the same software can perform both roles—but they solve different architecture problems. **A reverse proxy controls how clients reach an application.** It commonly handles TLS termination, hostname and path routing, request headers, compression, caching, rate limits, and access policy before forwarding traffic to a backend. **A load balancer controls how traffic is distributed across a pool of backends.** It uses balancing rules and health information to send new requests or connections to suitable targets, remove unhealthy nodes from rotation, and support horizontal scaling or higher availability. The practical decision is usually: - **One application backend:** start with a reverse proxy. - **Two or more interchangeable backends:** add load balancing. - **A public edge plus a resilient backend pool:** use both roles, even if one product performs both. This guide explains the architectural difference, Layer 4 vs Layer 7 balancing, health checks, session state, client IP handling, deployment safety, and the point at which a Raff workload should move from a single reverse proxy to a load-balanced private architecture. ## Reverse proxy vs load balancer: quick decision table | Your requirement | Reverse proxy | Load balancer | Usually need both? | |---|---:|---:|---:| | Terminate HTTPS for one app server | Yes | Not required | No | | Route `api.example.com` and `app.example.com` to different services | Yes | Not required | No | | Route `/api` and `/admin` to different internal ports | Yes | Not required | No | | Apply request-size limits, headers, compression, or caching | Yes | Sometimes at Layer 7 | Usually no | | Spread traffic across two or more app servers | Can, if configured with an upstream pool | Yes | Often | | Stop sending traffic to an unhealthy backend | Basic or advanced support varies | Core function | Often | | Keep the service available during one app-node failure | Not with one backend | Yes, if healthy capacity remains | Often | | Balance raw TCP or UDP connections | Only with transport-layer support | Yes, with Layer 4 balancing | No edge proxy may be required | | Perform path-, host-, header-, or cookie-based routing | Yes | Yes at Layer 7 | Often one layer can perform both | | Run blue-green or rolling deployments across nodes | Limited with one backend | Yes | Often | | Hide databases and backend nodes from public access | Helps define the public edge | Helps expose one frontend for a backend pool | Yes, with private networking | The important point is that **reverse proxy** and **load balancer** describe roles. Nginx, HAProxy, Envoy, Caddy, Traefik, cloud load balancers, and application gateways may combine several of these responsibilities in one implementation. ## What a reverse proxy actually does A reverse proxy accepts traffic on behalf of one or more backend services. Clients connect to the proxy, not directly to the application process. A basic request path looks like this: ```text Client ↓ HTTPS Reverse proxy ↓ HTTP or HTTPS Application service ``` The reverse proxy becomes the application’s controlled front door. ### TLS termination The proxy can present the public certificate and decrypt incoming HTTPS traffic. Centralizing TLS reduces certificate handling inside every application process and creates one place to enforce protocol and cipher policy. TLS termination does not automatically mean backend traffic should be unencrypted. Re-encrypt traffic to the upstream when it crosses an untrusted network, when compliance requires encryption in transit, or when defense in depth matters. ### Hostname and path routing A reverse proxy can direct requests based on application-layer information: ```text api.example.com → API service app.example.com → frontend service example.com/admin → admin service example.com/assets → static service ``` This lets several internal services share a small number of public addresses while remaining isolated on private ports or private IPs. ### Header and request control The proxy can add, remove, or normalize headers; limit request sizes; enforce timeouts; and define how client connection information is passed upstream. This is operationally important because applications often rely on proxy-provided values for: - original client IP; - original protocol, such as HTTP or HTTPS; - requested hostname; - correlation or request IDs; - authentication context from an upstream identity layer. Only trust forwarding headers from proxies you control. Accepting `X-Forwarded-For`, `Forwarded`, or similar headers directly from arbitrary clients can produce false client identities and unreliable security logs. ### Compression, buffering, and caching A reverse proxy can compress responses, buffer slow clients, cache eligible content, and protect application workers from handling every network detail directly. These features can improve performance, but they require deliberate configuration. Caching personalized or authenticated responses incorrectly can expose data. Buffering and timeout choices can also affect streaming, file uploads, server-sent events, and long-running requests. ### Edge security controls Depending on the implementation, a reverse proxy may apply: - rate limiting; - IP allowlists or denylists; - authentication checks; - web application firewall rules; - request filtering; - bot or abuse controls; - security headers. A reverse proxy reduces direct backend exposure, but it does not make the application secure by itself. Application authentication, patching, firewall policy, secrets management, and monitoring still matter. ## What a load balancer actually does A load balancer distributes requests or connections across multiple backend targets that provide the same service. A basic multi-node path looks like this: ```text Client ↓ Load balancer ├── App VM 1 ├── App VM 2 └── App VM 3 ``` The backend pool should contain nodes that can safely serve the same type of traffic. The load balancer cannot make incompatible or state-dependent servers interchangeable without help from the application architecture. ### Capacity distribution A load balancer prevents all traffic from being sent to one node while other healthy nodes sit idle. This makes horizontal scaling practical: instead of only increasing CPU and RAM on one VM, you can add more application nodes and distribute traffic across them. This does not mean horizontal scaling is always the first answer. A single right-sized VM is often simpler and more economical. Add a load balancer when availability, deployment safety, or sustained capacity justifies the extra layer—not because a multi-node diagram looks more advanced. ### Health-aware routing A useful load balancer distinguishes between registered backends and backends that are actually ready to serve traffic. Health checks may be: - **Passive:** infer failure from real connection errors, timeouts, or bad responses. - **Active:** send dedicated probes to a health endpoint or service port. A shallow check may confirm only that a port is open. A deeper application check can verify that the process is responsive and critical dependencies are available. Avoid making health checks too shallow or too strict: - A check that always returns `200 OK` may keep a broken node in rotation. - A check that fails whenever a noncritical dependency is slow may remove every node at once. - A check that performs expensive database work can create its own load problem. Use a readiness check that answers: **Can this node safely receive new traffic now?** ### Failover and failure isolation When one backend fails, the load balancer can stop selecting it and continue using healthy capacity. This reduces the blast radius of an individual application-node failure. However, a load balancer does not guarantee high availability by itself. The architecture can still fail if: - the load balancer is a single self-hosted VM; - all backends depend on the same failed database; - every node is deployed on one underlying failure domain; - a bad release breaks the entire backend pool; - health checks misclassify healthy or unhealthy nodes; - session state exists only on the failed node. High availability comes from the full dependency chain, not from one component named “load balancer.” ### Deployment control A load balancer can support safer maintenance and releases by controlling which nodes receive new traffic. A typical rolling deployment flow is: ```text Remove App VM 1 from rotation ↓ Drain existing connections ↓ Deploy and verify ↓ Return App VM 1 to rotation ↓ Repeat for App VM 2 ``` Connection draining matters because immediately terminating active traffic can interrupt uploads, API requests, WebSockets, or long-running sessions. A node should stop receiving new work while existing requests are given time to finish. This is one reason load balancing is closely connected to [blue-green and rolling deployments](/learn/guides/blue-green-vs-rolling-deployments). ## Layer 4 vs Layer 7 load balancing “Load balancer” does not describe only one type of traffic decision. ### Layer 4 load balancing Layer 4 operates at the transport layer, primarily using connection information such as: - source and destination IP; - source and destination port; - TCP or UDP protocol. It can distribute traffic without interpreting the HTTP path, hostname, cookie, or application payload. Common Layer 4 use cases include: - generic TCP services; - databases or message brokers where balancing is appropriate; - TLS passthrough; - DNS and other UDP services; - high-throughput connection distribution. Layer 4 balancing is protocol-flexible and can preserve end-to-end TLS, but it cannot make content-aware routing decisions unless another application-aware layer is added. ### Layer 7 load balancing Layer 7 understands application protocols such as HTTP and HTTPS. It can route using: - hostname; - URL path; - HTTP method; - headers; - cookies; - application response information. Common Layer 7 use cases include: - routing `/api` and `/app` to different services; - canary or weighted HTTP releases; - cookie-based session persistence; - TLS termination; - request filtering and application-aware health checks. The trade-off is that Layer 7 has more protocol awareness, configuration, and processing responsibility. | Decision | Layer 4 | Layer 7 | |---|---|---| | Sees HTTP paths and headers | No | Yes | | Supports generic TCP/UDP | Yes | Primarily application protocols | | Can terminate and inspect HTTP TLS | Not when using passthrough | Yes | | Content-based routing | No | Yes | | Typical configuration complexity | Lower | Higher | | Good fit | Connection distribution | Application-aware traffic policy | ## Why one tool can be both The concepts overlap because many implementations accept client traffic, proxy it, and choose an upstream target in the same process. This Nginx-style architecture demonstrates both roles: ```nginx upstream app_pool { least_conn; server 10.20.20.11:3000; server 10.20.20.12:3000; } server { listen 443 ssl; server_name app.example.com; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://app_pool; } } ``` The `server` block performs the reverse-proxy role: it accepts public HTTPS traffic and applies request policy. The `upstream` pool performs the load-balancing role: it selects one of multiple application servers. The implementation is one Nginx instance, but the architecture still contains two responsibilities. That distinction matters when troubleshooting. A TLS or hostname-routing problem belongs to the edge proxy concern. Uneven backend load, failed health checks, or bad node selection belongs to the load-balancing concern. ## Load-balancing algorithms and when they matter The balancing algorithm determines how a healthy backend is selected. ### Round robin Requests are distributed across backends in sequence. It is a sensible default when nodes have similar capacity and requests have similar cost. ### Weighted round robin More traffic is sent to higher-capacity nodes. This is useful during migrations, mixed VM sizes, canary releases, or gradual capacity changes. ### Least connections New traffic goes to the backend with fewer active connections. It can work better when request duration varies significantly, but active connection count is not always equal to real CPU or memory load. ### Hash-based routing A value such as client IP, cookie, URL, or another request attribute determines the backend. Hashing can provide stable routing, cache locality, or basic session affinity. ### Response-time or adaptive methods Some products combine connection state, latency, and health data to select a target. These methods can be useful at scale but should not hide poor observability or unequal backend configuration. The “best” algorithm cannot fix an application that is not safe to run across multiple nodes. ## Session state: the hidden requirement behind load balancing Load balancing works best when application nodes are stateless: any healthy node can handle the next request. A node is not truly interchangeable when it stores important session data only in local memory or local disk. Common state that causes problems includes: - login sessions stored in one process; - uploaded files written to one VM’s local disk; - background-job ownership stored only in memory; - local caches that contain required rather than optional data; - WebSocket state with no reconnection or coordination strategy. There are two common responses. ### Externalize shared state Store sessions, uploads, queues, and durable data in systems that every app node can reach, such as: - Redis or another shared session store; - managed or self-hosted databases; - object storage for uploads; - shared queues; - coordinated pub/sub services. This produces a cleaner multi-node architecture and makes node replacement easier. ### Use session persistence carefully Sticky sessions route a client back to the same backend. This can reduce immediate application changes, but it creates trade-offs: - traffic may become uneven; - the session can still fail when that node fails; - autoscaling and deployments become harder; - the application remains dependent on node-local state. Session persistence is a compatibility tool, not a substitute for designing shared state deliberately. Read [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) before assuming that adding a load balancer automatically makes the application horizontally scalable. ## WebSockets, gRPC, streaming, and long-lived connections Not all traffic behaves like a short HTTP request. ### WebSockets The proxy or load balancer must preserve the protocol upgrade and use timeouts appropriate for long-lived connections. Rebalancing an established WebSocket connection is not the same as selecting a backend for a new request. ### gRPC and HTTP/2 gRPC commonly uses HTTP/2 and long-lived multiplexed connections. A connection-level balancing decision may send many logical requests through one backend connection, so connection behavior and balancing implementation matter. ### Streaming and large uploads Buffering, request limits, idle timeouts, and connection draining can interrupt streaming responses or uploads if configured for short request-response traffic. ### TCP and UDP services Layer 7 HTTP routing is not appropriate for every protocol. Database, DNS, mail, VPN, game, or custom services may require Layer 4 proxying and protocol-specific health checks. Choose the traffic layer after identifying the real protocol and connection lifecycle—not only the domain name. ## Preserving the real client IP Once a proxy or load balancer sits in front of the application, the backend may see the proxy’s private IP instead of the original client address. Common mechanisms for passing client connection information include: - the standardized `Forwarded` HTTP header; - `X-Forwarded-For` and related de facto headers; - the PROXY protocol for connection-level metadata. Configure the backend to trust these values only when they arrive from known proxy addresses. Otherwise a client may submit a forged forwarding header and appear to originate from another IP. Client IP handling affects: - application logs; - rate limiting; - geolocation; - abuse detection; - allowlists; - audit trails; - incident investigation. Test it before production. “The app works” is not enough if every request is logged as the load balancer’s IP. ## Architecture patterns from one VM to multiple nodes ### Pattern 1: one VM with a reverse proxy ```text Internet ↓ HTTPS Nginx or Caddy on Raff VM ↓ localhost Application process ``` Use this when: - one VM has enough capacity; - the application can tolerate that VM as one failure domain; - you need TLS, routing, and a clean public edge; - operational simplicity matters more than node-level failover. A reverse proxy is valuable here. A dedicated load balancer usually is not. ### Pattern 2: one proxy VM and several backend processes on the same VM ```text Internet ↓ Reverse proxy ├── App process 1 ├── App process 2 └── App process 3 ``` This can use multiple CPU cores and isolate application processes, but it is still one VM. It improves process-level resilience, not infrastructure-level availability. ### Pattern 3: public load-balancing layer with private app VMs ```text Internet ↓ Load-balancing edge ↓ private network App VM 1 App VM 2 ↓ private network Database, Redis, workers ``` Use this when: - more than one app VM serves the same workload; - node failure should not take the entire application offline; - rolling maintenance or horizontal scaling is required; - backend services should stay off the public internet. This is the natural point to combine [Raff VMs](/products/raff-vm), [Private Cloud Networks](/products/private-cloud-networks), and a load-balancing layer. ### Pattern 4: external edge proxy plus internal load balancer ```text Clients ↓ CDN, WAF, or edge proxy ↓ Regional load balancer ↓ private network Application pool ``` Larger systems may separate global edge concerns from regional backend distribution. Do not adopt this pattern until latency, security, multi-region, or operational requirements justify the extra layer. ## Does a reverse proxy remove a single point of failure? No—not when the reverse proxy itself runs on one VM. A single reverse-proxy VM can protect and organize access to the application while remaining a single failure point. If it stops accepting traffic, users cannot reach healthy backends behind it. To reduce that risk, teams may use: - a managed load-balancing service; - multiple proxy nodes behind another traffic layer; - failover addresses or routing mechanisms; - redundant infrastructure across failure domains. The right design depends on the availability target. A small internal tool and a revenue-critical SaaS application do not need the same edge architecture. ## Security and private-network design The safest default is usually: ```text Public: edge proxy or load balancer on required ports Private: app nodes, databases, caches, queues, workers, monitoring ``` Backend nodes should normally accept traffic only from the approved balancing or proxy layer. Databases should not become public merely because several app nodes need access. Use private networking and firewall rules to define explicit paths: | Source | Destination | Allowed traffic | |---|---|---| | Internet | Public edge | TCP 80/443 as required | | Edge or load balancer | App pool | Application port and health checks | | App pool | Database | Database port only | | App pool | Redis or queue | Required internal port only | | Admin network | Infrastructure | Controlled SSH or management access | | Monitoring | Edge and app pool | Metrics and health endpoints only | Read [Private Cloud Networks Explained](/learn/guides/understanding-private-cloud-networks) and [Public vs Private Cloud Traffic](/learn/guides/private-networking-public-vs-private-traffic) before exposing every node for convenience. ## Common mistakes ### Calling any proxy a load balancer A proxy forwarding to one backend is not providing backend redundancy. The name of the software does not change the architecture. ### Adding a load balancer before adding a second backend This creates cost and operational work without distributing anything. Start with the simplest layer that solves the current problem. ### Assuming multiple backends automatically create high availability Shared databases, shared storage, DNS, the load balancer, and the deployment itself may still be single failure points. ### Using a port-open check as application readiness A process can accept TCP connections while being unable to serve real requests. Health checks should reflect whether new traffic is safe. ### Keeping required state on local app disks Uploads, sessions, and required job state tied to one node undermine load balancing and failover. ### Trusting forwarding headers from everyone Only known proxies should be allowed to define the original client identity. ### Forgetting connection draining Removing a node immediately can terminate active requests and persistent connections during maintenance. ### Exposing every backend publicly A load balancer should simplify the public surface, not multiply it. Keep internal nodes on private paths wherever possible. ## Decision framework ### Choose only a reverse proxy when: - the application runs on one VM; - you need HTTPS termination; - several services share one public address; - hostname or path routing is required; - you need header policy, compression, buffering, or basic rate controls; - node-level failover is not yet a requirement. ### Add a load balancer when: - two or more backend nodes provide the same service; - one app-node failure should not stop the entire service; - traffic exceeds the safe capacity of one right-sized VM; - rolling or blue-green deployment traffic control is required; - health-based backend selection is needed; - TCP, UDP, or Layer 7 traffic must be distributed across a pool. ### Use both roles when: - the public edge needs TLS and application-aware policy; - the backend contains multiple healthy nodes; - internal nodes should remain private; - the system needs both request control and failure-aware distribution. ### Do not add either layer merely because: - the architecture diagram looks more professional; - a framework tutorial included it; - traffic might grow someday; - “high availability” is desired but the database and proxy remain single points of failure. Build for the availability and traffic requirements you can define, then preserve a clear path to grow. ## A practical Raff growth path For many applications on Raff, the cleanest architecture evolves in stages. ### Stage 1: one Raff VM and one reverse proxy Run the application behind Nginx, Caddy, or another reverse proxy on a [Linux VM](/products/linux-vm). Terminate HTTPS, route traffic to local application ports, and keep nonpublic services closed. ### Stage 2: separate stateful dependencies Move the database, Redis, workers, or uploads into appropriate services or separate VMs. Connect internal components using [Private Cloud Networks](/products/private-cloud-networks) rather than public database and cache ports. ### Stage 3: add another application VM Make the application safe to run on more than one node by externalizing sessions, uploads, and durable state. ### Stage 4: add load balancing Use a load-balancing layer to distribute traffic, evaluate health, drain nodes during maintenance, and support rolling changes. This path avoids premature complexity while keeping the architecture ready for real growth. :::cta Explore Load Balancers Distribute traffic across healthy backends when your application is ready for multi-node availability and scaling. ::: ## Conclusion A reverse proxy and a load balancer are not competing products that solve the same problem. A reverse proxy gives an application a controlled public entry point. It handles concerns such as TLS, request routing, headers, buffering, caching, and edge policy. A load balancer makes a backend pool operate as one service. It distributes traffic, evaluates health, removes failed nodes, and supports horizontal scaling and safer deployments. For a single Raff VM, start with a reverse proxy. When the application becomes multi-node, make the backends stateless enough to be interchangeable, connect them through a private network, and add load balancing for health-aware distribution. The strongest architecture is not the one with the most traffic layers. It is the one where every layer solves a specific, measurable problem. ## Sources - [NGINX Documentation — Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) - [NGINX Documentation — HTTP Load Balancing](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/) - [NGINX Documentation — TCP and UDP Load Balancing](https://docs.nginx.com/nginx/admin-guide/load-balancer/tcp-udp-load-balancer/) - [NGINX Documentation — HTTP Health Checks](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/) - [NGINX Documentation — Accepting the PROXY Protocol](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/) - [IETF RFC 7239 — Forwarded HTTP Extension](https://www.rfc-editor.org/rfc/rfc7239) - Date last verified: 2026-07-25 --- ### Self-Hosting Apps on Raff: A Complete Guide for Developers URL: https://rafftechnologies.com/learn/guides/self-hosting-apps-on-raff Description: Learn how self-hosting apps on Raff works, what tools to host, which VM size to choose, and when a VPS beats managed platforms. ## Introduction Self-hosting apps on Raff means running your own software on a Raff Technologies Linux VM instead of relying entirely on managed SaaS platforms. For developers, founders, and small teams, this gives you control over runtime versions, deployment workflows, data storage, background workers, private services, and monthly infrastructure costs. Self-hosting is the practice of deploying and operating software on infrastructure you control. Instead of paying a vendor to host the entire application for you, you run the application on a virtual machine, container stack, or private server environment. That control matters when you need Docker, custom ports, persistent storage, private networking, full root access, or predictable server pricing. This guide explains when self-hosting makes sense, what types of apps work well on Raff, how to choose the right VM size, what a practical self-hosting stack looks like, and when a managed platform is still the better choice. It is the pillar guide for the Self-Hosting on Raff cluster, which includes hands-on tutorials for Coolify, Supabase, Plausible, Ghost, Vaultwarden, Outline, Mattermost, and GitLab CE. Many teams do not need Kubernetes, a full platform engineering team, or a hyperscale cloud account to run useful software. A properly secured [Raff Linux VM](/products/linux-vm) with Docker, backups, object storage, firewall rules, and a static IP can host many internal tools, automation platforms, dashboards, documentation systems, and lightweight production applications. ## What Is Self-Hosting? Self-hosting is the act of running software on infrastructure you manage directly. In practice, that usually means renting a cloud server, installing the required runtime, deploying the application, configuring a domain, securing access, and maintaining backups. A self-hosted application can be simple or complex. A small Ghost blog, Plausible Analytics instance, or Vaultwarden password manager may run comfortably on a single VM. A heavier application like Supabase, GitLab CE, or Mattermost may require more CPU, memory, storage planning, and backup discipline. The important difference is ownership of the operating environment. With a managed SaaS product, the vendor controls the servers, runtime, scaling model, data location, and operational limits. With self-hosting, you control those choices yourself. That control is useful when your application needs: * a specific runtime version * background workers * custom ports * persistent uploaded files * private internal services * direct database access * predictable monthly infrastructure costs * Docker Compose deployment * application-level backups * full access to configuration files Self-hosting does not mean doing everything from scratch. You can still use Docker images, open-source packages, managed DNS, SSL automation, object storage, monitoring tools, and backup utilities. The difference is that you decide how those pieces fit together. ## Why Developers and Small Teams Self-Host Apps Developers and small teams self-host because managed platforms often become limiting once a project needs more control. A simple hosted tool is convenient at the beginning, but the limitations appear when you need custom deployments, private services, nonstandard runtime behavior, or cost predictability. The common transition looks like this: you start with shared hosting or a managed app platform because it is fast, familiar, and easy. Then your project grows. You need a background worker. You want Docker. You need a database extension. You want to run a private analytics tool. You need access to logs and configuration. At that point, a real VM becomes more practical than a restricted hosting panel. At Raff, this is one of the clearest customer patterns we see: people do not usually move to a VM because they want more complexity. They move because they need control that shared hosting and managed platforms do not give them. Self-hosting works especially well for: * developer tools * internal dashboards * automation platforms * private AI tools * analytics systems * CMS and publishing platforms * team wikis * Git repositories * small SaaS backends * staging environments * API services * monitoring tools The strongest reason to self-host is not always cost. Cost matters, but control is often the real reason. A self-hosted environment lets you decide when to upgrade, how to secure the app, where to store files, how to back up the database, and which services should communicate privately. ## What You Can Self-Host on Raff You can self-host many applications on Raff if they run on Linux, Docker, Docker Compose, or standard server runtimes such as Node.js, Python, PHP, Go, Ruby, or Java. Raff is especially suitable for applications that need a persistent server, static public IP address, SSH access, and predictable compute resources. The best self-hosted apps usually fall into a few categories. | Category | Example apps | Why teams self-host them | |---|---|---| | Deployment platforms | Coolify, Dokploy, CapRover | To deploy apps without paying for a managed PaaS | | Backend platforms | Supabase, Appwrite | To run auth, databases, APIs, and storage under your control | | Analytics | Plausible, Umami, Matomo | To keep website analytics private and predictable | | CMS and publishing | Ghost, WordPress, Directus, Strapi | To control content, plugins, themes, and hosting costs | | Password and secrets tools | Vaultwarden, Bitwarden self-hosted | To control sensitive team credentials | | Documentation | Outline, BookStack, Wiki.js | To run private team knowledge bases | | Communication | Mattermost, Zulip, Rocket.Chat | To host internal chat and collaboration tools | | Git and DevOps | Gitea, GitLab CE, Forgejo, Harbor | To run source control and registries | | Monitoring | Uptime Kuma, Grafana, Prometheus | To monitor services without depending only on third-party tools | | Automation | n8n, Node-RED | To automate workflows and internal operations | The easiest self-hosting path on Raff is Docker Compose. Docker Compose lets you define the application, database, volumes, ports, and environment variables in one file. It is simple enough for small teams but structured enough for repeatable deployments. If you are new to this workflow, start with a simple Docker-based app before hosting heavier platforms. A good progression is: 1. Uptime Kuma or Plausible 2. Ghost or n8n 3. Coolify 4. Supabase or Mattermost 5. GitLab CE This progression helps you learn the core operational skills before running heavier production systems. ## Self-Hosting vs Managed Platforms Self-hosting and managed platforms solve different problems. Self-hosting gives you control; managed platforms give you convenience. The right choice depends on whether your team values flexibility or reduced operational responsibility more. | Factor | Self-hosting on a VM | Managed platform | |---|---|---| | Control | High — you control OS, runtime, ports, services, and data paths | Lower — platform defines supported behavior | | Setup speed | Moderate — requires server setup | Fast — often deploys from Git quickly | | Maintenance | Your responsibility | Vendor responsibility | | Cost predictability | Usually predictable if VM resources are fixed | Can vary with usage, seats, builds, bandwidth, or add-ons | | Runtime flexibility | High | Limited to platform-supported runtimes | | Data ownership | Stronger control over storage and backups | Depends on vendor export and retention rules | | Scaling | Manual or architecture-driven | Often built into platform | | Debugging | Full access to logs and system state | Limited to platform logs and dashboards | | Best for | Developers needing control | Teams wanting convenience | A managed platform is often the right choice for teams that want to ship quickly without touching server operations. Render, Railway, Heroku-style platforms, Vercel, and Netlify reduce deployment work and hide server maintenance. That is valuable. A VM is the better choice when you need more control than those platforms allow. If you want to run Docker Compose, expose custom services, host multiple internal tools, use private networking, manage your own database, or avoid usage-based pricing surprises, self-hosting becomes attractive. The practical rule is simple: use managed platforms when convenience matters more than control; use a Raff VM when control, cost predictability, and operational flexibility matter more than abstraction. ## Choosing the Right Raff VM Size Choosing the right VM size depends on the application type, traffic level, memory usage, database size, and whether the app runs background workers. Most self-hosted applications fail from memory pressure before CPU pressure, so RAM is usually the first number to check. Raff offers General Purpose VMs for flexible workloads and CPU-Optimized VMs for workloads that need dedicated, consistent compute. General Purpose VMs are a strong fit for websites, dashboards, test environments, and lightweight self-hosted tools. CPU-Optimized VMs are better for databases, build workloads, analytics engines, CI/CD, and heavier platforms. Use this as a starting framework: | Workload | Suggested starting VM | Why | |---|---|---| | Uptime Kuma, Vaultwarden, small wiki | 1 vCPU / 1–2 GB RAM | Lightweight services with low CPU usage | | Ghost, Plausible, n8n, small CMS | 1–2 vCPU / 2–4 GB RAM | Needs enough RAM for app, database, and reverse proxy | | Coolify with a few apps | 2 vCPU / 4 GB RAM | Builds, proxy, and app containers need headroom | | Mattermost or Outline | 2–4 vCPU / 4–8 GB RAM | Team apps need database and file storage planning | | Supabase | 4 vCPU / 8 GB RAM or higher | Multiple services, PostgreSQL, API, realtime, and storage components | | GitLab CE | 4–8 vCPU / 8–16 GB RAM | GitLab is memory-heavy and needs storage planning | For early projects, start smaller and resize when usage justifies it. Raff supports resizing resources from the dashboard, so you do not need to overbuy for a project that has not proven its workload yet. For production applications, avoid running every service on the smallest possible VM. A server that is technically “enough” at idle may struggle during builds, backups, imports, traffic spikes, or scheduled jobs. A little headroom is cheaper than debugging random out-of-memory crashes. ## The Basic Self-Hosting Stack A reliable self-hosting setup needs more than the application itself. The application is only one part of the system. You also need networking, security, backups, monitoring, and a deployment method. A practical Raff self-hosting stack usually includes: | Layer | Recommended choice | Purpose | |---|---|---| | Operating system | Ubuntu 24.04 LTS | Stable Linux base with broad package support | | Deployment | Docker Compose | Repeatable app deployment | | Reverse proxy | Caddy, Nginx, or Traefik | Routes domains to apps and handles HTTPS | | Firewall | Raff firewall rules + UFW | Restricts public access | | TLS | Let’s Encrypt | Encrypts public web traffic | | Storage | VM disk, block storage, or object storage | Stores app files, uploads, backups, and logs | | Backups | Snapshots + database dumps + object storage | Protects recoverability | | Monitoring | Raff dashboard + Uptime Kuma or Prometheus | Tracks server and app health | | Secrets | `.env` files with strict permissions or a secrets manager | Stores credentials safely | The key is to separate responsibilities. Your reverse proxy should handle traffic. Your app should run in a predictable environment. Your database should have backups. Uploaded files should not be treated casually. Secrets should not be committed to Git. For many small teams, a single VM can run the entire stack at the beginning. That is normal. As the workload grows, you can separate the database, move uploaded files to object storage, add a second VM, or introduce private networking. ## Security Checklist for Self-Hosted Apps Self-hosting gives you control, but it also gives you responsibility. A self-hosted app should not be exposed to the internet without basic server hardening. At minimum, every Raff self-hosted app should follow this checklist: * use SSH keys instead of password-based SSH login * keep the operating system updated * expose only required ports * enable a firewall * run apps behind a reverse proxy * use HTTPS for all public web apps * store secrets outside the application repository * use strong admin passwords * enable application-level two-factor authentication when available * back up databases and uploaded files * test restores before you need them * monitor disk usage and memory usage * review logs after failed logins or suspicious behavior The most common mistake is exposing too much. Most self-hosted applications only need ports `80` and `443` open publicly after setup. SSH should be restricted, protected with keys, and ideally limited by IP if your workflow allows it. Databases should not be exposed publicly unless there is a specific reason and additional network restrictions are in place. Raff provides infrastructure-level security features such as firewall controls, SSH-based access, DDoS protection, and isolated VM environments. But application security is still shared responsibility. Raff can provide the server foundation; you still need to configure the software correctly. ## Backup and Recovery Planning Backups are not optional for self-hosted apps. If an app contains users, content, uploads, analytics, secrets, configuration, or business data, it needs a backup plan before it becomes important. A good self-hosting backup plan protects four things: 1. the database 2. uploaded files 3. configuration files 4. secrets and environment variables VM snapshots are useful, but they are not a complete backup strategy by themselves. A snapshot captures server state at a point in time, which is helpful before upgrades or risky changes. But application-level backups are still important because they let you restore a database, move an app, or recover specific files without restoring the entire VM. For self-hosted apps on Raff, a strong backup pattern is: * scheduled database dumps * compressed application configuration backups * off-server storage for backup archives * periodic VM snapshots before major upgrades * restore testing every few months Raff Object Storage is a natural fit for backup archives because it is S3-compatible and designed for backups, media files, logs, and static assets. Raff Object Storage starts at $7/month with 100 GB storage, 1 TB egress, unlimited API requests, and the S3 endpoint `s3.raffusercloud.com`. The simplest rule is this: if losing the app tomorrow would be painful, create a restore plan today. ## When You Should Not Self-Host Self-hosting is powerful, but it is not always the right choice. You should not self-host just because the software is open source or because the monthly price looks cheaper. Avoid self-hosting when: * your team has no one comfortable with Linux basics * the app is mission-critical but no one can maintain it * compliance requirements exceed your operational maturity * you cannot commit to patching and backups * you need global edge deployment immediately * a managed product is cheaper than your team’s maintenance time * downtime would be unacceptable and you have no redundancy plan A managed platform may be better for teams that want to focus entirely on product development. For example, a startup with no infrastructure experience may choose managed database hosting, hosted analytics, or a managed PaaS until the team has time to operate its own stack. The honest answer is that self-hosting trades vendor dependency for operational responsibility. That trade can be excellent, but only when you understand what you are taking on. ## Raff-Specific Context Raff is well suited for self-hosting because it gives developers the infrastructure primitives they need without forcing them into a complicated cloud architecture. You can start with a Linux VM, install Docker, attach storage, configure a firewall, assign a static IP, and deploy real applications without building an entire platform first. For many developers, this is the useful middle ground between shared hosting and hyperscale cloud. Shared hosting is simple but restrictive. Hyperscale cloud is flexible but often complex. Raff gives you direct server control with predictable VM plans, NVMe SSD storage, static public IPv4, DDoS protection, snapshots, backups, private networking, and S3-compatible object storage. That combination matters for self-hosting because most apps need more than compute. A serious self-hosted setup eventually needs: * a stable public endpoint * secure SSH access * firewall control * persistent disk * off-server backups * optional object storage * monitoring * resize options * human support when something goes wrong Raff does not remove the need to understand your application. But it does provide a clean foundation for running it. The most practical starting point for the Self-Hosting on Raff cluster is a General Purpose VM for lightweight tools and a CPU-Optimized VM for heavier workloads. For example, a small Vaultwarden or Uptime Kuma instance can run on a small VM, while Coolify, Supabase, Mattermost, and GitLab CE need more memory and storage headroom. ## Recommended Self-Hosting Paths The best self-hosting path depends on what you are trying to build. Do not start with the heaviest tool. Start with the simplest app that teaches the operational pattern you need. ### Path 1: Beginner self-hosting Start here if you are new to Linux servers. | Order | App | What you learn | |---|---|---| | 1 | Uptime Kuma | Docker Compose, ports, reverse proxy basics | | 2 | Vaultwarden | secrets, HTTPS, persistent volumes | | 3 | Ghost | CMS deployment, database backups | | 4 | Plausible | analytics stack, database + event storage | This path teaches the core pattern: deploy, expose safely, persist data, back up, and monitor. ### Path 2: Developer deployment platform Start here if you want to deploy multiple apps from Git. | Order | App | What you learn | |---|---|---| | 1 | Docker | container runtime basics | | 2 | Coolify | self-hosted PaaS workflow | | 3 | PostgreSQL or MySQL | database persistence | | 4 | Object Storage | file and backup separation | Coolify is a strong option when you want a platform-like workflow without giving up server control. It lets you self-host a deployment layer for apps and services while keeping the infrastructure under your own account. ### Path 3: Internal team tools Start here if you are building infrastructure for a small company. | Order | App | What you learn | |---|---|---| | 1 | Outline | internal documentation | | 2 | Mattermost | team communication | | 3 | Gitea or GitLab CE | source control | | 4 | Uptime Kuma | service monitoring | This path is useful for teams that want control over collaboration tools, data location, and operating cost. ### Path 4: Application backend Start here if you are building a SaaS or app backend. | Order | App | What you learn | |---|---|---| | 1 | PostgreSQL | database operations | | 2 | Supabase | backend-as-a-service components | | 3 | Object Storage | user uploads and backups | | 4 | Monitoring | operational visibility | Supabase is powerful, but it is not the lightest starting point. Treat it as a real backend platform, not a tiny side project container. ## Practical VM Sizing Examples A realistic sizing plan prevents frustration. These recommendations are starting points, not permanent limits. | App | Minimum practical starting point | Better production starting point | |---|---|---| | Vaultwarden | 1 vCPU / 1 GB RAM | 1 vCPU / 2 GB RAM | | Uptime Kuma | 1 vCPU / 1 GB RAM | 1 vCPU / 2 GB RAM | | Ghost | 1 vCPU / 2 GB RAM | 2 vCPU / 4 GB RAM | | Plausible | 1 vCPU / 2 GB RAM | 2 vCPU / 4 GB RAM | | n8n | 1 vCPU / 2 GB RAM | 2 vCPU / 4 GB RAM | | Coolify | 2 vCPU / 4 GB RAM | 4 vCPU / 8 GB RAM for multiple apps | | Outline | 2 vCPU / 4 GB RAM | 4 vCPU / 8 GB RAM | | Mattermost | 2 vCPU / 4 GB RAM | 4 vCPU / 8 GB RAM | | Supabase | 4 vCPU / 8 GB RAM | 8 vCPU / 16 GB RAM for active use | | GitLab CE | 4 vCPU / 8 GB RAM | 8 vCPU / 16 GB RAM or higher | The safest strategy is to start with the smallest plan that gives the app comfortable headroom, then resize based on real CPU, RAM, disk, and network usage. Do not choose a tiny VM for a heavy platform just because the installer technically starts. Production reliability depends on headroom. ## Cost Planning for Self-Hosted Apps Self-hosting can reduce software costs, but the better reason to self-host is predictable control. A VM has a clear resource boundary. You know how much CPU, RAM, and disk you are paying for. That makes budgeting simpler than platforms where cost grows through seats, usage, builds, bandwidth, add-ons, or feature tiers. When estimating self-hosting cost, include: * VM monthly cost * block storage or extra disk * object storage for backups and files * domain name * email provider if the app sends email * monitoring or alerting tools * your team’s maintenance time For small apps, the VM may be the main cost. For production apps, storage, backups, and operations matter too. A practical cost model is: | Stage | Infrastructure pattern | |---|---| | Prototype | One small VM, simple Docker Compose, manual backups | | Early production | One VM, reverse proxy, scheduled backups, monitoring | | Growing app | Separate storage, database backup plan, object storage, stronger monitoring | | Team platform | Multiple VMs, private networking, documented recovery plan | Self-hosting is not “free software on a cheap server.” It is controlled infrastructure. Treat it that way and it becomes reliable. ## Common Self-Hosting Mistakes Most self-hosting problems come from weak operations, not bad software. The app may be well built, but the deployment environment is often rushed. Avoid these common mistakes: * running everything as root without understanding permissions * skipping firewall configuration * exposing databases to the public internet * storing secrets in Git * relying only on VM snapshots * never testing backups * ignoring disk usage * installing many apps on one tiny VM * skipping updates for months * using default admin passwords * forgetting email deliverability for apps that send notifications The most dangerous mistake is having backups that have never been restored. A backup is only proven when you can restore it into a working application. Another common issue is overloading one VM. It is fine to run multiple small apps on one server, especially for internal tools. But if one app grows or becomes critical, separate it. The cost of a second VM is often lower than the cost of debugging noisy-neighbor problems inside your own stack. ## Content Cluster: What to Read Next This guide is the pillar article for the Self-Hosting on Raff cluster. The next articles in the cluster should help you move from planning to implementation. Recommended next tutorials: * Install Coolify on Ubuntu 24.04: Self-Hosted PaaS on Raff * Self-Host Supabase on Ubuntu 24.04 with Docker Compose * Self-Host Plausible Analytics on Ubuntu 24.04 * Deploy Ghost CMS on Ubuntu 24.04 with Nginx * Deploy Vaultwarden on Ubuntu 24.04 with Docker Compose * Deploy Outline Wiki on Ubuntu 24.04 with Docker Compose * Deploy Mattermost on Ubuntu 24.04 with PostgreSQL * Deploy GitLab CE on Ubuntu 24.04 If you are starting from zero, begin with Docker and a lightweight app. If you already know Docker Compose, Coolify is the strongest next step because it gives you a platform-style deployment workflow while still running on infrastructure you control. ## Conclusion Self-hosting apps on Raff is a practical path for developers and small teams that want more control than shared hosting or managed platforms provide. You can run real software on a Linux VM, use Docker Compose for repeatable deployments, secure the server with firewall rules and SSH keys, store files in object storage, and build a backup plan that matches your risk. The right self-hosting setup starts simple. Choose one app, deploy it cleanly, secure it, back it up, and monitor it. Once that pattern is reliable, you can add more tools or split heavier workloads onto separate VMs. Raff Technologies is a strong foundation for this workflow because it gives you the core building blocks self-hosted apps need: Linux VMs, root access, static IPs, NVMe SSD storage, Docker support, snapshots, backups, private networking, and S3-compatible object storage. Start with a [Raff Linux VM](/products/linux-vm), deploy one useful application, and build the cluster from there. This guide was prepared as the pillar for Raff’s Self-Hosting on Raff content cluster. The next recommended article is the Coolify tutorial, because it turns a single Raff VM into a self-hosted deployment platform for multiple applications. --- ### Kubernetes vs Docker Compose for Small Teams: When to Switch URL: https://rafftechnologies.com/learn/guides/kubernetes-vs-docker-compose-small-teams Description: Learn when Docker Compose is enough and when small teams should move to Kubernetes, with a Raff path from VM, database, storage, and worker roles. Kubernetes vs Docker Compose is not a question of which tool is more advanced. It is a question of which operating model your team is ready to run. Docker Compose is a simple way to define and run multi-container applications, usually from a single `compose.yaml` file. Kubernetes is a container orchestration platform for running containerized workloads across a cluster, with scheduling, service discovery, self-healing, scaling, and declarative infrastructure controls. Docker describes Compose as a tool to define and run multi-container applications, while Kubernetes describes itself as an open source system for automating deployment, scaling, and management of containerized applications: [Docker Compose documentation](https://docs.docker.com/compose/) and [Kubernetes documentation](https://kubernetes.io/docs/home/). For Raff Technologies users, the real decision is practical: keep Docker Compose on a Raff VM while one server or a small VM setup is enough, then move toward Kubernetes only when deployment coordination, scaling, service discovery, multi-node scheduling, and operational consistency become real problems. This guide explains when Docker Compose is enough, when Kubernetes makes sense, what small teams should prepare before moving, and how to connect the decision to the broader Raff infrastructure path: [single VM vs multi-VM SaaS architecture](/learn/guides/single-vm-vs-multi-vm-saas-architecture), [database backup strategy](/learn/guides/database-backup-strategy-saas-apps), [app uploads on object storage](/learn/guides/app-uploads-vm-disk-vs-object-storage), and [Raff VM](/products/raff-vm). ## Docker Compose and Kubernetes solve different stages Docker Compose and Kubernetes are both used with containers, but they solve different problems. Docker Compose is best when a team wants a simple way to define an app and its supporting services. A single Compose file can describe the app container, database container, Redis container, worker process, networks, volumes, and environment variables. ![Diagram comparing Docker Compose on one VM with Kubernetes cluster architecture](https://raff-images.s3.raffusercloud.com/docker_compose_vs_kubernetes_comparison_diagram_webp_3b1d5f0012.png) Kubernetes is best when a team needs a cluster-level operating model. It handles workloads across nodes, restarts failed containers, exposes services, manages configuration and secrets, schedules workloads, supports rolling updates, and provides a standard API for cluster operations. The important difference is not syntax. It is responsibility. | Area | Docker Compose | Kubernetes | |---|---|---| | Main unit | One project on one host or small setup | Cluster of workloads across nodes | | Complexity | Lower | Higher | | Best stage | Prototype, MVP, small production app | Growing production system with operational needs | | Deployment model | `docker compose up`, CI/CD script, or systemd wrapper | Declarative manifests, Helm, GitOps, or cluster deploy pipeline | | Scaling model | Usually host-level or simple service replicas | Cluster scheduling and workload scaling | | Networking | Simple app-level container network | Services, ingress, DNS, network policies | | Self-healing | Limited compared with Kubernetes | Built into workload controllers | | Team requirement | Basic container operations | Cluster operations, observability, and release discipline | | Best Raff fit | Raff VM for simple production workloads | Raff Kubernetes path when cluster operations are justified | Docker Compose is not "unprofessional." Kubernetes is not automatically "better." A small SaaS team needs the tool that matches its stage. ## Docker Compose fits simple production workloads Docker Compose is often enough for early SaaS products. A typical Compose-based app on a VM might run: - Web app container - Reverse proxy container - PostgreSQL or MySQL container - Redis container - Background worker container - Cron or scheduled job container - Monitoring or log agent - Local volumes for state - Environment file for configuration This pattern is easy to understand: ```text Raff VM ↓ Docker Compose project ↓ App + database + workers + cache ``` For many small teams, this is the right starting point. It keeps the app close to the server, avoids cluster overhead, and gives developers a predictable deployment model. Docker Compose fits when: - You run one production VM - Traffic is low or predictable - The app is a monolith or simple service set - Deployments can happen on one host - One server failure is acceptable at this stage - The database is small or managed separately - The team wants the fewest moving parts - The business is still validating the product - You can restore the app from backups and code - You do not need cluster-level scheduling Compose also works well for staging, preview, internal tools, demos, and small production apps where simplicity is more valuable than cluster features. A Raff VM with Docker Compose can be a strong production baseline when it has firewall rules, backups, monitoring, update discipline, and a clear plan for when to split services. :::cta deploy Use Raff VM when your team wants a simple production home for Docker Compose before Kubernetes is justified. ::: ## Docker Compose starts to show limits as operations grow Docker Compose usually breaks down when the app needs more than one server or when different workloads need independent operations. The warning signs are practical: - One VM is becoming too large - App deploys affect workers, database, or cache - Background jobs slow down web traffic - App traffic needs multiple servers - Rollbacks are becoming risky - Manual SSH deploys are becoming fragile - Multiple environments drift from each other - Scaling one service means scaling the whole VM - A single server failure creates too much downtime - Developers need consistent deployment across teams - Workers, app containers, and scheduled jobs need clearer ownership - Health checks, restarts, and service discovery are becoming manual These problems do not always mean "move to Kubernetes now." Often, the next step is a multi-VM architecture first: ```text Raff VM for app ↓ Raff Managed Database ↓ Raff Object Storage for uploads ↓ Worker VM for background jobs ``` This is a safer middle path for many SaaS teams. It separates the roles that create the most risk without forcing the team into cluster operations too early. For this stage, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture). ## Kubernetes fits when the team needs a cluster operating model Kubernetes becomes valuable when the team needs a consistent way to operate many containers across multiple nodes. Kubernetes is not only about running containers. It is about running workloads with a cluster API and operational primitives. A Kubernetes-based app may use: - Deployments for stateless app workloads - Services for stable internal networking - Ingress for traffic entry - ConfigMaps and Secrets for configuration - Horizontal scaling for replicas - Rolling updates for deployment safety - Liveness and readiness probes for health checks - Namespaces for environment or team separation - Persistent volumes for workloads that require storage - Network policies for traffic control - Observability tooling for logs, metrics, and traces That operating model is powerful, but it comes with responsibility. Kubernetes fits when: - The app has multiple services or many containerized workloads - Deployments need consistent rollout and rollback workflows - Several app instances need to run across nodes - Service discovery is becoming important - The team wants declarative infrastructure workflows - Self-healing containers reduce operational burden - Environments need to be standardized - Traffic or jobs need cluster-level scheduling - The team has time to monitor and maintain the platform - The business risk justifies added complexity Kubernetes should be adopted because it solves a real operating problem, not because it looks more mature in an architecture diagram. ## Before Kubernetes, prove you have outgrown VMs Small teams should prove they have outgrown VMs before moving to Kubernetes. A single VM can be enough for early products. A multi-VM setup can be enough for many production SaaS apps. Kubernetes becomes the right move only when plain VMs make deployment, scaling, and operations harder than the cluster overhead. Before Kubernetes, ask: - Can one larger VM solve the issue for now? - Can the database be moved to a managed database first? - Can background workers move to a separate VM? - Can uploads move to object storage? - Can a load balancer and two app VMs solve the availability need? - Can CI/CD improve deployments without Kubernetes? - Can better monitoring reveal the real bottleneck? - Can the monolith stay simple while infrastructure roles split? If the answer is yes, VMs may still be the better path. A common Raff path is: ```text Stage 1: One Raff VM Stage 2: Raff VM + Managed Database Stage 3: Raff VM + Managed Database + Object Storage Stage 4: App VM + Worker VM + Database + Object Storage Stage 5: Load Balancer + multiple app VMs Stage 6: Kubernetes when cluster operations are justified ``` This staged path prevents premature Kubernetes adoption. Kubernetes is not the first scaling step for most small teams. It is the step after VM-based architecture starts creating coordination problems that a cluster is designed to solve. ## The quick decision framework Use this table to decide between Docker Compose, multi-VM infrastructure, and Kubernetes. | Situation | Better default | Why | |---|---|---| | Prototype or demo | Docker Compose on one VM | Fastest path with low overhead | | Early MVP | Docker Compose on Raff VM | Simple deployment and debugging | | Small production app | Docker Compose + managed database | Keeps app simple while protecting data | | App has durable uploads | Add object storage | Files should not depend on app VM disk | | Background jobs affect users | Add worker VM | Jobs should not compete with web traffic | | One VM is not enough | Multi-VM architecture | Split roles before adopting a cluster | | Multiple app servers are needed | Load balancer + app VMs | Horizontal scaling without full Kubernetes | | Many services need coordination | Kubernetes | Cluster-level scheduling and service discovery help | | Deployments need standard rollout controls | Kubernetes | Declarative updates and health checks reduce manual work | | Team lacks platform operations capacity | Avoid Kubernetes for now | Cluster complexity can create more risk | | Environment drift is causing incidents | Kubernetes may help | Standardized manifests and deployment flows can reduce drift | | Cost clarity matters more than automation | VMs first | VM-based architecture is easier to reason about early | The best answer is not "always Compose" or "always Kubernetes." The best answer is the smallest operating model that solves the current production risk. ## Cost is not only the infrastructure bill Kubernetes can reduce operational pain at the right stage, but it also adds cost. The cost is not only cluster nodes. It includes: - Cluster design - Control plane decisions - Node sizing - Monitoring - Logging - Ingress setup - Secrets management - Backup planning - Upgrade process - Security policies - Developer training - Incident response - CI/CD changes - Helm, Kustomize, or GitOps workflow - More infrastructure concepts for the team to understand Docker Compose has fewer moving parts. A VM-based architecture is usually easier for a small team to inspect and reason about. Kubernetes can become cheaper in practice only when it replaces enough manual coordination, downtime risk, deployment risk, or scaling friction. Use this cost question: > Are we paying more in engineering time and operational risk by avoiding Kubernetes than we would pay by adopting it? If not, stay on VMs. For deeper planning, read [Kubernetes Cost Optimization for Startups](/learn/guides/kubernetes-cost-optimization-startups) and compare infrastructure options on [Raff pricing](/pricing). ## Databases should usually stay outside the cluster early A common mistake is moving the application to Kubernetes and immediately putting the production database inside the cluster. That is not always the right first move for small teams. Databases have different recovery, storage, upgrade, and operational requirements than stateless app containers. Running production databases inside Kubernetes can work, but it requires experience with persistent volumes, storage classes, backup operators, restore testing, and operational runbooks. For many small SaaS teams, the cleaner pattern is: ```text Kubernetes or app VMs ↓ private access Raff Managed Database ``` This lets the app benefit from container orchestration while the database stays in a managed service with clearer database operations. If your team needs full database control, a dedicated database VM can also be a better first step than placing the database inside Kubernetes. Use [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) and [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps) before deciding where production data should live. ## Uploads should move to object storage before Kubernetes If app uploads still live on the VM disk, Kubernetes will expose the problem quickly. Containers are meant to be replaceable. Pods can be rescheduled. Nodes can change. If user files depend on local disk inside one container or one VM path, the architecture is not ready for Kubernetes. A better pattern is: ```text Application container ↓ Database stores upload metadata ↓ Object storage stores uploaded files ``` Move durable files before moving the app to Kubernetes. Raff Object Storage is S3-compatible and fits user uploads, exports, reports, media, and backup archives. This gives the app a storage layer that does not depend on one container or one VM. For the full file decision, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## Docker Compose can still support a production-grade path A Compose-based setup can be production-grade when the scope is right. A good Docker Compose production setup should include: - Versioned Compose file - Explicit container images or build process - Reverse proxy and TLS - Environment variables managed carefully - Restart policies - Health checks where supported - Firewall rules - Backup plan - Restore test - Monitoring - Log rotation - Security updates - Separate database or managed database when needed - Object storage for durable uploads - CI/CD process instead of manual edits - Documented rollback path The issue is not that Docker Compose is bad. The issue is that Compose does not become a full cluster platform just because the app gets larger. Treat Compose as the right tool for small production scope. Treat Kubernetes as the next operating model when that scope is exceeded. ## Kubernetes readiness requires more than container images Being containerized does not mean being Kubernetes-ready. Before moving from Docker Compose to Kubernetes, check these areas: - The app can run multiple replicas safely. - Sessions do not depend on one container. - Uploads are stored outside local container disk. - Background workers are defined separately from web containers. - Scheduled jobs do not accidentally run multiple times. - The database is externalized or intentionally managed. - Configuration can be expressed through manifests or charts. - Secrets are handled safely. - Health endpoints exist. - Readiness and liveness checks make sense. - Logs go to a central place. - Metrics are visible. - The deployment process can roll forward and roll back. - The team understands namespaces, services, ingress, and workload controllers. - Backup and restore plans exist for stateful parts. Kubernetes rewards preparation. Without it, the team may move the same problems into a more complex environment. ## A practical migration path from Docker Compose to Kubernetes Move gradually. Do not turn a simple production app into a cluster migration project without a clear reason. ![Raff migration path from Docker Compose on a VM to Managed Database, Object Storage, worker VMs, load balancing, and Kubernetes](https://raff-images.s3.raffusercloud.com/raff_docker_compose_to_kubernetes_migration_path_webp_4ca685a541.png) ### Stage 1: Docker Compose on one VM Start with a simple, documented Compose setup. ```text Raff VM ↓ Docker Compose ↓ App + database + worker + cache ``` This works for prototypes, MVPs, staging, and small production apps. ### Stage 2: Externalize the database Move production data out of the Compose host. ```text Raff VM running app containers ↓ private access Raff Managed Database or database VM ``` This reduces data risk before application scaling. ### Stage 3: Externalize uploads Move durable files to object storage. ```text App container ↓ Raff Object Storage ``` This makes app containers easier to replace and prepares for multiple app instances. ### Stage 4: Split workers Move background jobs away from web traffic. ```text App VM ↓ Worker VM ↓ Managed Database + Object Storage ``` This may still use Docker Compose on each VM. ### Stage 5: Add load balancing if needed If the app needs more capacity before Kubernetes, use multiple app VMs behind a load balancer. ```text Users ↓ Load balancer ↓ App VM 1 + App VM 2 ↓ Managed Database + Object Storage ``` This can solve many SaaS scaling problems without Kubernetes. ### Stage 6: Move to Kubernetes when coordination becomes the bottleneck Move to Kubernetes when managing app replicas, deployments, services, rollbacks, scheduling, and environment consistency across VMs becomes harder than operating a cluster. ```text Kubernetes cluster ↓ App workloads + workers + services ↓ Managed Database + Object Storage ``` This is the point where Kubernetes starts earning its complexity. :::cta kubernetes Use Raff Kubernetes when your team has outgrown VM-level deployment coordination and needs a cluster operating model. ::: ## Raff path: VM first, Kubernetes when it earns its place Raff's infrastructure path should feel staged, not forced. A small team can begin with a Raff VM and Docker Compose. When the app grows, the team can separate the database, move uploads to object storage, split workers, and add load balancing. Kubernetes becomes the later step when the team needs cluster-level operations. A practical Raff product path looks like this: ```text Raff VM ↓ Raff Managed Database ↓ Raff Object Storage ↓ Worker VM or more app VMs ↓ Raff Kubernetes when orchestration is justified ``` This path supports teams that want to launch quickly without being trapped in a fragile single-server setup. Use: - [Raff VM](/products/raff-vm) for simple app hosting and Docker Compose - [Raff Managed Databases](/products/managed-databases) for PostgreSQL, MySQL, or Redis operations - [Raff Object Storage](/products/object-storage) for uploads, exports, media, and backups - [Raff Kubernetes](/products/kubernetes) when cluster orchestration is the right operating model - [Raff pricing](/pricing) to compare the staged cost This is the Raff-specific principle: do not buy complexity before the workload proves it. ## The pre-Kubernetes checklist Before moving a small team from Docker Compose or VM-based deployment to Kubernetes, review this checklist. - [ ] The team has measured why VMs are no longer enough. - [ ] The database is managed or intentionally externalized. - [ ] Database backups and restore have been tested. - [ ] Durable uploads are in object storage. - [ ] App containers can run multiple replicas safely. - [ ] Sessions do not depend on local container memory. - [ ] Background workers are separated from web traffic. - [ ] Scheduled jobs are designed to avoid duplication. - [ ] The app has health endpoints. - [ ] Logs can be collected centrally. - [ ] Metrics and alerts are defined. - [ ] Secrets are not stored casually in files or images. - [ ] Configuration is documented. - [ ] CI/CD can deploy repeatably. - [ ] Rollback strategy is defined. - [ ] The team understands basic Kubernetes concepts. - [ ] There is a person responsible for cluster operations. - [ ] Cost has been compared against VM-based alternatives. - [ ] The migration has a rollback path. If this checklist feels heavy, that is the point. Kubernetes can help, but it also becomes part of the system your team must operate. ## Common mistakes to avoid ### Moving to Kubernetes because it feels more advanced Kubernetes should solve a real operational problem. If one VM or a small multi-VM architecture still works, Kubernetes may add complexity before it adds value. ### Putting production data into Kubernetes too early Databases need serious backup, restore, storage, and upgrade discipline. Small teams should often use a managed database or dedicated database VM before running stateful production databases inside Kubernetes. ### Keeping uploads on local disk Local upload storage blocks container replacement and multi-node scheduling. Move durable files to object storage before Kubernetes. ### Replacing a deployment problem with a platform problem If deployments are messy because CI/CD is weak, Kubernetes will not automatically fix the process. Improve build, release, rollback, and configuration discipline first. ### Ignoring observability Kubernetes without logging, metrics, alerts, and health checks creates a bigger black box. Observability should be part of the migration, not an afterthought. ### Splitting the codebase too early Kubernetes does not require microservices. A monolith can run on Kubernetes. Split infrastructure operations before splitting the application into many services. ### Underestimating team learning cost Kubernetes adds concepts: pods, deployments, services, ingress, namespaces, secrets, config maps, volumes, RBAC, and cluster upgrades. Make sure the team is ready to own those concepts. ## Docker Compose vs Kubernetes comes down to operating model Docker Compose is the right choice when a small team needs a simple, understandable way to run a containerized app on one VM or a small setup. Kubernetes is the right choice when the team has outgrown VM-level coordination and needs cluster-level scheduling, service discovery, rollout controls, self-healing, and consistent operations across workloads. Most SaaS teams should not jump directly from first VM to Kubernetes. A better path is staged: start with Docker Compose on a Raff VM, externalize the database, move uploads to object storage, split workers, add load balancing when needed, and move to Kubernetes only when the operating model is worth the complexity. Next, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture), [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps), and [Kubernetes Cost Optimization for Startups](/learn/guides/kubernetes-cost-optimization-startups). Then compare [Raff VM](/products/raff-vm), [Raff Managed Databases](/products/managed-databases), [Raff Object Storage](/products/object-storage), [Raff Kubernetes](/products/kubernetes), and [Raff pricing](/pricing) to choose the next infrastructure step your team can operate safely. --- ### Blue-Green vs Rolling Deployments: Cost and Rollback URL: https://rafftechnologies.com/learn/guides/blue-green-vs-rolling-deployments Description: Compare blue-green and rolling deployments by rollback speed, temporary capacity, database compatibility, and team fit for safer cloud releases. Blue-green and rolling deployments are two ways to release a new application version without intentionally taking the service offline. **Blue-green deployment prepares a separate replacement environment and switches traffic to it. Rolling deployment updates the existing application instances gradually.** The right choice depends on the failure your team most wants to avoid. Blue-green prioritizes fast rollback and pre-release validation. Rolling prioritizes lower temporary infrastructure overhead and frequent releases. For small cloud teams, the decision is not about choosing the most advanced architecture. It is about balancing rollback speed, database compatibility, infrastructure capacity, and the amount of operational coordination the team can manage safely. ## Blue-green vs rolling deployments: quick answer Choose **blue-green** when a failed release must be reversed quickly and your team can run temporary parallel application capacity. Choose **rolling** when you already have multiple application instances, release frequently, and can safely run old and new versions at the same time during the rollout. | Decision factor | Blue-green | Rolling | |---|---|---| | Release method | Switch traffic between two environments | Replace existing instances gradually | | Rollback | Usually fast | Requires rolling the previous version back out | | Temporary capacity | Higher | Usually lower | | Mixed-version period | Avoided at the app tier after cutover | Expected during rollout | | Pre-release validation | Strong | More limited | | Best fit | High-risk releases and fast rollback | Frequent releases across multiple app nodes | A useful rule is: > Choose blue-green when rollback speed matters more than temporary capacity. Choose rolling when operational efficiency matters more than an instant traffic switch. ## How blue-green deployment works A blue-green deployment maintains two application environments: - **Blue** is the version currently serving users. - **Green** is the new version being prepared and validated. A simplified flow looks like this: ```text Users ↓ Load balancer or reverse proxy ↓ Blue environment — currently live Green environment — new version under validation ``` After the green environment passes health checks and release validation, traffic is switched from blue to green. ```text Before cutover: traffic → blue After cutover: traffic → green ``` If the new version fails and the old environment is still compatible with the shared data layer, traffic can be switched back. ### Blue-green strengths - The new environment can be tested before users reach it. - Rollback can be a traffic-routing decision rather than another deployment. - The old app environment can remain available during a short validation window. - Application instances do not normally run mixed versions after cutover. ### Blue-green limitations - A second application environment needs temporary compute capacity. - Environment drift can make green behave differently from blue. - Database changes may prevent a clean rollback. - Traffic switching, health checks, secrets, and configuration must be consistent. Blue-green is not automatically safe. It is safe only when both environments are repeatable and the database remains compatible with both application versions during the release window. ## How rolling deployment works A rolling deployment updates the application instances one at a time or in small groups. A typical two-node rollout looks like this: ```text App VM 1 — version A App VM 2 — version A ``` The deployment system removes one node from traffic, updates it, verifies it, and returns it to service. ```text App VM 1 — version B App VM 2 — version A ``` The process continues until every node runs the new version. ```text App VM 1 — version B App VM 2 — version B ``` ### Rolling strengths - It uses the existing application pool instead of duplicating the full environment. - It fits frequent release workflows. - Capacity can remain available while individual nodes are updated. - It works naturally with multiple stateless app instances behind a load balancer. ### Rolling limitations - Old and new versions coexist during the rollout. - Shared schemas, cache formats, sessions, queues, and internal APIs must remain compatible. - Rollback usually means redeploying the previous version across the pool. - Weak readiness checks can return an unhealthy node to traffic. Rolling deployments work best when the application tier is stateless and any shared state can safely support both versions for the duration of the release. ## The database decision comes first The hardest part of either strategy is usually not the application VM. It is the database and other shared state. A traffic switch cannot reverse a destructive schema migration. A gradual rollout cannot work safely when version A and version B expect incompatible data. Risky changes include: - dropping a column before the old application stops using it - renaming fields in a single release - changing session or cache formats without backward compatibility - deploying workers that write data the old application cannot read - changing message contracts while old consumers are still running A safer migration pattern is **expand, migrate, contract**: 1. Add the new schema or field without removing the old one. 2. Deploy code that can work with both formats. 3. Migrate existing data where necessary. 4. Confirm the old version is no longer required. 5. Remove the old schema in a later release. This pattern supports both rolling and blue-green deployments. > If the old application cannot safely use the new database state, blue-green rollback is not truly available. ## Cost and capacity comparison The cost difference should be understood as required capacity, not as a fixed historical price. | Deployment model | Normal app capacity | Temporary additional capacity | Practical use | |---|---:|---:|---| | Single-node in-place release | 1 app VM | None | Low-risk apps that can accept a restart window | | Two-node rolling deployment | 2 app VMs | Usually none | Frequent releases with continued service | | Single-node blue-green | 1 active + 1 replacement VM | 1 app VM during overlap | Small apps that need faster rollback | | Two-node blue-green | 2 active + 2 replacement VMs | 2 app VMs during overlap | Higher-risk production cutovers | Use the live [Raff pricing page](/pricing) to calculate the current cost of the application shape you plan to duplicate. The right comparison is not simply “Which strategy has the lower bill?” Ask: - How much would a failed release cost in support time, lost revenue, or customer trust? - How long must temporary replacement capacity remain online? - Can the team validate the new environment quickly? - Does the application need two nodes for availability even without deployment overlap? Temporary capacity can be reasonable release insurance, but only when it reduces a meaningful business risk. ## Which strategy fits your team? ### Choose blue-green when - rollback must be a fast traffic switch - releases are relatively infrequent but high risk - the new environment needs full validation before cutover - the application does not tolerate mixed versions well - temporary parallel application capacity is acceptable - the team has reliable environment automation ### Choose rolling when - the application already runs on multiple nodes - releases happen frequently - the app tier is stateless or close to stateless - old and new versions can coexist safely - readiness and health checks are reliable - the team wants lower release-specific infrastructure overhead ### Use a hybrid approach when Some teams use rolling releases for normal application updates and blue-green for migrations, major platform changes, or releases with unusually high customer risk. This is often more practical than forcing every release through the same process. ## Infrastructure requirements Both strategies depend on more than deployment scripts. ### Meaningful health checks A process listening on a port is not necessarily ready to serve users. A useful readiness check may verify: - the application completed startup - required configuration loaded - the database can be reached - critical dependencies are available - the node can complete a representative request ### Controlled traffic routing Blue-green requires a reliable traffic switch. Rolling requires a way to drain, update, verify, and return individual nodes. A load balancer or reverse proxy should route users only to healthy application instances. ### Repeatable environments Blue and green must differ by application release, not by forgotten packages or manual configuration. Keep the following versioned or automated: - application deployment - runtime version - system packages where practical - environment variable names - service definitions - proxy configuration - health checks ### Private backend traffic Application nodes should communicate with databases and internal services through controlled private paths wherever possible. Raff [Private Cloud Networks](/products/private-cloud-networks) can keep application-to-database and service-to-service traffic away from unnecessary public exposure. ### Recovery points before risky changes Snapshots and backups do not replace a deployment rollback, but they add protection before high-risk infrastructure or schema changes. Use [data protection](/products/data-protection) according to the workload’s recovery requirements and test restore procedures separately from deployment rollback. ## A practical Raff architecture A rolling deployment on Raff can use: ```text Users ↓ Raff Load Balancer ↓ App VM 1 App VM 2 ↓ private network Database ``` A blue-green deployment can use: ```text Users ↓ Raff Load Balancer ↓ Blue app pool — live Green app pool — validating ↓ private network Compatible database layer ``` Useful Raff building blocks include: - [Linux VMs](/products/linux-vm) for application nodes - [Load Balancers](/products/load-balancers) for health-aware traffic distribution - [Private Cloud Networks](/products/private-cloud-networks) for internal communication - [Data Protection](/products/data-protection) for scheduled recovery and snapshots The platform does not make the application backward-compatible automatically. Your release design still needs safe migrations, good health checks, observability, and a rehearsed rollback procedure. ## Recommended path for small teams A practical progression is: 1. Start with one application VM and a documented release process. 2. Add a staging environment before production risk becomes significant. 3. Add a second app node and load balancing when availability or rolling releases justify it. 4. Keep the app tier stateless and move shared state to appropriate services. 5. Use rolling deployment for routine releases. 6. Use blue-green selectively when rollback speed or pre-cutover validation is worth the additional capacity. Do not build two complete environments only because blue-green sounds safer. Do not use rolling deployment if the application cannot tolerate mixed versions. Choose the smallest release model that handles the actual risk. ## Common mistakes ### Treating blue-green as database rollback Switching traffic back does not reverse destructive database changes. ### Returning nodes to traffic too early Use readiness checks, not only process checks. ### Keeping green online indefinitely A temporary environment without a cleanup decision becomes permanent cost and configuration drift. ### Running mixed versions without compatibility testing Rolling deployments require compatible schemas, sessions, caches, and message formats. ### Using only one rollback mechanism Application rollback, database recovery, and infrastructure restore solve different problems. Document each one. ### Changing routing manually without a runbook The person handling the release should know how to switch traffic, verify the result, and reverse the change safely. ## Conclusion Blue-green and rolling deployments reduce release downtime in different ways. Blue-green provides a separate environment, stronger pre-cutover validation, and a faster traffic-level rollback. Rolling deployment updates the existing application pool gradually and usually needs less temporary infrastructure capacity. For many small teams with multiple stateless app nodes, rolling is the practical default for routine releases. Blue-green is valuable when a release is high risk, a clean cutover matters, or rollback must happen quickly. The database remains the deciding factor. Use backward-compatible changes, meaningful health checks, controlled routing, private backend traffic, and recovery planning regardless of the deployment strategy. :::cta Explore Load Balancers Distribute traffic across healthy application nodes and build a safer release path. ::: --- ### MCP vs n8n vs API Integration: Choosing the Right Automation Layer URL: https://rafftechnologies.com/learn/guides/mcp-vs-n8n-vs-api-integration Description: Compare MCP, n8n, and direct API integration by control, predictability, security, orchestration, and the best use case for each automation layer. MCP, n8n, and direct API integration solve different parts of an automation architecture. **MCP standardizes how AI applications discover and use external tools and context. n8n orchestrates predefined workflows across services. Direct API integration gives application code precise control over requests, validation, retries, and business logic.** They are not direct substitutes. A production system may use all three: - an API exposes the underlying capability - n8n coordinates a repeatable business process - an MCP server makes selected tools and data available to an AI application The right choice depends on who controls execution, how predictable the workflow must be, and how much operational responsibility your team can support. ## MCP vs n8n vs API: quick answer Choose **MCP** when an AI application needs a standardized way to discover tools, retrieve context, or invoke approved actions. Choose **n8n** when a trigger should start a visible, repeatable workflow that connects multiple systems. Choose **direct API integration** when the automation belongs inside your product and requires strict control, validation, latency, testing, or transaction logic. | Decision factor | MCP | n8n | Direct API integration | |---|---|---|---| | Primary role | Connect AI applications to tools and context | Orchestrate workflows | Connect software systems through code | | Main controller | AI host, model, application, and user policies | Workflow definition | Application code | | Execution pattern | Context-dependent tool discovery and invocation | Predefined nodes and branches | Explicit programmed logic | | Predictability | Depends on host and model behavior | High when workflow paths are defined | Highest when fully specified in code | | Best fit | AI assistants and agent interfaces | Business and operational automation | Product features and backend systems | | Typical owner | AI or platform team | Operations, automation, or development team | Software engineering team | | Human review | Often important for sensitive tools | Can be added as workflow steps | Implemented explicitly in the application | A practical rule is: > Use APIs for capabilities, n8n for repeatable orchestration, and MCP when an AI application needs a standard interface to selected capabilities and context. ## What is MCP? MCP stands for **Model Context Protocol**. It is an open standard for connecting AI applications to external systems. An MCP-compatible server can expose information and actions in a structured format that an MCP client can discover and use. MCP does not define how the language model reasons, how an agent plans, or how your business process should work. It defines the communication layer between an AI host and external capabilities. ### MCP architecture ![MCP architecture showing the AI host, MCP client, MCP server, tools, resources, prompts, and connected APIs, databases, files, and internal services.](https://raff-images.s3.raffusercloud.com/mcp_architecture_host_client_server_primitives_webp_d2aa145cf4.png) A typical MCP setup includes: - **Host** — the AI application coordinating the interaction - **Client** — the connection managed by the host for a specific MCP server - **Server** — the component exposing approved capabilities MCP servers can expose three important primitives: - **Tools** — executable functions such as querying a service or creating a record - **Resources** — contextual data such as files, schemas, documentation, or database records - **Prompts** — reusable interaction templates A simplified flow looks like this: ```text User ↓ AI application / MCP host ↓ MCP client ↓ MCP server ↓ API, database, file, or internal service ``` The MCP server may call an existing API behind the scenes. MCP usually wraps or exposes a capability; it does not replace the underlying application interface. ### What MCP is good for MCP is useful when: - an AI assistant needs access to several approved tools - multiple AI applications should connect to the same capability through a common interface - the host needs to discover available tools dynamically - contextual resources need to be provided alongside actions - the team wants to separate AI-facing tool definitions from internal service code Examples include: - an internal support assistant reading product documentation and creating tickets - a coding assistant accessing repositories, issue trackers, and deployment tools - an operations assistant querying infrastructure status and proposing actions - a finance assistant retrieving approved reports and preparing summaries ### MCP limitations MCP does not automatically make an AI workflow safe or reliable. You still need: - authentication and authorization - tool-level permissions - input validation - audit logs - timeouts and rate limits - human approval for sensitive actions - protection against untrusted context and prompt injection - clear separation between read-only and destructive tools A tool being available through MCP does not mean the model should be allowed to call it without policy checks. ## What is n8n? n8n is a workflow automation platform used to connect services, transform data, apply conditions, and execute multi-step processes. A workflow is usually built from: - a trigger - one or more action or transformation nodes - conditions and branches - credentials - error handling - execution history A simple workflow might look like this: ```text Webhook received ↓ Validate payload ↓ Look up customer ↓ Create CRM record ↓ Send team notification ``` The workflow path is defined in advance. Data may change at runtime, but the sequence and branches are visible in the workflow design. ### What n8n is good for n8n is useful when: - a business process crosses several SaaS tools - non-core automation needs to be delivered quickly - webhooks, schedules, or application events trigger workflows - the team wants visual execution history - a workflow needs conditional branches and data transformations - operational users need more visibility than a custom backend script provides Typical use cases include: - lead routing - invoice and payment notifications - customer onboarding - support ticket enrichment - scheduled reporting - content workflows - data synchronization - approval processes ### n8n limitations Visual workflows can become difficult to operate when they grow without structure. Common problems include: - very large workflows with too many branches - duplicated logic across multiple workflows - unclear credential ownership - unbounded retries - missing idempotency - excessive execution data retention - no versioning or promotion process - business-critical logic hidden in low-code nodes n8n is not automatically simpler than code. It is simpler when the workflow is appropriately scoped and maintained as an operational system. ## What is direct API integration? Direct API integration means application code communicates with another system through its defined interface. That interface may use: - REST - GraphQL - gRPC - webhooks - event streams - vendor SDKs A direct integration typically handles: ```text Application event ↓ Validate business conditions ↓ Authenticate request ↓ Call external API ↓ Handle response and errors ↓ Store result and emit audit data ``` ### What direct API integration is good for Direct APIs are usually the strongest choice when: - the integration is part of the product itself - latency matters - strict validation is required - transaction or consistency rules are complex - high request volume is expected - the team needs automated tests and deployment control - failure handling must be explicit - a workflow should not depend on a separate automation platform Examples include: - payment processing - account provisioning - usage metering - infrastructure control planes - authentication flows - customer-facing product integrations - high-volume data pipelines ### Direct API limitations Direct integrations require software engineering work. The team must own: - authentication - secret storage - request validation - retries and backoff - rate-limit handling - idempotency - observability - version changes - test coverage - ongoing maintenance The benefit is control. The cost is responsibility. ## MCP vs n8n: what is the real difference? The search phrase “n8n vs MCP” can suggest that the two tools compete directly, but they operate at different layers. MCP answers: > How can an AI application discover and access approved tools and context through a standard protocol? n8n answers: > How should a predefined automation move data and execute steps across connected systems? An MCP server may expose an n8n workflow as a tool. An n8n workflow may call an MCP-enabled service or invoke an AI model. One can sit behind the other. | Scenario | Better starting point | |---|---| | AI assistant needs to list and invoke approved tools | MCP | | New lead should be enriched and routed automatically | n8n | | Product must provision a customer account reliably | Direct API | | AI assistant should start an approved onboarding workflow | MCP + n8n | | Internal service capability should support both apps and automations | API + n8n or MCP | ## MCP vs API: does MCP replace APIs? No. MCP normally depends on APIs, SDKs, databases, or local functions behind the server. An API exposes a capability to software. MCP describes selected capabilities in a way an AI client can discover and invoke. For example: ```text Existing ticketing API ↓ MCP server exposes: - search_tickets - get_ticket - create_ticket ↓ AI assistant discovers approved tools ``` The underlying API still performs the actual ticket operation. MCP adds value when the capability needs to be made understandable and usable within an AI application. It does not remove the need for stable APIs, permissions, validation, and domain logic. ## n8n vs API: when is a visual workflow better than code? Use n8n when the process is primarily orchestration rather than core product logic. Good n8n candidates often have: - clear triggers - moderate volume - several external services - visible business steps - frequent process changes - limited transaction complexity Use direct code when the integration needs: - low latency - high throughput - strict consistency - complex domain rules - detailed automated tests - deployment alongside the product - minimal dependency on an external workflow engine A useful boundary is: > Keep core product invariants in code. Use n8n to coordinate systems around those invariants. ## Can MCP, n8n, and APIs work together? Yes. A hybrid architecture is often the most practical design. ### Pattern 1: MCP calls a controlled workflow ```text User request ↓ AI host ↓ MCP start_customer_onboarding tool ↓ n8n webhook ↓ CRM + email + internal notification ``` The AI selects an approved high-level action. n8n executes a deterministic workflow. This is safer than giving the model separate low-level tools for every step when the process should always follow the same sequence. ### Pattern 2: n8n uses an AI capability ```text Support ticket trigger ↓ n8n workflow ↓ Retrieve customer context ↓ AI classification or summary ↓ Route to correct team ``` Here, n8n controls execution and the AI handles a bounded decision or transformation. ### Pattern 3: API remains the source of truth ```text Product API ↑ ↑ n8n MCP server ``` Both n8n and the MCP server call the same validated API. Business rules stay centralized instead of being duplicated across workflow nodes and AI tools. This is usually the strongest long-term architecture. ## Decision framework ### Choose MCP when - the main interface is an AI application - tools or resources should be dynamically discoverable - several AI clients may use the same capability - context and actions need a consistent AI-facing contract - user confirmation can be applied to sensitive actions ### Choose n8n when - the process is triggered by a schedule, webhook, or application event - the workflow should follow known steps - several third-party systems must be coordinated - execution history and visual inspection are valuable - process changes should not require a full product release ### Choose direct API integration when - the integration is core to the product - behavior must be deterministic - performance and scale matter - complex validation or transaction rules apply - the engineering team needs full testing and release control ### Combine them when - an AI assistant should initiate a controlled business workflow - n8n needs to coordinate services behind an AI tool - a shared API should serve applications, workflows, and AI clients - the model should select an action but not manage every low-level step ## Security and governance The more automation layers you add, the more important clear security boundaries become. ### Use least-privilege credentials Do not give an MCP server or n8n instance an unrestricted administrative token when the workflow needs only one action. Separate credentials by: - environment - workflow - tool - permission level - customer or tenant where required ### Separate read and write tools An MCP server should distinguish between actions such as: - list resources - inspect status - create resource - modify resource - delete resource Destructive actions should require stronger validation and, where appropriate, human approval. ### Validate outside the model Never rely on an AI model alone to enforce business rules. The underlying API or workflow should validate: - allowed users - allowed resources - input formats - account limits - environment boundaries - duplicate requests - destructive operations ### Protect webhooks n8n webhook workflows should use authentication, signature verification, validation, and replay protection where supported by the source system. ### Treat external content as untrusted Documents, tickets, webpages, and user messages may contain instructions designed to manipulate an AI application. Keep tool permissions narrow and do not allow retrieved content to override system policies or authorization checks. ### Preserve audit trails Record: - who initiated the action - which workflow or tool ran - the validated inputs - the result - failures and retries - approval decisions ## Reliability and operations ### Design for idempotency A retry should not create duplicate customers, duplicate invoices, or duplicate infrastructure. Use request identifiers, deduplication keys, or API-level idempotency controls. ### Define timeout and retry policies Not every failure should be retried. Separate: - temporary network errors - rate limits - invalid input - authentication failures - permanent business-rule failures Use bounded retries with backoff rather than infinite loops. ### Keep workflows small Break large n8n automations into understandable sub-workflows with clear inputs and outputs. ### Expose high-level MCP tools Prefer a tool such as: ```text start_approved_customer_onboarding ``` over a collection of unrestricted low-level tools when the process must remain controlled. ### Centralize business rules When possible, keep important validation and state changes in a shared API. Let MCP and n8n call that API rather than implementing different versions of the same rule. ### Monitor the full path A successful MCP tool call does not guarantee the downstream workflow completed. A successful n8n node does not guarantee the external business outcome is correct. Monitor: - host and tool errors - workflow execution status - API latency and error rates - queue depth - external provider failures - final business outcomes ## Hosting these workloads on Raff These components have different runtime needs. ### n8n workloads A self-hosted n8n instance needs persistent configuration, a database strategy, secure credentials, backups, and enough memory for concurrent executions. Raff offers an [n8n VM](/products/n8n-vm) for teams that want a dedicated environment for workflow automation. ### MCP servers Remote MCP servers can run as application services on [Linux VMs](/products/linux-vm). Keep private databases and internal APIs on controlled network paths and expose only the required MCP endpoint. ### API services Application APIs can run on Linux VMs and scale behind [Load Balancers](/products/load-balancers) when multiple instances are required. Use [Private Cloud Networks](/products/private-cloud-networks) for communication between automation services, internal APIs, databases, and supporting systems where public exposure is unnecessary. Protect persistent automation data and configuration according to your recovery requirements with [Data Protection](/products/data-protection). Use the live [Raff pricing page](/pricing) to size the infrastructure for your expected execution volume, concurrency, database needs, and recovery plan. ## Recommended architecture for small teams A practical progression is: 1. Start with the provider API or an internal service as the source of truth. 2. Use n8n for operational workflows that cross multiple systems. 3. Add an MCP server only when an AI application needs structured access to selected tools or resources. 4. Expose high-level, permission-limited actions rather than unrestricted low-level access. 5. Keep validation in the API or deterministic workflow. 6. Add monitoring, audit logs, retries, and human approval before expanding access. Do not introduce MCP simply because a workflow uses AI. Do not place core product logic in n8n only because a visual workflow is faster to create. Do not write a custom integration when a small, maintainable workflow already solves the operational need. Choose the layer that matches the responsibility. ## Common mistakes ### Treating MCP as an AI agent framework MCP standardizes connections to tools and context. It does not define the model, reasoning loop, planning strategy, or business workflow. ### Treating n8n as a replacement for every backend service n8n is strong at orchestration, but core product rules may belong in tested application code. ### Giving the model low-level destructive tools Prefer bounded high-level actions with explicit validation and approval. ### Duplicating business rules Rules implemented separately in APIs, n8n nodes, and MCP tools will drift over time. ### Ignoring retries and duplicate execution Webhooks, networks, and external systems fail. Design every important action for safe retry behavior. ### Running automation without recovery planning Workflow definitions, credentials, execution data, and databases may all require backup and restore procedures. ## Conclusion MCP, n8n, and direct API integration belong to different layers of an automation system. MCP provides a standard connection between AI applications and external tools or context. n8n coordinates repeatable workflows across services. Direct API integration gives software teams the strongest control over product logic, validation, performance, and reliability. For most production systems, the API should remain the source of truth. n8n can orchestrate business processes around it, while MCP can expose carefully selected capabilities to AI applications. The strongest architecture is not the one with the most automation layers. It is the one that keeps control, permissions, and failure handling clear. :::cta Explore n8n VM Run self-hosted n8n workflows in a dedicated cloud environment built for your automation stack. ::: --- ### IPv4, IPv6, and Dual-Stack Networking for Cloud Servers URL: https://rafftechnologies.com/learn/guides/ipv4-ipv6-dual-stack-networking-cloud-servers Description: Compare IPv4, IPv6, and dual-stack networking for cloud servers, including DNS, firewalls, application binding, monitoring, and migration planning. IPv4, IPv6, and dual-stack describe how a cloud server is addressed and reached across modern networks. **IPv4 remains the broadest compatibility baseline. IPv6 provides a much larger address space and cleaner long-term network planning. Dual-stack lets a service use both, but only works well when DNS, firewall rules, application listeners, and monitoring are configured for both address families.** For most public applications, the safest path is not an immediate IPv6-only cutover. It is a staged rollout: keep IPv4 available, add IPv6 where the platform and application path support it, test both independently, and publish both DNS records only after the complete route works. ## IPv4 vs IPv6 vs dual-stack: quick answer Choose **IPv4-only** when broad compatibility and operational simplicity matter more than immediate IPv6 adoption. Choose **dual-stack** when you want to support both IPv4 and IPv6 clients without forcing a hard migration. Choose **IPv6-only** only when every client, dependency, monitoring service, and administrative path is known to support IPv6 or when translation is deliberately part of the design. | Decision factor | IPv4-only | IPv6-only | Dual-stack | |---|---|---|---| | Public compatibility | Highest | Depends on client and dependency support | High | | Operational complexity | Lowest | Medium | Highest | | Address-space flexibility | Limited | Very high | Very high | | DNS records | `A` | `AAAA` | `A` and `AAAA` | | Firewall review | IPv4 rules | IPv6 rules | Both rule sets | | Best fit | Fast launches and legacy dependencies | Controlled modern environments | Gradual public adoption | A useful rule is: > Do not publish an `AAAA` record until the IPv6 path works end to end. DNS should advertise a working route, not an intended future state. ## What IPv4 means for a cloud server IPv4 uses 32-bit addresses such as: ```text 203.0.113.20 ``` It remains widely supported by browsers, enterprise networks, monitoring providers, partner systems, allowlists, and operational tooling. IPv4 is often the simplest starting point for: - public websites - APIs with third-party consumers - services used by older corporate networks - workloads that depend on IPv4 allowlists - teams that have not yet tested IPv6 operations Its limitation is address scarcity. Public IPv4 addresses are finite, and private IPv4 ranges can also become difficult to manage when environments, customers, VPNs, and internal networks begin to overlap. NAT can extend IPv4 designs, but it also adds translation, state, and troubleshooting complexity. ## What IPv6 changes IPv6 uses 128-bit addresses such as: ```text 2001:db8:1234:1::20 ``` The larger address space is the obvious difference, but it is not the only operational change. IPv6 affects: - address planning - DNS - firewall policies - service binding - log formats - monitoring - access-control lists - application libraries - third-party allowlists IPv6 does not remove the need for firewalls or least-privilege access. A globally routable address should not be treated as permission for the internet to reach the service. The security model remains: 1. expose only required services 2. restrict source and destination traffic 3. authenticate users and services 4. monitor both expected and unexpected access ## What dual-stack actually means Dual-stack means the relevant server, network, or application path can use both IPv4 and IPv6. For a public website, a simplified path looks like this: ```text Client ├─ IPv4 route → A record → IPv4 listener └─ IPv6 route → AAAA record → IPv6 listener ``` A complete dual-stack deployment may require support at every layer: - the cloud platform assigns or routes IPv6 - the VM operating system configures the address - the firewall allows the intended IPv6 traffic - the reverse proxy or application listens on IPv6 - DNS publishes the correct `AAAA` record - monitoring tests the IPv6 endpoint separately A service is not operationally dual-stack merely because the operating system displays an IPv6 address. ## Why broken IPv6 can affect users Modern clients may receive both `A` and `AAAA` records and choose between multiple addresses. Algorithms such as Happy Eyeballs reduce delays by attempting suitable routes without waiting too long for a broken path. That does not make bad IPv6 configuration harmless. A partially working route can still create: - slow connection attempts - failures from specific ISPs or office networks - monitoring disagreements - TLS or proxy issues visible only over one address family - support cases that appear intermittent Test from real external IPv4 and IPv6 networks rather than relying only on local server checks. ## DNS design for IPv4 and IPv6 ### `A` records An `A` record maps a hostname to an IPv4 address. ```text app.example.com → 203.0.113.20 ``` ### `AAAA` records An `AAAA` record maps a hostname to an IPv6 address. ```text app.example.com → 2001:db8:1234:1::20 ``` ### Dual-stack DNS A dual-stack hostname usually publishes both: ```text app.example.com → A → 203.0.113.20 app.example.com → AAAA → 2001:db8:1234:1::20 ``` Before publishing the `AAAA` record, verify: - the address is assigned and routed correctly - the service listens on the intended IPv6 socket - TLS certificates and SNI behavior work - firewall rules allow only the intended ports - health checks pass over IPv6 - logs record the client address correctly - upstream dependencies do not assume IPv4-only source addresses DNS should be the final publication step after the network path is validated. ## Firewall rules must cover both families A common migration error is protecting IPv4 carefully while leaving IPv6 broader than intended. Review IPv4 and IPv6 exposure separately. For a web VM, the intended policy may be: | Service | IPv4 | IPv6 | Source | |---|---|---|---| | HTTP 80 | Allow | Allow | Public internet | | HTTPS 443 | Allow | Allow | Public internet | | SSH 22 | Restricted | Restricted | Approved admin source or private path | | Database port | Deny publicly | Deny publicly | Application network only | Do not assume a firewall tool automatically mirrors IPv4 rules to IPv6. Confirm the actual behavior of the operating system and platform firewall. Private addresses also do not replace firewall policy. A private network limits reachability, while firewall rules define which reachable systems may communicate. ## Application and reverse-proxy binding Even when networking is configured correctly, the application may listen only on IPv4. Common listener examples include: ```text 0.0.0.0:443 IPv4 on all interfaces [::]:443 IPv6 on all interfaces 127.0.0.1:3000 IPv4 loopback only [::1]:3000 IPv6 loopback only ``` The exact behavior depends on the operating system and application runtime. On some systems, an IPv6 wildcard listener may also accept IPv4-mapped connections; on others, separate listeners are needed. Verify the behavior rather than assuming it. For reverse proxies such as Nginx, HAProxy, or Caddy, test: - frontend IPv4 reachability - frontend IPv6 reachability - backend connection family - original client-IP forwarding - TLS termination - health-check behavior Read [Reverse Proxy vs Load Balancer](/learn/guides/reverse-proxy-vs-load-balancer) when deciding where the public listener should sit. ## Public and private traffic are separate decisions Public IPv6 adoption does not require every internal service to become publicly reachable. A practical architecture may use: ```text Internet clients ↓ IPv4 or IPv6 Public load balancer or reverse proxy ↓ private network Application servers ↓ private network Database and internal services ``` The public edge may support both address families while backend communication stays on the private addressing model supported by the environment. Use [Private Networking in Cloud: Public vs Private Traffic](/learn/guides/private-networking-public-vs-private-traffic) to decide which components should be internet-accessible. ## IPv4-only: when it remains reasonable IPv4-only is still a valid choice when: - your service must support the widest possible range of networks - third-party allowlists accept only IPv4 - operational tooling has not been tested with IPv6 - your team needs the simplest initial deployment - IPv6 does not yet solve a current constraint The important point is to avoid creating unnecessary future barriers. Keep configuration and application code flexible by: - storing hostnames instead of hardcoded IP addresses - supporting IPv6-safe log and database fields - avoiding parsing logic that assumes dotted-decimal addresses - reviewing libraries and access-control systems for IPv6 support ## Dual-stack: when it is the better migration path Dual-stack is a good fit when: - the workload is public-facing - both legacy and modern networks must connect - the team wants gradual IPv6 adoption - IPv6 routing is supported across the required platform path - monitoring can validate each family independently Dual-stack adds operational work because every exposed service has two potential paths. That added work is justified when compatibility and gradual adoption both matter. ## IPv6-only: when to use it carefully IPv6-only may work well for: - controlled internal networks - greenfield environments with known dependencies - specialized services where clients are IPv6-capable - architectures with a tested IPv4 translation layer Before choosing IPv6-only, verify: - package repositories and update systems - identity providers - external APIs - monitoring and alerting services - CI/CD runners - DNS resolvers - support access - backup destinations A single critical IPv4-only dependency can make an otherwise clean IPv6-only design unreliable. ## Monitoring and observability Monitor IPv4 and IPv6 as distinct service paths. At minimum, test: - DNS `A` response - DNS `AAAA` response - TCP connection over IPv4 - TCP connection over IPv6 - TLS handshake over both families - application health response - latency and error rate by address family Logs and analytics should preserve valid IPv6 addresses. Database columns sized only for short IPv4 strings can truncate or reject IPv6 values. For textual storage, allow enough space for normalized and non-normalized address representations or use a database-native IP address type where available. ## A practical rollout plan ### Stage 1: audit the path Confirm platform support, VM configuration, firewall behavior, proxy listeners, DNS management, and monitoring capability. ### Stage 2: test without public DNS Reach the service directly over the assigned IPv6 address or use a temporary test hostname. ### Stage 3: validate the application Check authentication, redirects, callbacks, WebSockets, API clients, logs, and rate limiting. ### Stage 4: publish the `AAAA` record Add the IPv6 DNS record only after the path is stable. ### Stage 5: monitor both families Track failures separately and keep rollback simple: removing the `AAAA` record should be an available response to an IPv6-specific incident. ### Stage 6: expand gradually Move additional services only after the first deployment behaves predictably. ## How this applies on Raff Raff [Private Cloud Networks](/products/private-cloud-networks) are designed for isolated internal communication and the current product page lists flexible subnet support for IPv4 and IPv6. Public IPv6 assignment and end-to-end dual-stack behavior should still be verified for the exact resource you are deploying. Before adding a public `AAAA` record, check the current Raff dashboard or documentation for: - whether the VM or load balancer has a public IPv6 address - how that address is routed - whether platform firewall rules cover IPv6 - whether the selected private network uses IPv4, IPv6, or both Use [Linux VMs](/products/linux-vm) for the application layer and [Private Cloud Networks](/products/private-cloud-networks) to keep internal service traffic away from unnecessary public exposure. The live [pricing page](/pricing) should be used for current infrastructure costs rather than embedding plan prices in a networking guide. ## Common mistakes ### Publishing `AAAA` before testing the route A DNS record can send real users to an incomplete path. ### Protecting only IPv4 IPv6 exposure requires its own firewall review. ### Assuming the application listens on both families Confirm the actual socket configuration. ### Hardcoding IPv4 addresses Use DNS names when possible and make storage formats IPv6-safe. ### Treating private addressing as full isolation Private networks and firewall policy solve different parts of the security model. ### Monitoring only one path A service can be healthy over IPv4 and unavailable over IPv6, or the reverse. ## Conclusion IPv4, IPv6, and dual-stack are operational choices that affect much more than address format. IPv4 remains the simplest compatibility baseline. IPv6 provides long-term address flexibility. Dual-stack is often the safest public migration model because it preserves IPv4 while introducing IPv6 gradually. The success of dual-stack depends on the complete path: address assignment, routing, DNS, firewall rules, application binding, TLS, and monitoring. Test each family separately and publish only routes that are ready to serve users. :::cta Explore Private Cloud Networks Keep application, database, and internal service traffic on controlled private network paths. ::: ## Sources - [Cloud-init documentation](https://docs.cloud-init.io/) - [RFC 8305: Happy Eyeballs Version 2](https://www.rfc-editor.org/rfc/rfc8305.html) - [Raff Private Cloud Networks](/products/private-cloud-networks) --- ### Cloud-Init vs Custom Images vs One-Click Apps URL: https://rafftechnologies.com/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click Description: Compare cloud-init, custom images, and one-click apps for VM provisioning. Learn when to use each model and how to combine them safely. Cloud-init, custom images, and one-click apps solve the same broad problem in different ways: turning a new virtual machine into a usable environment. **Use cloud-init when each server needs configuration at first boot. Use a custom image when many servers need the same tested baseline. Use a one-click app when deployment speed matters more than controlling every installation decision. Most production teams eventually combine these approaches instead of relying on only one.** The right provisioning model affects deployment speed, consistency, security patching, rollback, and how much configuration your team must maintain. ## Cloud-init vs custom images vs one-click apps: quick answer | Model | Best for | Main advantage | Main trade-off | |---|---|---|---| | Cloud-init | Dynamic first-boot configuration | Flexible and easy to version | Boot-time failures and longer provisioning | | Custom image | Repeated identical baselines | Fast, consistent deployments | Image maintenance and rebuild discipline | | One-click app | Fast evaluation and common stacks | Minimal setup effort | Less control and more opinionated defaults | | Hybrid model | Production fleets and multiple environments | Speed plus environment-specific configuration | More components to maintain | A practical decision rule is: - Choose **cloud-init** when values differ by environment or instance. - Choose a **custom image** when software changes less often than servers are created. - Choose a **one-click app** when you want a supported starting point and can accept its defaults. - Choose a **hybrid model** when you need both a hardened baseline and deployment-time customization. ## What VM provisioning includes VM provisioning is more than creating a server record. A usable environment may require: - operating-system selection - users and SSH keys - package installation - security updates - firewall rules - application dependencies - configuration files - service startup - monitoring agents - log rotation - backup configuration - application deployment The provisioning model decides which of these actions happen before the VM exists, during its first boot, or after it joins the environment. A useful way to separate responsibilities is: ```text Image layer ↓ operating system and stable baseline First-boot layer ↓ instance-specific configuration Configuration layer ↓ ongoing state and updates Deployment layer ↓ application releases ``` Trying to force every responsibility into one layer usually creates fragile automation. ## Cloud-init: configuration at first boot Cloud-init is an initialization system used by many Linux cloud images. It reads instance metadata and user-provided configuration, then performs tasks during the early boot process. Common cloud-init tasks include: - creating users - adding SSH keys - installing packages - writing files - setting hostnames - running commands - configuring storage or networking where supported A simple configuration may look like this: ```yaml #cloud-config package_update: true packages: - nginx - git users: - name: deploy groups: sudo shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: - ssh-ed25519 AAAA...example write_files: - path: /etc/nginx/conf.d/app.conf permissions: '0644' content: | server { listen 80; server_name _; location /health { return 200 'ok'; } } runcmd: - nginx -t - systemctl enable --now nginx ``` The exact modules and data sources available depend on the operating-system image and cloud platform. ## What cloud-init is good at Cloud-init is strongest when configuration must be decided at launch time. Examples include: - assigning an environment-specific hostname - adding deployment SSH keys - selecting a package repository - registering the VM with monitoring - writing environment-specific configuration - attaching the instance to a deployment workflow - installing a small set of current packages Because the configuration is text, it can be stored in version control, reviewed, tested, and generated through automation. ## Cloud-init limitations ### It is primarily a first-boot tool Cloud-init is not a complete long-term configuration-management system. It can prepare a server, but ongoing changes may be better handled by: - Ansible - Salt - Puppet - Chef - deployment pipelines - container images - application-specific management tools Using cloud-init for every future change can make state difficult to understand. ### Provisioning time grows with the script Downloading packages, compiling dependencies, and configuring large application stacks during boot can delay readiness. A new VM should not appear healthy until cloud-init and the required services complete successfully. ### External dependencies can fail First-boot configuration may depend on: - package mirrors - Git repositories - DNS - secret stores - external APIs - license servers A temporary failure can leave the VM partially configured. ### Debugging is different from interactive setup Cloud-init runs early and non-interactively. Commands that work in a shell may fail because of environment variables, network timing, missing paths, package locks, or service startup order. Common diagnostic locations include: ```text /var/log/cloud-init.log /var/log/cloud-init-output.log ``` The exact locations may vary by distribution. ## Cloud-init best practices ### Keep first-boot logic small Use cloud-init for bootstrap tasks rather than an entire platform installation when possible. A strong pattern is: 1. configure identity and access 2. install a small bootstrap dependency 3. retrieve a versioned configuration or artifact 4. start the next automation layer ### Make tasks idempotent A task is idempotent when running it again does not create duplicate or conflicting state. For example, prefer commands that check whether a file, package, user, or service already exists. ### Do not place long-lived secrets directly in reusable files User-data may be visible in platform metadata, logs, automation history, or support workflows depending on the environment. Prefer short-lived credentials, secret-store retrieval, or post-provisioning injection with appropriate access controls. ### Validate syntax before deployment YAML indentation errors and shell quoting mistakes can break a complete launch. Test cloud-init configurations on disposable VMs before production use. ### Define readiness separately from VM power state A running VM is not necessarily a configured VM. Use a health check, completion marker, or deployment status that confirms the required services are ready. ## Custom images: a prebuilt server baseline A custom image is a reusable machine image created from a prepared system or through an image-building pipeline. The image can contain: - operating-system updates - standard users and packages - monitoring agents - security configuration - language runtimes - container runtime - application dependencies - approved baseline settings New VMs begin from that baseline instead of repeating every installation step at boot. ## What custom images are good at Custom images fit workloads where the same server baseline is created repeatedly. Examples include: - autoscaled application nodes - CI/CD runners - standardized development environments - worker fleets - security-hardened server baselines - managed-service customer templates The primary benefit is consistency. Every node begins from the same tested artifact. Custom images can also reduce deployment time because package installation and large dependency setup happen during image creation rather than during every VM boot. ## Custom-image limitations ### Images become stale An image contains the software versions and security state from the moment it was built. Without a rebuild schedule, new VMs may start with outdated packages and known vulnerabilities. ### Changes require a new version Treat images as immutable artifacts. Instead of modifying one image in place, build and test a new version. A simple naming model may be: ```text web-base-2026-07-01 web-base-2026-07-15 web-base-2026-08-01 ``` Keep enough history for rollback, but remove obsolete images according to a retention policy. ### Hidden machine identity can be cloned A server copied directly into an image may contain identity and state that should not be duplicated. Examples include: - SSH host keys - machine IDs - cloud-init instance state - temporary credentials - shell history - logs - DHCP leases - application tokens - monitoring-agent identity Image preparation must remove or regenerate machine-specific data. ## Custom-image hygiene checklist Before capturing or finalizing an image, review: 1. **Secrets** — remove API keys, passwords, private certificates, tokens, and environment files. 2. **SSH host keys** — regenerate on first boot where appropriate. 3. **Machine identity** — clear values such as `/etc/machine-id` according to the distribution’s supported process. 4. **Cloud-init state** — clean previous instance data if the image will run cloud-init again. 5. **Logs and shell history** — remove operational and sensitive history. 6. **Temporary files** — clear package caches and build artifacts that do not belong in the image. 7. **Network state** — remove static addresses or leases that should not be cloned. 8. **Monitoring identity** — ensure every new VM registers as a unique node. 9. **Updates** — apply and test the intended patch level. 10. **Documentation** — record image version, build source, package versions, and intended use. The cleanup commands differ by operating system. Follow the distribution’s documented image-preparation process rather than deleting identity files blindly. ## Build images through a pipeline Manual image creation is suitable for experiments but becomes difficult to audit at scale. A stronger production workflow is: ```text Base OS image ↓ Versioned build script ↓ Security and package installation ↓ Automated tests ↓ Image capture ↓ Staging deployment ↓ Approved production image ``` Tools such as Packer or custom automation can make image creation repeatable where supported by the platform. The important outcome is not the tool name. It is having a build definition that can recreate the image without relying on undocumented manual steps. ## One-click apps: a prepared application starting point A one-click app is a platform-provided image or deployment template that includes an operating system and a common application stack. Depending on platform availability, examples may include: - Docker - WordPress - n8n - database tools - control panels - development stacks One-click apps reduce initial installation work. They do not remove operational responsibility. After deployment, the user may still need to manage: - application updates - operating-system patches - backups - domain and TLS configuration - admin credentials - firewall rules - plugins and extensions - monitoring - data migration ## What one-click apps are good at One-click apps work well for: - evaluation - prototypes - internal tools - common self-hosted software - teams that want a known initial structure - users who prefer platform defaults over manual installation They can also reduce setup errors when the template is actively maintained and documented. ## One-click app limitations ### The defaults may not match production requirements A template may choose: - a specific directory layout - a container setup - a database location - a firewall policy - an update mechanism - a default administrator path Review those choices before placing customer data or production traffic on the system. ### Maintenance ownership can be unclear Understand which parts the platform maintains and which parts you maintain. A preinstalled application is not automatically a managed application service. ### Templates can age Confirm the application and operating-system versions before deployment. Update them according to the vendor’s supported process. ### Migration may still require manual work A one-click deployment creates a destination. It does not automatically move an existing database, uploads, DNS, plugins, email configuration, or external integrations. ## Decision framework ## Choose cloud-init when - server configuration varies by environment - values must be assigned at launch - the setup can complete reliably during boot - the team is comfortable testing and debugging automation - the base image is already close to the desired state Avoid putting large, slow, or fragile installation workflows entirely into cloud-init. ## Choose custom images when - many servers need the same baseline - startup time matters - consistency is more important than per-instance variation - the team can maintain a rebuild and patching process - the image can be tested as an immutable artifact Do not use custom images as permanent archives of manually modified servers. ## Choose one-click apps when - a common application must be launched quickly - the platform template matches the intended use - the team accepts the template’s architecture - the environment will be reviewed and hardened after deployment Do not assume one-click means fully managed, automatically backed up, or production-secure. ## Use a hybrid model when A common production pattern is: 1. **Custom image** for the operating-system and security baseline 2. **Cloud-init** for instance identity and environment-specific configuration 3. **Configuration management** for ongoing server state 4. **CI/CD** for application releases 5. **One-click app** only where its maintained template genuinely reduces work Example: ```text Hardened base image ↓ Cloud-init adds hostname, SSH keys, monitoring registration ↓ Configuration management applies environment policy ↓ CI/CD deploys application version ``` This separates stable configuration from values that change per server or per release. ## Provisioning and infrastructure as code Provisioning models and infrastructure as code are related but not identical. Infrastructure as code may define: - VM size - network attachment - storage - firewall policy - load balancer configuration Cloud-init or an image then prepares the operating system inside the resource. Read [Infrastructure Automation on Raff](/learn/guides/automation-infrastructure-as-code-raff) for the wider workflow across scripts, APIs, and infrastructure tooling. ## Provisioning across environments Development, staging, and production should share a controlled baseline without sharing every secret or capacity decision. A practical model is: - same image family - different environment-specific cloud-init values - separate credentials - separate networks - separate databases - different VM sizes where justified Read [Dev, Staging, and Production Environments](/learn/guides/dev-staging-production-cloud-environments) for environment-boundary decisions. ## Provisioning and backups solve different problems A custom image or provisioning script helps recreate a server baseline. It does not protect current application data. Backups and snapshots may protect: - databases - uploads - application state - configuration changes - recovery points A useful recovery plan combines: - reproducible infrastructure - reproducible server configuration - protected persistent data - documented restore steps Read [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies) before treating an image as a backup. ## Security responsibilities by model | Responsibility | Cloud-init | Custom image | One-click app | |---|---|---|---| | Patch baseline | Script or base image | Image rebuild | Verify template, then maintain | | Secret handling | Avoid reusable plaintext | Remove before capture | Rotate defaults and review setup | | Consistency | Depends on execution | High when versioned | Depends on template version | | Ongoing updates | Separate process required | Rebuild and replace | User or service owner responsibility | | Auditability | Strong when versioned | Strong with build pipeline | Depends on template documentation | No provisioning model removes the need for security ownership. ## Testing a provisioning workflow A provisioning workflow should pass more than a boot test. Validate: - user and SSH access - package installation - service startup - firewall rules - DNS and network access - storage mounts - logging - monitoring registration - time synchronization - application health - reboot behavior - secret retrieval - backup configuration Test repeated creation and deletion, not only one successful VM. For custom images, test the image after a clean launch. For cloud-init, test both successful execution and failure recovery. For one-click apps, review the initial credentials, exposed ports, and update path. ## Observability and failure handling Provisioning failures should be visible to operators. Track: - creation request - VM power state - cloud-init completion - application health - image version - configuration version - deployment version Do not route production traffic to a node merely because the VM exists. A load balancer health check or deployment gate should confirm that the intended service is ready. ## How this applies on Raff Raff provides [Linux VMs](/products/linux-vm), snapshots, APIs, and application-oriented product paths that can support different provisioning workflows. The exact availability and behavior of cloud-init user data, custom-image creation, snapshot-based reuse, and one-click applications should be confirmed in the current Raff dashboard and product documentation before designing automation around them. A safe Raff planning approach is: - use a current Linux image as the starting baseline - use first-boot automation only when the dashboard and selected image support it - use snapshots for recovery according to their documented behavior - treat a reusable custom-image workflow as available only after confirming the platform operation - review current application templates instead of relying on an older `/products/raff-apps` assumption - use the live [pricing page](/pricing) for current VM and storage costs This prevents a guide from promising a provisioning feature that may differ by product, image, or current platform release. ## Common mistakes ### Installing everything during first boot Large installation scripts increase launch time and failure risk. ### Capturing secrets inside an image Every VM created from that image may inherit the same credentials. ### Treating snapshots and images as interchangeable A snapshot may be designed primarily for recovery, while a reusable image is designed for clean repeated deployment. Confirm platform behavior. ### Never rebuilding images An old image can recreate old vulnerabilities at high speed. ### Assuming a one-click app is managed Preinstalled software still requires patching, backups, monitoring, and secure configuration unless the product explicitly includes management. ### Mixing application releases into the base image unnecessarily If the application changes daily but the operating-system baseline changes monthly, separate those release cycles. ### Ignoring provisioning failure states A powered-on VM can still be incomplete or unsafe to receive traffic. ## Provisioning checklist Before choosing a model, answer: 1. Which settings are stable across every server? 2. Which values change per instance or environment? 3. How quickly must a replacement node become ready? 4. Who rebuilds and patches the image? 5. Where are secrets retrieved? 6. How is provisioning tested? 7. What indicates successful completion? 8. How are failed nodes removed or retried? 9. Which data must survive server replacement? 10. Does the current platform support the required workflow? ## Conclusion Cloud-init, custom images, and one-click apps are not competing versions of the same feature. They move configuration work to different stages. Cloud-init is best for dynamic first-boot values. Custom images are best for consistent, frequently reused baselines. One-click apps are best for fast deployment of common stacks when their defaults fit the workload. For production systems, a hybrid approach is often the most maintainable: build a tested baseline, keep instance-specific configuration small, manage ongoing changes separately, and protect persistent data with a real backup strategy. :::cta Deploy Your Server Start with a Raff Linux VM and choose the provisioning workflow that matches your team’s operating model. ::: ## Sources - [Cloud-init documentation](https://docs.cloud-init.io/) - [Raff Linux VMs](/products/linux-vm) - [Infrastructure Automation on Raff](/learn/guides/automation-infrastructure-as-code-raff) --- ### VPS vs VDS: Is There a Real Difference in Hosting? URL: https://rafftechnologies.com/learn/guides/vps-vs-vds Description: Learn how VPS and VDS differ in CPU allocation, isolation, performance, storage, cost, and terminology—and what to verify before choosing a server. VPS and VDS are two labels used for virtual servers. In some provider catalogs, VDS means a virtual machine with stronger or dedicated resource guarantees; in others, it is simply another name for VPS. The label alone does not prove better isolation, faster performance, or dedicated hardware. The practical difference appears in the service definition. Buyers should compare how CPU time is allocated, whether memory is guaranteed, how storage performance is managed, what network limits apply, and how much contention the provider allows. A well-defined VPS can offer stronger guarantees than a loosely defined VDS. This guide explains where the terms came from, when they describe a meaningful technical difference, and how to evaluate a plan without relying on the product name. For the underlying architecture first, read [how VPS hosting works](/learn/guides/how-vps-hosting-works). ## VPS and VDS Are Not Universally Standardized Terms VPS stands for virtual private server. VDS stands for virtual dedicated server. Both usually describe an independent virtual machine running on provider-managed physical infrastructure. Each can include: - A separate operating system - Root or administrator access - Virtual CPU and memory - Persistent storage - Public or private networking - Independent users, processes, and system settings The difficulty is that the hosting industry does not apply one universal definition to the two labels. Some providers use **VPS** for plans with shared CPU access and **VDS** for plans with dedicated or reserved CPU capacity. Other providers use VDS as a regional or marketing synonym for VPS. A third group may call every virtual machine a VPS while offering both shared and dedicated resource tiers inside the same product family. This means a product name is not a technical guarantee. The contract, resource policy, and plan specifications are more important than whether the page says VPS or VDS. A useful rule is: > Treat VPS and VDS as provider-defined labels until the resource guarantees are documented. ## A VPS Usually Emphasizes Isolation and Cost Efficiency A VPS is a virtual server with an isolated operating environment. It behaves like an independent server even though lower-level infrastructure may be shared. The operating system inside the VPS has its own filesystem, users, processes, network configuration, and application stack. One customer does not normally manage another customer’s operating system or files. VPS plans often prioritize efficient infrastructure sharing. The provider can schedule processor time across multiple virtual machines while assigning defined memory and storage limits to each one. This makes VPS hosting cost-effective for workloads that do not use maximum CPU continuously. Typical VPS workloads include: - Websites and content management systems - APIs and small web applications - Development and staging environments - Docker hosts - Automation tools - Internal dashboards - Small databases - Linux services - Windows remote workloads The word “shared” requires context. A VPS is not the same as shared web hosting. Shared web hosting normally places multiple customers inside one provider-managed application environment with limited server control. A VPS gives the customer an independent operating system and administrative access. However, some physical capacity can still be shared beneath the virtual machine. Shared CPU access is the most common example. Storage systems and network links can also serve multiple customers even when each VPS remains logically isolated. ## A VDS Usually Emphasizes Stronger Resource Guarantees Providers that distinguish VDS from VPS usually use VDS to describe a virtual machine with more exclusive or predictable resources. A VDS plan may include: - Dedicated or reserved virtual CPU capacity - Lower CPU oversubscription - Guaranteed memory allocation - Higher or more predictable storage performance - Stricter limits on neighboring workloads - A larger default server size - Higher support or availability expectations The virtual server is still not necessarily a physical dedicated server. It normally remains a virtual machine managed through a virtualization layer. The difference is the degree of resource commitment rather than the absence of virtualization. This distinction can matter for workloads that consume resources continuously. A busy database, build runner, encoding service, game server, or high-traffic application may benefit from more consistent CPU access than a burst-oriented general-purpose workload. But “VDS” does not automatically guarantee all of these characteristics. One provider may reserve CPU but use shared storage. Another may provide dedicated CPU threads while applying the same network policy as its VPS plans. A third may use the VDS label without publishing any stronger guarantee. The buyer must verify exactly what is dedicated, reserved, limited, or shared. ## The Real Difference Is Resource Allocation, Not the Acronym The most useful VPS vs VDS comparison focuses on resource behavior. ![VPS vs VDS comparison showing their shared virtualization foundation and differences in CPU, memory, storage, and network resource policies.](https://raff-images.s3.raffusercloud.com/vps_vs_vds_resource_policy_comparison_webp_a4f8ba1a19.png) | Factor | Typical VPS positioning | Typical VDS positioning | What to verify | | --- | --- | --- | --- | | Operating-system isolation | Independent guest OS | Independent guest OS | Whether each server has separate administrative control | | CPU | Often shared or burstable | Often dedicated or reserved | Shared vs dedicated CPU and sustained-use policy | | Memory | Defined plan allocation | Defined or strongly guaranteed allocation | Whether memory can be reclaimed or overcommitted | | Storage | Persistent virtual disk | Persistent virtual disk, sometimes higher tier | Latency, throughput, IOPS, contention, and expansion options | | Networking | Shared provider network | Shared provider network, sometimes higher limits | Port speed, transfer policy, caps, and fair-use terms | | Performance consistency | Good for variable workloads | Often positioned for sustained workloads | Actual guarantees rather than marketing language | | Price | Usually lower | Usually higher | Total cost for equivalent resources and protection | | Physical hardware | Shared host infrastructure | Usually still virtualized infrastructure | Whether the plan is virtual or truly bare metal | ### CPU policy is usually the most meaningful separator Shared CPU plans allow several virtual machines to use the same underlying processor capacity over time. This works well when workloads are idle or lightly loaded for significant periods. Dedicated CPU plans provide a more exclusive execution allocation. They are better suited to applications that remain CPU-active for long periods or need more predictable compute availability. When a provider uses VDS to indicate dedicated CPU, the difference can be meaningful. When both VPS and VDS plans use the same CPU policy, the distinction may be mostly naming. Ask these questions: - Is CPU shared, dedicated, reserved, or burstable? - Is sustained 100% CPU usage permitted? - Are virtual CPUs mapped to exclusive processor capacity? - Does the provider publish a fair-use policy? - Can performance be reduced after sustained usage? ### Memory guarantees should be stated clearly Most VPS and VDS plans advertise a fixed memory amount. The guest operating system sees that allocation as system RAM. The important issue is whether the provider guarantees the allocation under load and how aggressively the host platform is overcommitted. Buyers rarely receive full visibility into host-level policy, so the service terms and observed consistency matter. A VDS label may imply a stricter memory guarantee, but it should not be assumed without documentation. ### Storage can remain shared in both models Even a VDS with dedicated CPU may use a shared storage platform. Shared storage is not automatically weak; well-designed storage systems can provide strong availability and performance. The relevant question is how the provider manages latency, throughput, and contention. Compare: - Storage medium - Included capacity - Expansion pricing - Expected latency - Throughput or IOPS limits - Snapshot and backup options - Behavior during heavy neighboring workloads ### Network capacity is rarely physically dedicated per server VPS and VDS plans normally connect through provider-managed network infrastructure. A plan may have a stated port speed or transfer policy, but upstream links and routing remain shared systems. Check whether bandwidth is metered, capped, unmetered, or governed by fair-use rules. A VDS name does not guarantee a dedicated physical network connection. ## Performance and Isolation Should Be Evaluated Separately Performance consistency and security isolation are related to infrastructure quality, but they are not the same property. Both VPS and VDS products can provide strong operating-system isolation. Each virtual machine normally has separate processes, files, users, and network configuration. A dedicated CPU allocation does not automatically make the guest operating system more isolated than a shared CPU allocation. The primary performance risk in shared-resource environments is contention. A neighboring workload may consume processor time, storage throughput, or network capacity. Providers reduce this risk through scheduling, limits, monitoring, and capacity planning. A VDS may reduce CPU contention when the provider reserves processor capacity. It does not necessarily remove storage or network contention. Conversely, a high-quality VPS platform with conservative capacity management can perform more consistently than a poorly managed product labeled VDS. Security should be evaluated through a different checklist: - Guest isolation - Patch responsibility - Firewall controls - Account and key management - Console security - Backup and recovery design - Provider access controls - Incident response scope Neither acronym removes the customer’s responsibility for securing the operating system and applications in an unmanaged service. ## Choose Between VPS and VDS Using Workload Behavior The right choice depends on how the workload consumes resources rather than how important the project sounds. ![VPS and VDS decision framework comparing shared-CPU VPS, dedicated-CPU VPS or VDS, and dedicated servers by workload behavior.](https://raff-images.s3.raffusercloud.com/vps_vs_vds_workload_decision_guide_webp_0cf5326b65.png) | Workload behavior | Better starting point | Reason | | --- | --- | --- | | Intermittent website traffic | Shared-CPU VPS | Efficient for bursty demand and idle periods | | Development or staging | Shared-CPU VPS | Lower cost usually matters more than sustained consistency | | Small API or SaaS application | VPS with enough headroom | General-purpose allocation is often sufficient initially | | Continuous builds or encoding | Dedicated-CPU VPS or VDS | Sustained compute benefits from stronger CPU guarantees | | Busy transactional database | Dedicated-CPU VPS or VDS | More consistent CPU and storage behavior may matter | | Latency-sensitive application | Plan with documented guarantees | Product label alone is not enough | | Large fixed workload needing physical control | Dedicated server | VPS and VDS remain virtualized products | Use this decision framework: 1. **Measure workload shape.** Determine whether CPU demand is bursty or sustained, how much memory is actively used, and whether storage latency affects the application. 2. **Define acceptable variation.** Decide whether occasional performance variation is acceptable or whether predictable execution time is a requirement. 3. **Identify the constrained resource.** Dedicated CPU does not solve a storage-bound or memory-bound workload. 4. **Compare written guarantees.** Ignore the VPS or VDS label until CPU, memory, storage, and network policies are clear. 5. **Include recovery and operations.** Backups, monitoring, support, and resizing can matter more than a small compute difference. Teams that need broader provider-selection criteria can use the [VPS hosting decision guide](/learn/guides/virtual-private-server-hosting). For resource sizing, see the [guide to choosing the right VM size](/learn/guides/choosing-right-vm-size). :::cluster ## Use a Provider Checklist Instead of Trusting the Label Before purchasing either product, ask the provider for precise answers. ### Compute - Is the CPU shared or dedicated? - What does one vCPU represent? - Is sustained CPU use allowed? - Is there a burst limit or fair-use policy? - Can the plan be resized without rebuilding? ### Memory and storage - Is the advertised RAM guaranteed? - What storage medium is used? - Are throughput or IOPS limits published? - Can storage be expanded independently? - How are snapshots and backups priced? ### Networking - What port speed applies? - Is transfer metered or unmetered? - Are there sustained-use restrictions? - Are IPv4, IPv6, and private networking available? - Is DDoS protection included or separate? ### Operations - Who patches the operating system? - What support is included? - What uptime commitment applies? - How are incidents communicated? - What is the restore process? A provider should be treated cautiously when it claims “dedicated” resources but cannot identify which resources are dedicated and under what conditions. ## Raff Uses Resource Type Instead of VDS Terminology Raff does not require buyers to interpret a separate VDS product label. Raff VM presents shared and dedicated CPU options directly, allowing the workload model to drive the choice. Shared CPU plans are intended for general-purpose workloads with variable utilization, including websites, APIs, development environments, and small application servers. Dedicated CPU plans are intended for sustained processing and workloads that benefit from more consistent compute availability. The operating environment remains a virtual machine in both cases. Customers receive an independent operating system, administrative access, memory, NVMe storage, and networking. The meaningful distinction is the CPU allocation model, not a change from “VPS” to “VDS.” Raff VM plans use a 3 Gbps unmetered public bandwidth policy. Backups and snapshots are available as separate protection mechanisms, and each VM includes 3 free backup slots. These features should still be evaluated alongside operating responsibility, application design, and recovery requirements. From an infrastructure perspective, clear resource wording is more useful than introducing another acronym. A buyer should be able to identify whether compute is shared or dedicated without reverse-engineering what a provider means by VDS. ## VPS vs VDS Is Usually a Service-Definition Question VPS and VDS both describe virtual server environments. The term VDS often signals stronger resource guarantees, especially dedicated or reserved CPU capacity, but the industry does not apply that meaning consistently. Do not choose a server because VDS sounds more dedicated or VPS sounds more affordable. Compare the actual CPU policy, memory guarantee, storage behavior, bandwidth terms, support scope, and recovery options. A documented shared-CPU VPS is suitable for many variable workloads. A dedicated-CPU VPS or clearly defined VDS is a better fit when sustained compute consistency matters. A physical dedicated server is a different category when the workload requires exclusive hardware. The best product is the one whose resource guarantees match the workload and whose service boundaries are clear. For a broader comparison of virtual-server terminology, read [VPS vs cloud VM vs cloud server](/learn/guides/vps-vs-cloud-vm-vs-cloud-server-explained). :::cta Explore Raff VM Compare shared and dedicated CPU plans using the resource model your workload actually needs. ::: --- ### KVM VPS vs OpenVZ Containers: Isolation, Kernel Control, and Performance URL: https://rafftechnologies.com/learn/guides/kvm-vps-vs-openvz-containers Description: Compare KVM VPS and OpenVZ containers across isolation, guest kernel control, operating systems, performance, resource guarantees, and workload fit. A KVM VPS is a full virtual machine with its own guest kernel and virtual hardware, while an OpenVZ container is an operating-system-level environment that shares the host kernel. KVM usually provides broader operating-system compatibility and a stronger VM-style boundary; OpenVZ containers usually provide lower virtualization overhead and higher host density. The comparison needs one important clarification. Modern OpenVZ platforms can manage both containers and KVM-based virtual machines. In this guide, **OpenVZ** means the container-based VPS model that hosting providers commonly contrast with a KVM VPS—not every capability of the OpenVZ platform. Neither label guarantees faster hosting. Performance depends on CPU allocation, memory policy, storage latency, network capacity, oversubscription, and provider operations. A well-managed OpenVZ container can outperform a poorly managed KVM VPS, while a properly sized KVM VPS can provide capabilities an OS-level container cannot. For the virtualization layer first, read [what a hypervisor is](/learn/guides/what-is-a-hypervisor). For the wider server architecture, see [how VPS hosting works](/learn/guides/how-vps-hosting-works). ## KVM and OpenVZ Containers Virtualize Different Layers KVM and OpenVZ containers can both present customers with an isolated server-like environment, but they create that environment at different layers. KVM uses hardware-assisted virtualization. The provider creates a virtual machine with virtual CPU, memory, storage devices, networking, firmware, and a guest operating system. The guest boots its own kernel and behaves like an independent computer. An OpenVZ container uses operating-system-level virtualization. The container has its own files, processes, users, resource limits, and network identity, but it runs on the host’s Linux kernel rather than booting a separate guest kernel. A simplified comparison looks like this: ![Virtual machines vs containers diagram showing separate guest operating systems and kernels for VMs and a shared host kernel for containers.](https://raff-images.s3.raffusercloud.com/virtual_machines_vs_containers_isolation_webp_d1b3816508.png) This architectural difference affects kernel control, supported operating systems, device access, isolation boundaries, maintenance behavior, and virtualization overhead. It does not automatically determine the quality of the VPS plan. The provider still decides how resources are allocated and how aggressively the host is shared. ## A KVM VPS Runs as a Full Virtual Machine KVM stands for Kernel-based Virtual Machine. It provides the Linux host with the interfaces needed to create and operate virtual machines. A KVM VPS normally receives: - Virtual CPUs - A defined memory allocation - One or more virtual disks - Virtual network interfaces - Virtual firmware and boot configuration - An independently booted guest operating system - Its own guest kernel The guest operating system sees a virtual computer. It can load its own kernel modules when supported, manage its own boot process, use its own filesystem, and run software that expects a conventional virtual machine. This makes KVM a strong fit when the workload requires: - Linux or Windows guest operating systems - A custom or provider-supported alternative kernel - Kernel-level features inside the guest - Stronger separation between guest environments - Full operating-system installation and boot behavior - Software that expects standard virtual hardware - More control over low-level networking or storage configuration A KVM VPS remains virtualized. The physical CPU, storage platform, network links, and host hardware can still be shared with other VMs unless the provider explicitly offers dedicated hardware. KVM also does not mean every vCPU is dedicated. Providers can offer shared, burstable, reserved, or dedicated CPU plans on KVM infrastructure. The CPU policy must be evaluated separately from the virtualization technology. ## An OpenVZ Container Shares the Host Kernel An OpenVZ container is an isolated Linux environment created at the operating-system layer. Each container can have its own: - Filesystem and installed packages - Processes and process identifiers - Users and permissions - Hostname and network configuration - Resource limits - Startup configuration - Application stack The container feels server-like to the user, but it does not boot an independent kernel. Its processes use the host Linux kernel under container-level isolation and resource controls. This lighter model can reduce virtualization overhead because the provider does not need to run a complete guest kernel for every container. It can also support higher instance density on the physical host. OpenVZ containers can be a practical fit for: - Standard Linux web hosting - Lightweight development environments - Small application servers - Automation tools - Test workloads - Linux services that do not require custom kernels - Cost-sensitive workloads with conventional software requirements The shared-kernel model creates limits. The container cannot run Windows as its guest operating system. It cannot independently boot a different kernel family, and some low-level kernel features may be unavailable or controlled by the provider. The exact capabilities depend on the OpenVZ release, host configuration, container privileges, and provider policy. Buyers should not assume that every OpenVZ service exposes the same kernel features or device access. ## Kernel Control Changes OS and Software Compatibility Kernel control is the clearest practical difference between a KVM VPS and an OpenVZ container. A KVM VM boots its own guest kernel. The provider still controls the physical host and virtualization layer, but the customer can manage the guest operating system as a complete VM. An OpenVZ container shares the host kernel. The customer controls the container’s userspace, packages, files, and applications but does not independently replace or boot the underlying kernel. | Requirement | KVM VPS | OpenVZ container | | --- | --- | --- | | Independent guest kernel | Yes | No | | Linux guest | Yes | Yes, within supported container templates and host compatibility | | Windows guest | Possible when offered by the provider | No | | Custom kernel | Possible within provider and guest constraints | Not independently booted | | Kernel modules | Guest and provider dependent | Primarily controlled at the host level | | Standard VM boot process | Yes | No full guest-kernel boot | | Low-level device features | Possible when exposed by provider | More restricted | | Conventional Linux applications | Strong fit | Strong fit when kernel requirements are standard | This difference matters most when software depends on a particular kernel version, custom kernel module, nested virtualization, low-level network feature, security module, or operating system outside the supported Linux container model. For ordinary websites, APIs, reverse proxies, automation tools, and small Linux services, the workload may not need independent kernel control. In that case, the decision should move to resource guarantees, reliability, backup options, and support rather than kernel architecture alone. ## Isolation and Resource Guarantees Are Separate Questions ![KVM VPS vs OpenVZ resource allocation comparison covering CPU, memory, storage, networking, predictability, and host-level sharing.](https://raff-images.s3.raffusercloud.com/kvm_vps_vs_openvz_resource_allocation_d5c8a1593b.png) KVM and OpenVZ both isolate customer environments, but they do not use the same boundary. A KVM VPS separates complete guest operating systems through a virtual machine boundary. Each VM has its own kernel, virtual memory space, virtual devices, filesystem, processes, and operating-system configuration. An OpenVZ container separates Linux userspace environments while sharing the host kernel. Filesystems, processes, users, and resource controls remain isolated at the container layer, but the kernel is common infrastructure. This usually gives KVM a stronger and more general-purpose isolation model. However, the virtualization type is only one part of security. The complete risk model also includes: - Host patching - Hypervisor or container-runtime maintenance - Provider access controls - Capacity management - Guest operating-system patching - Firewall configuration - Account and key security - Backup and restore design - Monitoring and incident response Resource guarantees are also separate from isolation. A KVM VPS can still use shared CPU, shared storage, and shared networking. An OpenVZ container can have strict CPU and memory limits. The terms KVM and OpenVZ do not reveal how much contention a provider permits. Buyers should verify: - Whether CPU is shared, burstable, reserved, or dedicated - Whether the advertised RAM is guaranteed - Whether swap or memory pressure is handled inside or outside the guest - Which storage limits apply - Whether network transfer is capped or governed by fair use - Whether sustained CPU use is allowed - How the provider responds to noisy-neighbor conditions For the resource terminology behind many provider labels, read [VPS vs VDS](/learn/guides/vps-vs-vds). For compute allocation specifically, see [shared vs dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). ## Performance Depends on Workload and Provider Capacity OpenVZ containers are lighter because they share the host kernel and do not emulate a complete virtual hardware environment for every instance. This can reduce memory consumption and virtualization overhead. KVM introduces a fuller virtual machine layer, but modern hardware-assisted virtualization can still provide strong performance. The VM model also gives the provider and customer clearer guest boundaries and broader operating-system flexibility. The correct conclusion is not that one technology is always faster. Real VPS performance depends on: - Physical processor generation and clock behavior - CPU scheduling and oversubscription - Shared or dedicated CPU policy - Memory allocation and host pressure - Storage latency, throughput, and IOPS - Network capacity and routing - Host density - Workload shape - Provider monitoring and capacity planning A lightweight OpenVZ container can perform well for a standard Linux service when the host is managed conservatively. A KVM VPS can perform well for sustained applications when CPU, memory, storage, and networking are allocated appropriately. Both can perform badly when too many workloads compete for the same host resources. ### Workload shape matters more than synthetic labels A small web server that spends most of its time idle may not benefit from the fuller KVM boundary if it has no kernel-specific requirements. A database, build worker, security appliance, custom networking workload, or Windows application may need the control and compatibility of a full VM. A benchmark should also be interpreted carefully. Short CPU tests can reward burst capacity. Storage benchmarks can change depending on cache state and neighboring activity. Network tests may reflect routing and location more than virtualization overhead. The better question is: > Does this service provide the control, consistency, compatibility, and recovery model required by the workload? ## Use a Decision Framework Instead of Picking by Label Choose based on technical requirements first, then compare provider implementation. ![KVM VPS vs OpenVZ comparison showing differences in kernel control, isolation, operating system support, root access, performance, and workload fit.](https://raff-images.s3.raffusercloud.com/kvm_vps_vs_openvz_isolation_workload_fit_webp_5a538e376e.png) | Workload requirement | Better starting point | Why | | --- | --- | --- | | Windows operating system | KVM VPS | Requires a separate guest operating system and kernel | | Custom guest kernel | KVM VPS | Full VM can boot its own supported kernel | | Standard Linux website | Either | Resource quality and provider operations matter more | | Lightweight Linux service | OpenVZ can fit | Lower-overhead container model may be sufficient | | Docker host | Usually KVM VPS | Full VM boundary and kernel control reduce compatibility uncertainty | | Kernel modules or low-level networking | KVM VPS | More guest-level control when provider permits it | | Simple development sandbox | Either | Choose based on price, recovery, and required features | | Stronger VM-style isolation | KVM VPS | Independent guest kernel and virtual hardware boundary | | Maximum density for standard Linux workloads | OpenVZ container | Shared-kernel model reduces per-instance overhead | | Sustained CPU workload | Plan with documented CPU guarantees | Virtualization label alone is insufficient | | Nested virtualization | KVM, only when explicitly supported | Requires host and provider support | | Lowest-cost Linux environment | Compare both | Provider pricing and resource policy decide value | Use this sequence: 1. **Check operating-system requirements.** Windows or a nonstandard guest environment points toward a full VM. 2. **Identify kernel dependencies.** Custom modules, kernel versions, nested virtualization, or low-level networking usually favor KVM. 3. **Measure workload behavior.** Determine whether CPU, memory, storage, or network consistency is the real constraint. 4. **Read the provider’s resource policy.** Shared versus dedicated CPU and sustained-use rules matter more than the brand name. 5. **Compare recovery and support.** Snapshots, backups, console access, rebuild options, and support scope affect operational risk. 6. **Avoid paying for control you do not need.** A conventional Linux workload can run well without custom kernel access when the service is managed properly. ## Ask the Provider These Questions Before Buying A provider that advertises KVM VPS or OpenVZ VPS should explain what the label means in its own platform. ### Virtualization and operating system - Is the service a full VM or an OS-level container? - Does the instance boot its own guest kernel? - Which Linux distributions are supported? - Is Windows supported? - Can the kernel be changed? - Are custom kernel modules allowed? - Is nested virtualization available? ### Compute and memory - Is CPU shared or dedicated? - Is sustained CPU usage permitted? - What does one vCPU represent? - Is the advertised RAM guaranteed? - Are memory or process limits applied outside the guest? ### Storage and networking - What storage technology is used? - Are throughput or IOPS limits published? - Can storage expand independently? - What bandwidth and transfer policy applies? - Are private networking and IPv6 available? ### Recovery and operations - Are snapshots and automated backups available? - Can the instance be rebuilt from an image? - Is browser console access provided? - Who handles host-level security updates? - What support and uptime commitments apply? A transparent provider should answer these questions without relying on “KVM” or “OpenVZ” as a substitute for service details. :::cluster ## Raff VM Keeps the Customer Decision at the Resource Level Raff’s customer-facing VM plans are organized around resources and workload behavior rather than asking buyers to choose a virtualization brand. Shared CPU plans fit general-purpose workloads with variable utilization. Dedicated CPU plans fit sustained processing and applications that benefit from more consistent compute access. The customer also evaluates memory, NVMe storage, networking, backup protection, operating-system support, and management responsibility. This is the practical lesson from KVM vs OpenVZ: virtualization architecture matters when it changes compatibility, kernel control, or the isolation boundary. For most hosting decisions, however, the service must also make resource allocation and operational limits clear. Raff VM plans use a 3 Gbps unmetered public bandwidth policy and include 3 free backup slots per VM. Those customer-visible details describe how the server can be operated and protected. They do not disclose or require assumptions about Raff’s internal virtualization implementation. KVM is usually the stronger fit when a workload needs a full guest operating system, independent kernel, Windows support, or broader low-level control. An OpenVZ container can be efficient for conventional Linux workloads that do not require those capabilities. Neither technology should be treated as an automatic performance ranking. Choose the boundary and compatibility model the workload needs, then verify CPU policy, memory guarantees, storage behavior, network terms, recovery options, and provider operations through the [VPS hosting decision guide](/learn/guides/virtual-private-server-hosting). :::cta Explore Raff VM Compare virtual server plans by resource allocation, workload fit, and recovery requirements. ::: --- ### VPS vs Dedicated Server: Cost, Performance, and When to Upgrade URL: https://rafftechnologies.com/learn/guides/vps-vs-dedicated-server Description: Compare VPS and dedicated servers by cost, performance, isolation, scaling, recovery, and the workload signals that justify upgrading to physical hardware. A VPS is a virtual server with an independent operating system and allocated resources on provider-managed physical infrastructure. A dedicated server gives one customer control of an entire physical machine. The practical difference is not that one is professional and the other is basic: a VPS prioritizes flexibility and efficient resource use, while a dedicated server prioritizes hardware exclusivity and large, stable capacity. Most small teams should remain on a VPS until their workload has measurable requirements that virtualization cannot meet economically. High sustained utilization, specialized hardware needs, strict physical-isolation requirements, or predictable demand large enough to justify an entire server are stronger upgrade signals than traffic growth alone. This guide compares VPS and dedicated servers across cost, performance, isolation, scaling, operations, and migration risk. For the broader hosting decision first, use the [VPS hosting decision guide](/learn/guides/virtual-private-server-hosting). ## VPS and Dedicated Servers Allocate Hardware Differently A VPS runs as an isolated virtual machine. The provider’s virtualization layer presents virtual CPU, memory, storage, networking, and firmware to the guest operating system. Multiple virtual machines can run on the same physical host while maintaining separate filesystems, processes, users, and operating-system configurations. ![VPS vs dedicated server architecture showing isolated virtual machines on shared provider infrastructure and an entire physical server assigned to one customer.](https://raff-images.s3.raffusercloud.com/vps_vs_dedicated_server_architecture_webp_e905fb9de2.png) A dedicated server assigns the entire physical machine to one customer. Its processors, installed memory, local storage devices, and server chassis are not divided into customer VMs by the hosting provider unless the customer chooses to run its own virtualization layer. The architectural distinction is straightforward: A dedicated server is also often described as a bare-metal server. In hosting comparisons, both terms usually mean that the customer rents physical hardware without another customer’s VM running on the same machine. Providers may still distinguish bare metal through faster automated provisioning or cloud-style APIs, so service details should be verified. A dedicated CPU VPS is not the same as a dedicated server. A virtual machine may receive reserved or more exclusive processor capacity while still using provider-managed virtualization, storage, networking, and host infrastructure. The [shared vs dedicated vCPU guide](/learn/guides/shared-vs-dedicated-vcpu) explains that narrower compute decision. ## VPS vs Dedicated Server Comparison The right model depends on whether the workload benefits more from virtual-machine flexibility or whole-machine control. | Factor | VPS | Dedicated server | | --- | --- | --- | | Customer environment | Independent virtual machine | Entire physical machine | | Physical hardware | Shared host infrastructure | Exclusive server hardware | | CPU model | Shared or dedicated vCPU, depending on plan | Full installed processor capacity | | Memory | Defined VM allocation | Full installed system memory | | Storage | Virtual disks on provider storage or local host storage | Direct use of installed disks or provider-attached storage | | Initial cost | Usually lower | Usually higher | | Deployment speed | Often minutes | Usually slower, though automated bare metal can be fast | | Resizing | Often simple within platform limits | Commonly requires hardware change or migration | | Operating-system control | Full guest-level control | Full machine-level control | | Custom hardware | Limited | Possible when provider offers options | | Physical tenant isolation | No | Yes at the server level | | Best fit | Variable, growing, or moderate workloads | Large stable workloads and hardware-specific requirements | The table describes the infrastructure category, not a guaranteed service level. A poorly sized dedicated server can be slower than a modern VPS. A high-quality VPS can provide better storage, networking, automation, and recovery tooling than an older physical server. The product label should therefore begin the comparison, not finish it. ## Cost Depends on Utilization, Not Only Monthly Price A VPS usually has a lower starting price because the provider can allocate physical capacity efficiently across several customers. A small team can select the CPU, memory, and storage it needs without paying for an entire machine. A dedicated server has a higher minimum commitment. The customer pays for the machine whether its resources are fully used or mostly idle. This creates two different cost models: > VPS value comes from buying the capacity needed now. Dedicated-server value comes from using enough of a whole machine to justify the commitment. A dedicated server may become cost-effective when a workload continuously consumes a large amount of CPU, memory, storage throughput, or local disk capacity. At that point, buying equivalent high-end virtual-machine capacity can cost as much as or more than renting one physical server. However, the server price is only part of total cost. | Cost area | VPS consideration | Dedicated-server consideration | | --- | --- | --- | | Compute | Pay for selected VM size | Pay for the whole machine | | Idle capacity | Usually limited | Can be substantial | | Hardware replacement | Provider responsibility | Provider responsibility, but replacement may take longer | | Scaling | Resize or deploy another VM | Upgrade hardware or migrate | | Backups | Platform option or external system | Must be designed around the physical server | | High availability | Add VMs and distribute workloads | Requires another server or recovery target | | Licensing | Based on guest OS and software | May be affected by sockets, cores, or physical deployment | | Operations | Guest OS and applications | OS, applications, hardware-aware design, and recovery planning | Dedicated hardware can reduce unit cost at high sustained utilization, but it can increase operational concentration. If the entire application, database, and storage stack lives on one large server, that machine becomes a significant failure domain. Small teams should compare the cost of a working system rather than a single server. Include backups, secondary capacity, migration time, licenses, monitoring, and the impact of hardware failure. The [cloud server cost guide](/learn/guides/cloud-server-cost-2026) provides the broader cost framework. ## Performance Is About Consistency, Capacity, and Bottlenecks Dedicated servers provide direct access to the installed hardware and remove contention from other customer VMs on the same machine. This can improve predictability for sustained workloads and provide access to larger local resource pools. That does not mean a dedicated server is always faster. A VPS may run on newer processors, faster NVMe storage, a better network, or a platform with stronger automation than an available dedicated server. It may also be easier to select a dedicated-CPU VM without accepting the operational commitment of a physical machine. Performance should be evaluated by resource: ### CPU A dedicated server gives the customer the installed processor capacity. This is useful for continuous builds, rendering, encoding, analytics, simulation, high-volume game workloads, or other compute that can keep many cores active. A VPS remains a strong fit when CPU demand is moderate, bursty, or can be handled through dedicated vCPU plans. Moving to physical hardware solely because a shared-CPU VPS is inconsistent skips an important intermediate option. ### Memory Dedicated servers can provide large memory configurations at a favorable unit cost. They become attractive when the workload needs a consistently large working set, such as an in-memory database, cache, analytics engine, or many consolidated services. A VPS is more efficient when the application needs a smaller allocation or when memory requirements are still changing. ### Storage Dedicated hardware can offer direct local NVMe performance and predictable disk access, but local disks create a recovery question. If the machine fails, the application needs backups, replicated data, or another recovery target. A VPS may use local or distributed provider storage. The virtualized model does not reveal storage quality by itself. Compare latency, throughput, IOPS, durability, expansion, snapshots, and backup design. ### Networking A dedicated server can have a defined physical network interface, but upstream switching, transit, and internet routes are still provider infrastructure. Dedicated hardware does not automatically mean a dedicated end-to-end network path. For either model, verify port speed, transfer policy, routing, private networking, DDoS protection, and sustained-use limits. The strongest performance decision begins with measurements. Determine whether the current constraint is CPU contention, memory capacity, disk latency, network throughput, or application design before changing infrastructure categories. ## Isolation Improves, but Responsibility Also Increases A VPS provides logical isolation. Each virtual machine normally has its own operating system, files, users, processes, and virtual network interfaces. The provider controls the physical host and virtualization layer. A dedicated server adds physical tenant isolation at the machine level. Another customer does not run a VM on the same server hardware. This can matter when: - A policy requires single-tenant physical infrastructure - The application handles sensitive data under a defined isolation requirement - Licensing depends on physical sockets or cores - A workload needs direct device access - The team must control the machine-level virtualization layer - Host-level contention is unacceptable Physical isolation does not remove security responsibility. The customer still needs operating-system updates, access control, firewall rules, service hardening, monitoring, backups, credential management, and incident response. It can also expand the responsibility boundary. A team that installs its own hypervisor on dedicated hardware now owns virtual-machine placement, host updates, capacity planning, and recovery at that layer. For most small teams, strong virtual-machine isolation plus clear resource guarantees is sufficient. Dedicated hardware should be selected when physical tenancy is a documented requirement, not because the word “dedicated” simply sounds safer. ## Scaling and Recovery Favor Different Models ![VPS vs dedicated server diagram comparing flexible resizing and multiple virtual machines with fixed physical capacity, hardware upgrades, and recovery planning.](https://raff-images.s3.raffusercloud.com/vps_vs_dedicated_server_scaling_recovery_webp_f4c652d2dc.png) VPS platforms are designed for change. A team can often resize a VM, attach storage, create another instance, clone an image, or distribute services across several servers without waiting for physical hardware changes. This flexibility is valuable when demand is uncertain. The team can begin with a smaller server, observe real usage, and adjust the architecture as the workload grows. Dedicated servers favor stable capacity. They provide a large fixed resource pool, but vertical upgrades can require migration to another machine. Horizontal scaling requires purchasing and operating additional servers. | Change | VPS | Dedicated server | | --- | --- | --- | | Add CPU or RAM | Often resize plan | Hardware upgrade or migration may be required | | Add another server | Deploy another VM | Provision another physical machine | | Replace failed host | Provider platform may recreate or move the VM | Hardware repair or replacement process applies | | Create test environment | Clone image or deploy smaller VM | Usually requires another VM layer or server | | Build high availability | Multiple VMs and services | At least 2 physical servers plus coordination | | Reduce capacity | Resize or remove VM | Continue paying or migrate to smaller hardware | A dedicated server is not automatically more reliable than a VPS. It removes one type of shared-host risk, but it concentrates the workload on one physical machine. High availability still requires redundancy. For both models, define: - Recovery Point Objective - Recovery Time Objective - Backup frequency and retention - Restore procedure - Replacement capacity - DNS or traffic cutover plan - Database consistency requirements The migration path matters as much as the destination. Moving from VPS to dedicated hardware can involve copying data, rebuilding the operating system, transferring secrets, testing storage, changing IP addresses, updating DNS, and planning rollback. ## Use a Workload Decision Framework Choose the server model by workload behavior and operating constraints. ![Decision framework showing the progression from shared CPU VPS to larger VPS, dedicated CPU, multiple virtual machines, and a dedicated server only when justified.](https://raff-images.s3.raffusercloud.com/vps_to_dedicated_server_upgrade_framework_webp_794486276d.png) | Requirement | Better starting point | Reason | | --- | --- | --- | | New application with uncertain demand | VPS | Lower commitment and easier resizing | | Website, API, or SaaS app with moderate usage | VPS | Flexible resources and simpler operations | | Development and staging | VPS | Fast deployment and lower idle cost | | Sustained CPU workload | Dedicated-CPU VPS first; dedicated server at larger scale | Test whether reserved compute solves the problem | | Very large stable memory requirement | Dedicated server may fit | Whole-machine memory can improve unit economics | | Physical single-tenancy requirement | Dedicated server | Entire server assigned to one customer | | Custom accelerator or device requirement | Dedicated server | Direct hardware options may be necessary | | Large local-storage workload | Dedicated server may fit | Direct disks can provide capacity and throughput | | Workload must shrink or grow frequently | VPS | Capacity can change more easily | | Multi-environment product team | VPS | Separate production, staging, and test instances | | Large predictable 24/7 utilization | Compare total cost | Dedicated hardware may become economical | | Small team without hardware-level operations | VPS | Provider retains more infrastructure responsibility | Use four questions: 1. **Is the current VPS actually constrained?** Confirm the resource and duration of the bottleneck. 2. **Can a larger or dedicated-CPU VPS solve it?** Test the simpler upgrade before changing infrastructure models. 3. **Will the workload use most of a physical machine continuously?** Dedicated economics weaken when capacity remains idle. 4. **Can the team operate and recover the physical-server design?** Include redundancy and migration, not only benchmark performance. ## Upgrade From VPS When the Evidence Is Clear A dedicated server becomes reasonable when several of these signals appear together: - CPU utilization remains high for long periods across a large VM - Dedicated vCPU no longer provides enough capacity or value - Memory requirements are large, stable, and expensive in VM form - Local storage throughput or capacity is central to the workload - Physical single-tenancy is required by contract or policy - Specialized hardware or device access is necessary - The application can use most of the server continuously - The team has a tested backup, replacement, and migration plan - The cost of equivalent VM capacity is consistently higher Traffic growth by itself is not an upgrade trigger. A busy application may still run efficiently across multiple VMs, while a low-traffic database may require dedicated hardware because of memory or storage behavior. The best upgrade signal is a measured constraint combined with a clear economic or technical benefit. Avoid moving because the server appears more serious, because a competitor uses bare metal, or because one benchmark looks faster. Those reasons do not account for recovery, scaling, utilization, or operational cost. ## Stay on VPS When Flexibility Has More Value A VPS remains the better option when: - Demand is still changing - The workload fits comfortably within available VM sizes - A dedicated-CPU plan provides enough consistency - Multiple small environments are more useful than one large machine - Rapid deployment and rebuilding matter - The team wants provider-managed host infrastructure - Capacity may need to decrease later - Physical single-tenancy is not required - The application architecture benefits from several failure domains For many startups and small teams, the correct path is not VPS followed automatically by dedicated server. It may be: ```text Small shared-CPU VPS ↓ Larger VPS ↓ Dedicated-CPU VPS ↓ Multiple VMs or separated services ↓ Dedicated server only when economics or hardware requirements justify it ``` This path keeps the infrastructure proportional to the workload. Use the [VM sizing guide](/learn/guides/choosing-right-vm-size) to determine whether the current problem is plan size rather than server type. :::cluster ## Raff VM Fits the VPS Side of the Decision Raff VM is designed for teams that need a clear virtual-server model with shared or dedicated CPU options, memory, NVMe storage, networking, operating-system control, snapshots, and backups. Raff does not need a dedicated-server claim to make this comparison useful. The practical Raff fit is the period before physical hardware becomes necessary: development, websites, APIs, SaaS applications, databases, Docker hosts, internal systems, Windows workloads, and sustained compute that can be handled through dedicated CPU. A Raff VM gives the customer an independent operating system while Raff operates the underlying host infrastructure. Shared CPU plans suit variable general-purpose demand. Dedicated CPU plans provide a stronger option when sustained processing and compute consistency matter. The buyer should still monitor CPU, memory, storage, network behavior, and recovery requirements. If a workload eventually requires an entire physical machine, specialized hardware, or contractual physical isolation, that requirement should drive the next infrastructure decision. ## Choose Dedicated Hardware Only When It Solves a Defined Constraint VPS and dedicated servers are not entry-level and advanced versions of the same product. They optimize for different operating models. A VPS gives small teams flexible capacity, fast deployment, lower minimum cost, and a provider-managed physical layer. A dedicated server gives one customer the whole machine, which can improve physical isolation, stable high-capacity economics, and hardware control. Remain on VPS while virtual-machine resources meet the workload safely and economically. Consider dedicated hardware when utilization is large and stable, physical tenancy is required, specialized devices are necessary, or equivalent VM capacity no longer makes financial sense. Before changing categories, test whether a larger or dedicated-CPU VM resolves the issue. Measure the bottleneck, model total cost, plan migration and rollback, and include redundancy in the dedicated-server design. :::cta Explore Raff VM Compare shared and dedicated CPU VM options before committing to the cost and operational model of an entire physical server. ::: --- ### Managed vs Unmanaged VPS: Responsibilities, Support, and Total Cost URL: https://rafftechnologies.com/learn/guides/managed-vs-unmanaged-vps Description: Compare managed and unmanaged VPS hosting by responsibility, support scope, security, backups, control, and the true cost of operating a server. A managed VPS includes an agreed layer of server administration from the provider, while an unmanaged VPS gives the customer control of the virtual machine and leaves operating-system and application management primarily to the customer. The difficult part is that **managed** is not a standardized service level. One provider may include security updates and monitoring; another may only help with a control panel or respond when the customer opens a ticket. The right choice therefore depends less on the label and more on the responsibility boundary. Buyers should verify who handles patching, firewall configuration, backups, restore testing, monitoring, malware response, performance troubleshooting, application errors, migrations, and after-hours incidents. For most technically capable teams, an unmanaged VPS offers lower direct cost and more control. A managed VPS can be worth the premium when operational time, recovery risk, or the lack of Linux administration skills would otherwise become the real bottleneck. ## Managed and Unmanaged VPS Describe Responsibility, Not Hardware Managed and unmanaged VPS plans can use similar CPU, memory, storage, networking, and virtualization infrastructure. The distinction is usually about **who operates the guest environment after provisioning**. ![Managed vs unmanaged VPS responsibility stack showing the same provider infrastructure with different ownership of the guest operating system, security, monitoring, backups, and applications.](https://raff-images.s3.raffusercloud.com/managed_vs_unmanaged_vps_responsibility_stack_webp_6ffa983373.png) With an unmanaged VPS, the provider normally operates the physical server, virtualization layer, data-center network, and platform control plane. The customer receives access to the VM and takes responsibility for the guest operating system and the software running inside it. With a managed VPS, the provider also accepts some operating responsibility inside the VM. The exact scope varies by provider and plan. A simplified responsibility model looks like this: | Layer | Unmanaged VPS | Managed VPS | | --- | --- | --- | | Physical hardware | Provider | Provider | | Virtualization platform | Provider | Provider | | Data-center networking | Provider | Provider | | VM provisioning | Provider | Provider | | Guest operating system | Customer | Shared or provider, depending on scope | | Security updates | Customer | May be included | | Firewall configuration | Customer | May be included | | Monitoring | Customer | May be included | | Backups | Customer must configure and verify | May be configured or monitored | | Web server and runtime | Customer | May be included | | Application code | Customer | Usually customer | | Database administration | Customer | Sometimes available as an add-on | | Incident response | Customer coordinates | Shared, within documented scope | The words “managed VPS” do not reveal which rows the provider owns. The service description, support policy, and exclusions are more important than the product name. For the infrastructure layer itself, read [how VPS hosting works](/learn/guides/how-vps-hosting-works). ## What an Unmanaged VPS Usually Requires From the Customer An unmanaged VPS is a full-control server environment. The provider gives the customer the VM, credentials or SSH-key access, network connectivity, and platform tools. The customer builds and operates the software stack. Typical customer responsibilities include: - Choosing and installing the operating system - Creating users and securing SSH access - Applying operating-system security updates - Configuring the firewall - Installing the web server, runtime, database, or container engine - Managing TLS certificates - Monitoring CPU, memory, disk, network, and services - Configuring backups and retention - Testing restores - Investigating application and operating-system errors - Handling compromised credentials or malware - Planning upgrades and migrations - Recovering the service after a bad deployment or configuration change Unmanaged does not mean unsupported. A provider may still help with platform issues, networking, VM lifecycle operations, snapshots, backups, billing, and migration. It means that the customer should not assume the provider is continuously administering the guest operating system or application stack. An unmanaged VPS works well when the team already knows how to operate Linux or Windows servers, has repeatable deployment and monitoring processes, and wants control over versions, configuration, and architecture. It becomes risky when the server is launched by someone who can install an application but cannot confidently secure, monitor, update, and recover it. ## What a Managed VPS May Include A managed VPS adds provider work inside the guest environment, but packages vary widely. Common managed services may include: - Initial server setup - Operating-system updates - Security hardening - Control-panel installation - Web server and PHP configuration - Firewall rules - Basic monitoring - Backup scheduling - Restore assistance - Malware scanning or cleanup - Performance investigation - Service restart and recovery - Migration assistance - Proactive alert response Some plans are **reactive**. The provider helps only after the customer opens a ticket. Others are **proactive**. The provider monitors services, applies updates, responds to alerts, and performs scheduled maintenance without waiting for a request. Some providers manage only approved software stacks, such as cPanel, Plesk, Apache, Nginx, PHP, MySQL, or WordPress. Custom Docker deployments, Kubernetes, unusual databases, application code, CI/CD systems, and third-party agents may be outside scope. That leads to the most important buying rule: > Do not buy “managed VPS.” Buy a written list of responsibilities, response targets, and exclusions. ## Support Is Not the Same as Server Management Fast technical support and managed administration are related but different services. ![Technical support vs server management diagram comparing customer-initiated reactive assistance with proactive monitoring, patching, alert response, and ongoing operational ownership.](https://raff-images.s3.raffusercloud.com/vps_support_vs_server_management_webp_116a7f9a9b.png) Support usually helps the customer diagnose or resolve a problem. Management means the provider has accepted an ongoing operational responsibility. Examples of support: - Explaining why a VM cannot reach the network - Helping recover access through a console - Investigating a platform or storage issue - Assisting with a snapshot or retained backup - Answering API or billing questions - Helping plan or perform a migration Examples of management: - Applying operating-system updates on a schedule - Monitoring services continuously - Responding to alerts without a customer ticket - Maintaining firewall and SSH policies - Managing web-server configuration - Testing backup restoration - Patching a control panel - Owning an application-level incident runbook A provider can offer excellent support without selling a fully managed VPS. Buyers should not treat response speed, live chat, or access to engineers as proof that every operating-system and application task is included. The correct question is: > When something breaks at 2 AM, who is expected to detect it, who is expected to act, and which parts of the stack are covered? ## Compare Total Cost, Not Only the Monthly Plan An unmanaged VPS usually has a lower direct price because the customer supplies the operational labor. A managed VPS adds labor, tooling, and responsibility to the provider’s cost. The real comparison is: ```text Unmanaged total cost = VM price + engineering time + monitoring and backup tooling + incident risk + maintenance work Managed total cost = VM price + management fee + customer work outside scope + add-ons and escalation costs ``` A cheap unmanaged server can become expensive when a developer repeatedly interrupts product work to patch systems, investigate disk pressure, repair certificates, or recover failed services. A managed plan can also become poor value when the team already has automation and operational skill, or when the provider excludes the exact application stack the team uses. | Cost factor | Unmanaged VPS | Managed VPS | | --- | --- | --- | | Monthly infrastructure price | Usually lower | Usually higher | | Internal administration time | Higher | Lower within scope | | Tooling | Customer selects and pays | Some tools may be included | | Emergency labor | Customer responsibility | Included or billed, depending on plan | | Application debugging | Customer | Usually customer | | Backup verification | Customer | May be shared or included | | Control and customization | Higher | May be constrained | | Predictability | Depends on team maturity | Depends on contract clarity | The financial decision should include the value of the operator’s time and the cost of downtime. A founder spending five hours each month on routine server work may be paying more than the difference between managed and unmanaged plans, even when that labor does not appear on an invoice. ## Security Depends on Ownership and Execution A managed VPS is not automatically secure, and an unmanaged VPS is not automatically unsafe. Security depends on whether required tasks are assigned, performed, and verified. Important responsibilities include: - Operating-system patching - Package and runtime updates - SSH hardening - Firewall management - Least-privilege access - Credential and key rotation - Log review - Vulnerability response - Malware investigation - Backup isolation - Restore testing - Incident communication With an unmanaged VPS, the customer owns these tasks. With a managed VPS, some may move to the provider, but application security, user permissions, code vulnerabilities, secrets, and business logic usually remain customer responsibilities. A dangerous managed-service assumption is: > The provider manages the server, so our application is secure. The provider cannot usually correct insecure application code, weak user roles, exposed API keys, vulnerable dependencies, or unsafe business logic unless those services are explicitly included. Before purchase, map every security task to an owner. Shared responsibility without named ownership often becomes no responsibility. ## Backups and Recovery Need Separate Verification “Backups included” can describe several different services: - The platform provides a backup feature, but the customer must enable it - The provider schedules backups but does not test restores - The provider monitors backup jobs - The provider performs restoration only after a ticket - The provider manages application-consistent backups - The provider retains complete server images but not external data Buyers should verify: 1. What is backed up? 2. How often does backup run? 3. How long is data retained? 4. Is backup stored outside the primary VM? 5. Who monitors failed jobs? 6. Who initiates a restore? 7. Has the restore process been tested? 8. What recovery time is realistic? 9. Are databases application-consistent? 10. What happens if the customer deletes the VM or account? A managed VPS may reduce recovery work, but it does not remove the need for a recovery objective. The customer still needs to know how much data can be lost and how quickly service must return. ## Control and Flexibility Usually Favor Unmanaged VPS An unmanaged VPS gives the customer freedom to choose: - Operating-system version - Package sources - Web server - Container runtime - Database engine - Monitoring stack - Backup tooling - Security policies - Deployment workflow - Network configuration - Upgrade schedule That freedom is useful for developers, DevOps teams, SaaS products, custom application stacks, Docker hosts, and infrastructure automation. Managed providers may restrict support to approved distributions, versions, panels, or configurations. A customer can sometimes install unsupported software, but the provider may refuse to troubleshoot it. This does not make managed plans worse. Standardization is how providers deliver consistent administration efficiently. It does mean that teams with unusual software or strong internal automation should check whether management creates friction instead of reducing it. ## Use a Decision Framework ![Managed vs unmanaged VPS decision framework comparing customer-operated, co-managed, and provider-managed models by skills, time, software support, operational scope, and incident ownership.](https://raff-images.s3.raffusercloud.com/managed_vs_unmanaged_vps_decision_framework_webp_b005e492a9.png) | Situation | Better starting point | Why | | --- | --- | --- | | Developer or DevOps team with server experience | Unmanaged VPS | Control and lower direct cost | | Small business without an administrator | Managed VPS | Routine operations need an owner | | Custom Docker or application stack | Unmanaged VPS | Fewer support-scope restrictions | | Standard WordPress or control-panel hosting | Managed VPS may fit | Standardized management can reduce workload | | Production service with no monitoring process | Managed VPS or external operations help | Detection and response need ownership | | Strict configuration requirements | Unmanaged VPS | Full control over system design | | Founder wants to avoid server maintenance | Managed VPS | Time may be more valuable than the fee | | Team already uses configuration management and monitoring | Unmanaged VPS | Existing automation reduces management value | | Compliance requires documented patching and response | Compare written scope | Either can work when evidence and ownership are clear | | Low-risk development environment | Unmanaged VPS | Operational risk is limited | | Revenue-critical application with a small team | Managed or co-managed model | Risk and after-hours response matter | Use these five questions: 1. **Can the team securely operate the server today?** Installing software is not the same as maintaining it. 2. **How much internal time will routine operations consume?** Include updates, monitoring, backups, and incidents. 3. **What does the managed plan actually cover?** Read exclusions before comparing price. 4. **Does the provider support the required stack?** Custom software can fall outside management scope. 5. **Who acts during an outage?** Detection, escalation, repair, and communication must have owners. ## Questions to Ask a Managed VPS Provider Before purchasing, ask for specific answers: ### Operating system and patching - Which operating systems and versions are supported? - Are security updates automatic or scheduled? - Are reboots coordinated? - Are third-party repositories supported? - Who handles major-version upgrades? ### Monitoring and incident response - Is monitoring proactive or ticket-based? - Which services are monitored? - Does the provider act on alerts automatically? - What coverage exists outside business hours? - What response and resolution targets apply? ### Applications and control panels - Which web servers, runtimes, databases, and panels are covered? - Is Docker supported? - Is application-code debugging included? - Are performance optimizations included? - Which custom configurations void support? ### Backups and recovery - Are backups included, enabled, and monitored? - Are restores tested? - Is database-consistent recovery supported? - Who performs restoration? - Are recovery times documented? ### Security - Who manages the firewall and SSH policy? - Is malware response included? - Are vulnerability scans included? - Who rotates credentials after an incident? - Is remediation billed separately? ### Commercial scope - Is management included in the plan or sold separately? - Are there limits on support time or tickets? - Are emergency interventions billable? - Can the customer retain root access? - What actions require customer approval? The answers should be written into the service description or agreement. Verbal assurances are difficult to rely on during an incident. :::cluster ## How Raff Fits the Decision Raff provides full-control cloud VMs with root access, platform tooling, backups and snapshots, networking features, API access, and direct technical support. Raff’s public support documentation covers areas such as VM creation and configuration, networking issues, backup-based recovery, images, snapshots, API and CLI questions, and migration assistance. That support should not be confused with an undefined promise to administer every operating system, control panel, database, container stack, or custom application. Teams should keep ownership of their guest environment clear and confirm any application-level management expectations before deployment. Raff is therefore a strong fit for customers who want the control of an unmanaged or self-managed VM without being left alone when platform, migration, networking, recovery, or infrastructure questions arise. For standard applications, teams can combine Raff VM with documentation, automation, monitoring, and backup processes. Organizations that need ongoing guest-OS or application administration can add an internal operator, MSP, or specialized management partner while keeping the infrastructure on Raff. ## Choose the Responsibility Model Your Team Can Operate Managed and unmanaged VPS hosting can use similar infrastructure. The decisive difference is who owns the work after the server is deployed. Choose unmanaged VPS when your team can secure, update, monitor, back up, and recover the server reliably—and when control is worth the internal labor. Choose managed VPS when the provider’s documented scope removes operational work your team cannot or should not own. Confirm exactly what is proactive, what is reactive, which software is supported, and which tasks remain yours. Do not compare only monthly prices. Compare responsibility, response, recovery, exclusions, and the cost of engineering time. The best server model is the one where every production task has a clear owner before an incident begins. :::cta Explore Raff VM Deploy a full-control cloud VM with direct infrastructure support, flexible resources, backups, networking, and migration assistance. ::: ## Sources - [Raff VM Support Documentation](https://docs.rafftechnologies.com/products/build/virtual-machines/details/support) - [Raff Virtual Machines](https://rafftechnologies.com/products/raff-vm) - Date verified: 2026-07-28 --- ### VPS Hosting With or Without cPanel: Cost, Control, and Management Trade-Offs URL: https://rafftechnologies.com/learn/guides/vps-with-or-without-cpanel Description: Compare VPS hosting with and without cPanel across license cost, resource use, control, email, security, multi-site management, and custom app compatibility. A VPS with cPanel adds a graphical web-hosting control panel on top of the server. A VPS without cPanel is managed through the operating system, command line, automation, or another control panel. The underlying VPS can be identical; the difference is how websites, domains, email, databases, SSL certificates, users, and server settings are administered. cPanel is usually worth considering when one server hosts several traditional websites and the operator values a familiar interface more than maximum flexibility. It is less attractive for Docker-based apps, custom deployment pipelines, infrastructure-as-code workflows, or teams that already manage Linux directly. The key decision is not whether cPanel is easier. It usually is for common hosting tasks. The decision is whether that convenience justifies the license cost, resource use, operational constraints, and extra software layer. ## What cPanel Adds to a VPS cPanel is a commercial control panel for Linux web hosting. It typically combines two interfaces: - **cPanel** for website and account-level administration - **WHM** for server, package, reseller, and hosting-account administration On a VPS, this layer can centralize: - Website and domain management - DNS zones - Email accounts and mail routing - Databases and database users - SSL certificate workflows - File management - FTP accounts - Backups and restore interfaces - Resource packages and account limits - Hosting-account creation - Basic security and service configuration Without cPanel, these same capabilities still exist, but they are managed through individual tools such as the Linux shell, Nginx or Apache configuration, systemd, database clients, DNS providers, certificate automation, monitoring platforms, and deployment pipelines. The panel does not create new server resources. It organizes and automates access to existing services. ## cPanel Does Not Make a VPS Managed A VPS can be unmanaged and still run cPanel. A managed VPS can also use a different panel or no panel at all. These are separate decisions: | Decision | Main question | | --- | --- | | Managed vs unmanaged VPS | Who operates and maintains the server? | | cPanel vs no cPanel | Which interface and software stack manages hosting tasks? | Installing cPanel does not automatically transfer responsibility for: - Operating-system updates - Monitoring - Incident response - Backup verification - Malware cleanup - Application debugging - Capacity planning - Security policy - Restore testing The panel can simplify these tasks, but someone still needs to own them. For the responsibility model, read [Managed vs Unmanaged VPS](/learn/guides/managed-vs-unmanaged-vps). ## Compare the Two Models | Factor | VPS with cPanel | VPS without cPanel | | --- | --- | --- | | Administration | Graphical interface plus WHM | CLI, automation, APIs, or another panel | | License cost | Additional recurring cost | No cPanel license | | Setup speed | Faster for standard hosting stacks | Depends on automation and experience | | Multi-site management | Strong fit | Requires custom tooling or another panel | | Email hosting | Built into common workflows | Must be configured separately | | DNS management | Integrated | External DNS or manual configuration | | SSL management | Integrated workflows | Usually automated through other tools | | Resource overhead | Higher because panel services run continuously | Can be lower with a minimal stack | | Stack flexibility | More standardized | Full control over services and versions | | Docker and custom apps | Possible but often awkward | Better fit | | Learning curve | Lower for hosting users | Higher for beginners | | Root control | Still available, but panel expects control of key services | Full architectural freedom | | Migration | Easier between compatible cPanel environments | Depends on custom stack | ## Cost Includes More Than the VPS Plan cPanel licensing is separate from the VPS price. Current cPanel cloud licenses are account-based, so the monthly cost grows as the number of hosted accounts increases. Buyers should confirm the current license tier and included account count before choosing a server. A realistic cost model is: ```text VPS with cPanel = VPS price + cPanel license + backup storage + email-delivery or security add-ons + administration time ``` A VPS without cPanel removes the license line item, but not the work. The team may spend more time configuring services, maintaining scripts, troubleshooting email, or building an internal management workflow. The correct comparison is therefore convenience cost versus engineering cost. cPanel can be economical when one administrator manages many traditional sites. It can be unnecessary overhead when a developer operates one application through Git, Docker, CI/CD, and external managed services. ## Resource Overhead Matters Most on Small VPS Plans A control panel runs services beyond the website itself. Depending on the configuration, the server may also operate: - Web and proxy services - Database services - Mail transfer and mailbox services - Spam filtering - DNS services - Logging and statistics tools - Security agents - Backup processes - Panel background tasks These consume memory, CPU, disk space, and I/O. On a larger VPS, the overhead may be acceptable. On a very small VPS, it can take resources away from websites and databases. This is especially important when email, DNS, databases, and several customer sites share one machine. A cPanel server should be sized for the entire hosting stack, not only the main website. Without cPanel, a team can run a narrower stack. For example, an application may need only Nginx, a runtime, an agent, and a connection to an external database. That minimal model can be more resource-efficient. ## cPanel Fits Traditional Multi-Site Hosting cPanel is strongest when the server behaves like a hosting platform rather than a single application server. Good use cases include: - Agencies hosting several client websites - WordPress and PHP hosting - Teams managing many domains - Businesses that need mailbox administration - Operators who need per-account limits - Reseller-style account separation - Environments where non-technical users manage websites - Migrations from another cPanel host The panel creates a consistent operating model. Each site or customer can have an account, domains, files, databases, email, logs, and resource limits inside a familiar interface. That consistency can reduce support and onboarding time. ## cPanel Is Often a Weak Fit for Custom Application Infrastructure Teams building modern applications may find cPanel restrictive or redundant. Common examples include: - Docker Compose deployments - Kubernetes workloads - GitOps or infrastructure-as-code - Node.js, Go, Python, or Java services with custom runtimes - Separate managed databases - External transactional email - External DNS providers - CI/CD-controlled releases - Immutable images - Multi-VM application architectures In these environments, the application stack already has its own control plane. Adding cPanel can duplicate functions and make configuration ownership less clear. A developer may change Nginx manually while cPanel expects to generate configuration. An automation workflow may install packages that the panel does not support. A custom service may not fit cPanel’s account model. For these workloads, a clean Linux VM without cPanel is usually easier to automate and reason about. ## Email Can Change the Decision Email is one of the strongest reasons some buyers choose cPanel. The panel can simplify: - Mailbox creation - Aliases and forwarding - Domain mail routing - Spam controls - Webmail access - DNS records related to mail - Per-account email administration But operating email on the same VPS also introduces responsibility for: - IP reputation - Spam abuse - Delivery failures - Blacklists - Storage growth - Authentication records - Malware and compromised accounts - Queue monitoring A panel makes email administration easier; it does not make email deliverability automatic. Teams using an external email provider may gain little from running the mail stack locally. In that case, cPanel loses one of its major convenience advantages. ## Security Is Simpler to Administer but Broader in Scope cPanel can centralize updates, access settings, certificates, account isolation, and security tooling. That can help operators follow a consistent process. At the same time, the panel increases the number of services and interfaces exposed on the server. The environment may include web, mail, DNS, FTP, databases, panel ports, and third-party plugins. Security still requires: - Keeping the OS and panel updated - Restricting administrator access - Using strong authentication - Monitoring account compromises - Reviewing plugins and add-ons - Maintaining backups outside the server - Testing restores - Removing unused services - Controlling customer and reseller privileges A minimal non-cPanel server can have a smaller attack surface, but only when it is properly configured and maintained. ## Backup and Restore Workflows Differ cPanel provides integrated backup and restore workflows for accounts, websites, databases, email, and configuration. These can make site-level recovery and migration easier. However, buyers should verify: - Where backups are stored - Whether backups leave the VPS - Retention period - Encryption - Account-level versus full-server recovery - Restore testing - Database consistency - Recovery time A backup stored only on the same VPS is not sufficient protection against complete server loss. Without cPanel, teams can use provider snapshots, file-level backup tools, database-native backups, object storage, and automation. This requires more design work but can fit custom recovery objectives better. ## Root Access and Control Still Need Discipline cPanel servers normally provide root access, but direct changes to panel-managed services can create conflicts. The panel expects to control parts of the web, mail, DNS, and account configuration. That means full root access does not always equal full design freedom. Before modifying a cPanel VPS, ask: - Will the panel overwrite this configuration? - Is the package supported? - Will the change survive updates? - Does it affect migration compatibility? - Can the provider or cPanel support troubleshoot the modified system? A VPS without cPanel has fewer assumptions. The team can build exactly the stack it wants, but must document and maintain every choice. ## Migration and Exit Planning Moving between cPanel environments is often easier because account structures and backup formats are standardized. This can be valuable for agencies and hosting providers. A full account may include websites, databases, email, DNS, and settings that can be transferred together. Leaving cPanel for a custom stack can be more involved because services need to be separated and rebuilt. Buyers should not treat the panel as a temporary interface that can always be removed cleanly. cPanel documentation recommends installing on a fresh supported operating system. In practice, moving away from a panel-managed server is usually safer through migration to a new VPS rather than attempting to remove the panel in place. The exit plan should be considered before the initial installation. ## Decision Framework Choose a VPS with cPanel when: - You host several traditional websites - You need centralized domain, email, database, and SSL administration - You manage customer hosting accounts - You want per-account resource controls - Non-technical users need an interface - You are migrating from an existing cPanel environment - The license cost is small compared with saved administration time Choose a VPS without cPanel when: - You run one custom application - You deploy through Git, CI/CD, Docker, or automation - You use external email and DNS providers - You need full control over packages and services - You want a minimal operating system - The team already has Linux administration skills - You want to avoid account-based panel licensing - You plan to split the app, database, and other services across multiple VMs | Workload | Better default | | --- | --- | | Agency hosting 20 client WordPress sites | cPanel may fit | | One production SaaS application | No cPanel | | Shared hosting-style customer accounts | cPanel | | Docker host | No cPanel | | Business website plus local email | cPanel may fit | | Application using managed database and external email | No cPanel | | Developer staging server | No cPanel | | Reseller-style multi-account hosting | cPanel may fit | ## Questions to Ask Before Buying 1. What is the total monthly cPanel license cost for the expected number of accounts? 2. Does the VPS have enough RAM and storage for web, mail, DNS, database, backups, and the panel? 3. Will email be hosted locally or externally? 4. Is the workload traditional website hosting or a custom application? 5. Who will maintain the OS and panel? 6. Are backups stored outside the VPS? 7. Does the required software fit cPanel’s supported stack? 8. Will customers or non-technical users need panel access? 9. How will the server be migrated later? 10. Is a different panel or automation workflow a better fit? :::cluster ## How Raff Fits the Decision Raff provides full-control Linux VMs that can host traditional websites or custom application stacks. Customers can choose a clean Linux environment and manage it through SSH, automation, containers, and external services. cPanel is separate commercial software. Its license and compatibility requirements should be confirmed before deployment. Raff VM pricing should therefore be compared with the complete hosting stack, including any panel license, backups, storage, email services, and administration work. For custom applications, a clean Raff Linux VM usually provides the simpler foundation. Agencies or hosting operators that need cPanel’s multi-account workflows can evaluate the panel separately and size the VM for the complete service stack. ## Choose the Interface That Matches the Workload cPanel is valuable when one VPS must behave like a traditional multi-site hosting platform. It centralizes common web-hosting tasks and can reduce administration time for agencies, site operators, and teams managing many accounts. A VPS without cPanel is usually better for custom applications, Docker deployments, automation-first teams, and minimal server stacks. It avoids the panel license and provides greater architectural freedom. Do not choose cPanel only because a graphical interface feels safer. Do not reject it only because command-line management offers more control. Compare the workload, operator skills, account count, email requirements, resource overhead, migration plan, and total monthly cost. :::cta Explore Linux VM Choose a full-control Linux VM for traditional web hosting or a custom application stack. ::: ## Sources - [cPanel Pricing](https://www.cpanel.net/pricing/) - [cPanel Installation Guide](https://docs.cpanel.net/installation-guide/) - [cPanel System Requirements](https://docs.cpanel.net/installation-guide/system-requirements/) - Date verified: 2026-07-29 --- ### VPS vs Reseller Hosting: Which Model Fits Agencies and Multi-Site Hosting? URL: https://rafftechnologies.com/learn/guides/vps-vs-reseller-hosting Description: Compare VPS and reseller hosting for agencies by client isolation, control, support, margins, scaling, migration, and operational responsibility. VPS hosting and reseller hosting can both support multiple client websites, but they create very different agency operating models. **Reseller hosting gives the agency a provider-managed hosting allocation that can be divided into client accounts. A VPS gives the agency control of an entire virtual server and makes the agency responsible for designing or arranging the hosting environment.** Reseller hosting is usually the simpler starting point for freelancers and agencies that want to package hosting without operating infrastructure. A VPS becomes more attractive when the agency needs root access, custom software, stronger resource control, deeper automation, or enough scale to justify taking ownership of the server layer. The decision should not be reduced to which option has more CPU or storage. Agencies should compare client separation, support escalation, provider restrictions, operational skill, migration effort, profit margin, and the business impact of one infrastructure failure affecting multiple customers. ## VPS and Reseller Hosting Are Different Business Models A reseller hosting account is a wholesale-style hosting arrangement. The provider operates the underlying server and gives the reseller a defined amount of storage, bandwidth, accounts, domains, or other capacity. The reseller then creates smaller hosting packages for clients. ![VPS vs reseller hosting diagram comparing a provider-managed client account platform with an agency-built hosting platform on a virtual server.](https://raff-images.s3.raffusercloud.com/vps_vs_reseller_hosting_operating_model_webp_c88686fcdb.png) A VPS is a virtual server. The provider operates the physical infrastructure and virtualization platform, while the VPS customer controls the guest operating system and chooses how client websites are deployed and separated. | Area | Reseller hosting | VPS hosting | | --- | --- | --- | | Infrastructure ownership | Provider operates the hosting server | Agency controls its virtual server | | Root access | Usually unavailable | Usually available | | Client accounts | Built into the reseller platform | Agency must create the account model | | Server software | Provider selects and maintains most of the stack | Agency selects or arranges the stack | | Resource allocation | Limited by reseller plan and provider rules | Limited by VPS resources and agency design | | Support path | Agency escalates platform issues to reseller provider | Agency handles the VM and escalates infrastructure issues to VPS provider | | Custom software | Usually restricted | Usually flexible | | Operational workload | Lower | Higher | | Migration control | Depends heavily on provider tools | More control, but more migration planning | | Scaling model | Upgrade reseller package or move provider | Resize, split workloads, or add VMs | The key distinction is not simply shared hosting versus dedicated resources. It is whether the agency is **reselling a provider-defined hosting product** or **building its own hosting platform on a virtual server**. ## What Reseller Hosting Gives an Agency Reseller hosting is designed around account creation and packaging. Depending on the provider, a reseller plan may include: - A reseller control panel - Separate client hosting accounts - Storage and bandwidth quotas - Website, database, email, and DNS tools - White-label nameservers or branding options - Billing integrations - SSL workflows - Backup features - Provider-managed server updates - A support escalation path In cPanel & WHM environments, resellers can create and manage the cPanel accounts they own, while the server administrator defines their privileges and account limits. Packages can be used to set restrictions such as disk space and bandwidth. This model is useful because the agency can sell hosting without first designing user isolation, quota enforcement, account suspension, or customer-facing control-panel access. The trade-off is that the provider controls the server, software versions, allowed features, resource policies, and many technical decisions. ## What a VPS Gives an Agency A VPS gives the agency a server rather than a ready-made reseller product. The agency can choose: - Operating system - Web server and runtime - Control panel or no control panel - Account-isolation method - Database architecture - Backup design - Monitoring stack - Security tooling - Deployment workflow - Email strategy - DNS provider - Resource allocation - Automation and APIs This flexibility supports traditional hosting, custom application hosting, containerized sites, staging environments, client-specific software, and more advanced agency workflows. But a VPS does not automatically include a client hosting system. The agency must build or purchase the layers that reseller hosting bundles together. That may include: - A commercial control panel - Per-client Linux users or containers - Resource limits - Billing and provisioning automation - Monitoring and alerting - Backup and restore processes - Malware response - Customer access controls - Documentation and support procedures A VPS can improve control and margins, but only when the agency can operate the resulting platform reliably. ## This Decision Is Separate From cPanel and Managed Hosting Three related decisions are often mixed together: | Decision | Question | | --- | --- | | VPS vs reseller hosting | Should the agency resell provider-managed hosting or operate its own server platform? | | VPS with or without cPanel | Should the server use cPanel as its hosting-management interface? | | Managed vs unmanaged VPS | Who maintains the guest operating system and services? | An agency can run cPanel on a VPS and create reseller-style client accounts. It can also build a VPS platform without cPanel. Similarly, a VPS may be self-managed, managed by the provider, or operated by an MSP. Reseller hosting is normally provider-managed at the server layer, but the agency still owns customer communication, website-level support, and many service-delivery tasks. For the panel decision, read [VPS Hosting With or Without cPanel](/learn/guides/vps-with-or-without-cpanel). For the responsibility boundary, read [Managed vs Unmanaged VPS](/learn/guides/managed-vs-unmanaged-vps). ## Client Account Separation Is the First Major Difference Reseller hosting usually starts with an account model. Each client can receive a separate hosting account with its own files, databases, email, domains, usage limits, and login. ![Client isolation comparison showing built-in reseller accounts, a weak shared-admin VPS design, and a VPS with separate accounts, containers, and dedicated virtual machines.](https://raff-images.s3.raffusercloud.com/vps_vs_reseller_hosting_client_isolation_webp_fb35a0f346.png) That separation helps with: - Client onboarding - Access control - Account suspension - Migration - Resource packages - Billing alignment - Customer handoff - Reducing accidental cross-client access A VPS can provide equal or stronger separation, but it must be designed. Common VPS separation models include: - Separate control-panel accounts - Separate Linux users - Containers - Separate application processes - Per-site PHP pools - Dedicated databases or database users - Separate VMs for high-value clients Simply placing every website under one administrator account is not a strong multi-client architecture. One compromised site, incorrect permission, or failed deployment can affect the entire portfolio. For agencies, the question is not only whether multiple websites fit on the server. It is whether clients can be isolated, supported, migrated, and recovered independently. ## Control and Custom Software Favor VPS Hosting Reseller plans are designed for standard hosting workloads. They often work well for WordPress, PHP, static sites, databases, email accounts, and common CMS platforms. They become restrictive when the agency needs: - Custom server packages - Node.js, Python, Go, or Java services outside supported workflows - Docker or container orchestration - Background workers - Custom reverse-proxy rules - Private services - Specialized caching - Non-standard database engines - Custom monitoring agents - CI/CD-controlled deployments - Application-level networking A VPS is usually the better fit when the agency is hosting applications rather than only websites. Reseller hosting is usually the better fit when customers need a conventional hosting account and the agency does not benefit from server-level customization. ## Resource Control Works Differently With reseller hosting, the agency receives capacity inside a provider-controlled server. The provider decides how the underlying machine is operated and how accounts share resources. The reseller may be able to define packages and quotas, but may not have full visibility into host-level CPU contention, storage architecture, service configuration, or the activity of unrelated resellers. With a VPS, the agency receives a defined allocation of virtual CPU, RAM, storage, and networking. The agency controls how those resources are distributed among its clients. This creates more control but also more responsibility. The agency must decide: - How many sites belong on one VPS - Whether one client can consume excessive CPU or memory - When a site should move to a separate VM - How storage growth is monitored - How backups affect disk and I/O - How traffic spikes are handled - Which customers require stronger isolation A VPS does not provide unlimited capacity. It provides a clearer resource boundary that the agency must actively manage. ## Support Escalation Can Determine the Better Model Reseller hosting gives the agency a layered support model: 1. The client contacts the agency. 2. The agency investigates the website or account. 3. The agency escalates server-level issues to the reseller provider. This can reduce infrastructure work, but it also creates dependency. The agency may not have enough access to diagnose a slow server, mail issue, blocked service, or configuration limit directly. With VPS hosting, the agency has more diagnostic control. It can inspect logs, services, resource usage, network configuration, and application behavior. However, the VPS provider normally supports the infrastructure and platform—not every website, plugin, database query, or custom application running inside the VM. Before choosing either model, define who handles: - Website errors - CMS and plugin failures - Email delivery - DNS mistakes - SSL issues - Malware cleanup - Operating-system updates - Service outages - Backup restoration - Resource exhaustion - After-hours incidents The best model is the one where the agency can resolve or escalate customer-impacting problems within its promised service level. ## Compare Total Cost and Agency Margin Reseller hosting usually has a simple commercial model. The agency pays one package fee and sells smaller plans to clients. A VPS may have a lower infrastructure cost per site at scale, but the server is only one part of the cost. ```text Reseller hosting total cost = reseller plan + optional add-ons + agency support time + migration and provider dependency risk VPS hosting total cost = VPS + control panel or automation + backups and storage + monitoring and security tools + server administration + incident response + agency support time ``` Agencies should measure margin after labor, not only after hosting invoices. A VPS that saves $30 per month but creates several hours of maintenance is not necessarily more profitable. A reseller plan with a higher per-site cost may still be better when it allows the agency to focus on design, development, SEO, or retainers. A VPS becomes financially attractive when: - The agency has enough recurring clients - Server operations are standardized - Provisioning and backups are automated - Support processes are documented - The team already has infrastructure skills - The agency needs features reseller plans cannot provide - The cost of provider restrictions exceeds the cost of operating the VPS ## White Labeling and Client Experience Reseller hosting is often built for white-label service delivery. Providers may allow custom nameservers, branded control panels, customer packages, and billing integrations. A VPS offers more branding freedom because the agency controls the platform, but building a polished client experience requires additional work. The agency may need to provide: - Client login portal - Hosting dashboard - Usage reporting - Password-reset workflow - Billing integration - Suspension and cancellation automation - Documentation - Support ticketing - Status communication Some agencies do not need customer-facing hosting controls. They manage every site internally and bundle hosting into a maintenance retainer. In that model, a VPS may work without a reseller-style interface. Other agencies want clients to manage domains, email accounts, files, or databases directly. Reseller hosting may provide that experience faster. ## Security and Risk Concentration Both models can concentrate many clients on shared infrastructure. With reseller hosting, the provider owns the server-security architecture, while the agency manages client websites, credentials, and account access. With VPS hosting, the agency or its management partner also owns the guest operating system, service configuration, and client-isolation design. Important risks include: - One compromised site affecting other clients - Shared administrator credentials - Inadequate account separation - Backups stored only on the hosting server - One server outage affecting the entire client portfolio - A traffic spike exhausting shared resources - Malware spreading through writable directories - An agency administrator making a server-wide mistake A VPS allows stronger customization, but it does not automatically create stronger security. The agency must implement the controls that a reseller provider would otherwise manage. High-value or high-risk clients may need separate VMs even when smaller customers remain consolidated. ## Backup and Migration Control Reseller hosting often provides account-level backups and migration tools. These can make it easier to move individual websites between compatible hosting environments. But the agency should verify: - Whether backups are included - Whether restores are self-service - Whether backups are stored outside the server - How long data is retained - Whether email and DNS settings are included - Whether the provider charges for migrations - How easily accounts can move to another platform A VPS gives the agency more freedom to design backups around business requirements. It can combine provider snapshots, file backups, database dumps, and off-server storage. The trade-off is that the agency must test and document recovery. Migration from reseller hosting to VPS is easier when each client already has a clean account boundary. Migration becomes harder when domains, email, databases, and websites are tightly coupled to provider-specific systems. ## When Reseller Hosting Is the Better Choice Reseller hosting is usually the better default when: - The agency is launching its first hosting service - Most clients run conventional websites or WordPress - The team does not have a server administrator - Fast client-account provisioning matters - Customers need a familiar hosting interface - The agency wants the provider to maintain the server stack - Predictable support escalation is more important than root access - The number of hosted clients is still modest - Custom software is rarely required - The agency wants to minimize infrastructure risk This model lets the agency validate demand before investing in its own hosting platform. ## When VPS Hosting Is the Better Choice A VPS is usually the better default when: - Root access is required - The agency hosts custom applications - Clients need different runtimes or services - The team can operate Linux securely - The reseller provider creates performance or configuration limits - The agency wants deeper monitoring and automation - Client volume makes per-account reseller pricing inefficient - The agency needs predictable control over resources - Some customers need private services or advanced networking - The agency wants to split workloads across multiple servers over time The agency does not need to operate everything internally. A managed service, MSP, or dedicated infrastructure partner can manage the VPS while the agency retains architectural control. ## Decision Framework for Agencies ![Agency hosting decision framework comparing reseller hosting, VPS hosting, and a hybrid model for standard websites, custom applications, and high-value clients.](https://raff-images.s3.raffusercloud.com/vps_vs_reseller_hosting_agency_decision_framework_webp_902b0c5bc9.png) | Agency situation | Better starting point | Reason | | --- | --- | --- | | Freelancer hosting five brochure sites | Reseller hosting | Low operational burden | | WordPress agency with standard client sites | Reseller hosting may fit | Account workflows are already packaged | | Development agency hosting custom Node.js apps | VPS | Custom runtime and server control | | Agency with no Linux administrator | Reseller hosting | Lower infrastructure responsibility | | Agency with DevOps capability | VPS | Automation and control can improve efficiency | | Clients need individual control-panel access | Reseller hosting may fit | Faster customer account delivery | | Hosting is bundled into a managed retainer | VPS may fit | Clients may not need direct platform access | | One client needs custom software | Separate VPS | Avoid forcing the whole portfolio into one model | | Agency is constrained by provider limits | VPS | More control over software and resources | | Agency wants to become a hosting provider | VPS or multi-server platform | Greater control, but higher operational commitment | Use these questions: 1. Does the agency want to sell hosting accounts or operate infrastructure? 2. Do clients need direct access to hosting tools? 3. Does the workload require root access or custom software? 4. Who handles server updates, monitoring, backups, and incidents? 5. Can client accounts be isolated and restored independently? 6. What is the real margin after administration and support time? 7. What happens when the current provider becomes restrictive? 8. How many clients can one failure affect? 9. Can the agency meet its support promises with the available access? 10. Is the current model still suitable after the next 10 clients? ## When to Move From Reseller Hosting to a VPS Moving to a VPS should solve a documented constraint, not simply make the hosting stack feel more professional. Common migration signals include: - The agency repeatedly hits account, storage, bandwidth, or software limits - Clients need runtimes the reseller platform does not support - Performance troubleshooting requires server-level visibility - Per-account pricing is reducing margin - The agency needs custom backups or monitoring - Provider support delays are affecting client service - The agency wants to automate provisioning and deployment - Important clients need stronger isolation - The agency has someone who can own server operations - A staged migration plan has been tested Do not migrate every client at once by default. A safer path is to move one low-risk account, validate provisioning, backups, monitoring, and support procedures, and then migrate in controlled groups. ## A Hybrid Model Is Often the Practical Answer Agencies do not need to place every client on the same platform. A hybrid portfolio can use: - Reseller hosting for small, standard websites - VPS instances for custom applications - Dedicated VMs for high-value customers - External email for all clients - Managed databases for application workloads - Object storage for backups and media - Separate staging environments for development clients This reduces the pressure to make one hosting model serve every customer. The agency can keep low-complexity accounts on reseller hosting while moving clients to VPS only when control, performance, or software requirements justify the added responsibility. :::cluster ## How Raff Fits the Agency Hosting Decision Raff provides full-control cloud VMs that agencies can use for client websites, custom applications, staging environments, and multi-site hosting platforms. The agency controls the operating system, software stack, deployment model, and resource allocation. Raff is not a packaged reseller hosting account. Agencies that choose Raff VM must create or select their own client-account, control-panel, backup, monitoring, and management model. That makes Raff a stronger fit when the agency has outgrown provider-defined reseller limits, needs custom software, wants server-level control, or plans to build a more flexible hosting platform. Agencies that only need a simple white-label hosting package with minimal infrastructure work may be better served by reseller hosting until their operational or technical requirements change. ## Choose the Model That Supports the Agency Business Reseller hosting is usually the cleaner starting point for agencies that want to package standard hosting without operating servers. It provides customer-account workflows, quotas, and a provider-managed platform with less technical overhead. VPS hosting is the stronger choice when control creates measurable value: custom software, better automation, clearer resource ownership, stronger architecture flexibility, or improved margins at sufficient scale. The right time to move is when reseller hosting creates a real business constraint and the agency has a reliable operating model ready to replace it. :::cta Explore Linux VM Build a flexible agency hosting environment on a full-control Linux VM. ::: ## Sources - [cPanel Guide to Reseller Accounts](https://docs.cpanel.net/knowledge-base/accounts/guide-to-reseller-accounts/) - [cPanel Create a New Account](https://docs.cpanel.net/whm/account-functions/create-a-new-account/) - [cPanel Edit Reseller Nameservers and Privileges](https://docs.cpanel.net/whm/resellers/edit-reseller-nameservers-and-privileges/) - Date verified: 2026-07-29 --- ### WordPress VPS Hosting: When It Beats Shared and Managed Hosting URL: https://rafftechnologies.com/learn/guides/wordpress-vps-hosting Description: Learn when WordPress VPS hosting beats shared and managed hosting, with a decision framework for traffic, control, WooCommerce, cost, and operations. WordPress VPS hosting runs a WordPress site on a virtual private server where you control the operating system, web server, PHP runtime, database, security rules, and backups. It offers more infrastructure control than shared or managed WordPress hosting, but your team also takes on more operational responsibility. Raff treats this as a hosting-model decision, not a promise that every WordPress site needs a server. A small brochure site may be better served by shared hosting, while a growing WooCommerce store, agency portfolio, or plugin-heavy site may justify a VPS. This guide is part of the [VPS & Cloud VM Fundamentals](/learn/guides/virtual-private-server-hosting) series and explains when the additional control is worth the work. ## WordPress VPS Hosting Changes the Operating Model A VPS gives WordPress its own defined server environment. You can choose the Linux distribution, web server, PHP version, database configuration, caching layer, firewall rules, and backup process. You are no longer limited to the packages, process limits, or control-panel settings selected by a shared hosting provider. That flexibility is useful only when the site benefits from it. A VPS does not automatically make WordPress faster. Performance still depends on the theme, plugins, PHP workers, database queries, caching, image delivery, storage, and traffic pattern. ![WordPress VPS hosting architecture showing visitors, DNS or CDN, web server, PHP, WordPress, database, storage, backups, and the underlying Linux VPS.](https://raff-images.s3.raffusercloud.com/wordpress_vps_hosting_architecture_webp_316ae5d938.png) The main change is responsibility. On shared or managed WordPress hosting, the provider handles more of the operating system and platform maintenance. On a self-managed VPS, your team is responsible for: - operating-system updates - web server and PHP configuration - database maintenance - firewall and SSH access - malware prevention and incident response - backup schedules and restore testing - uptime monitoring - capacity planning Raff separates VM infrastructure from WordPress management because the two buyers need different things. Teams that need root access should not be forced into a fixed control-panel workflow. Teams that want someone else to manage WordPress updates and application issues should choose a managed WordPress service instead of assuming a VPS removes operational work. ## Shared, Managed WordPress, and VPS Hosting Serve Different Buyers The three hosting models solve different problems. Shared hosting optimizes for simplicity and low cost. Managed WordPress hosting optimizes for reduced maintenance. A VPS optimizes for control and workload flexibility. | Decision factor | Shared hosting | Managed WordPress hosting | WordPress VPS hosting | | --- | --- | --- | --- | | Server control | Limited | Limited to provider tools | Full root-level control | | WordPress maintenance | Mostly your responsibility | Provider assists with platform tasks | Your responsibility | | Resource isolation | Account-level limits | Provider-defined | Defined by VM plan and CPU class | | Custom software | Usually restricted | Usually restricted | Install the stack you need | | Security scope | Provider secures the platform | Provider secures platform and WordPress layer | You secure the operating system and application | | Scaling path | Upgrade hosting plan | Upgrade managed tier | Resize VM or separate services | | Best fit | Small, simple sites | Teams prioritizing convenience | Sites needing control, custom services, or predictable capacity | Shared hosting remains sensible when a site is small, changes infrequently, and fits the provider’s limits. Managed WordPress hosting is a strong choice when the site matters to the business but the team does not want to maintain Linux, PHP, Nginx, or MariaDB. A VPS becomes compelling when the hosting environment itself is limiting the site. ## A VPS Becomes Worthwhile When Hosting Constraints Affect the Site WordPress VPS hosting is most useful when a site needs capabilities that shared or managed plans cannot provide cleanly. ![WordPress performance stack showing server resources, runtime tuning, caching, database efficiency, content delivery, and operational stability on a VPS.](https://raff-images.s3.raffusercloud.com/wordpress_vps_performance_stack_webp_aaee44b313.png) ### Custom software and runtime control A VPS lets you choose the web server, PHP version, extensions, database settings, cache, background services, and deployment tools. This matters when a plugin requires a system package, a custom PHP extension, a queue worker, scheduled processing, or a non-standard proxy configuration. ### WooCommerce and dynamic workloads WooCommerce adds database writes, logged-in sessions, cart operations, checkout requests, scheduled actions, email jobs, and third-party integrations. These workloads cannot be solved by page caching alone. A VPS gives you room to tune PHP workers, database memory, object caching, cron execution, and storage. It also lets you observe which layer is actually slow before buying more resources. ### Multiple production sites Agencies and developers may prefer one controlled server environment for several client sites. A VPS can reduce per-site hosting costs and standardize the stack, but it also increases blast radius. One compromised plugin or full disk can affect every site on that server. For multi-site hosting, isolation, backups, update policies, and account permissions matter as much as raw capacity. The [VPS with or without cPanel guide](/learn/guides/vps-with-or-without-cpanel) explains when a hosting panel reduces operational friction. ### Unpredictable limits on shared hosting Shared hosting providers often enforce CPU, memory, process, database, inode, or execution-time limits. These controls protect the platform, but they can become a constraint when traffic, imports, backups, or plugin jobs grow. Moving to a VPS replaces hidden account-level limits with a server you can measure. It does not remove limits; it makes CPU, RAM, disk, and network capacity easier to understand and change. ### Staging and deployment control A VPS supports a more deliberate release workflow. You can maintain staging environments, use version control, automate deployments, control PHP versions, and schedule maintenance without depending on a hosting dashboard’s feature set. ## A VPS Is the Wrong Choice When Operations Are the Bottleneck A VPS is not the right upgrade when the team lacks time or confidence to operate the server. Stay with shared hosting when the site is small, the current host is reliable, and no technical limit is affecting the business. Moving a simple site to a VPS may add patching, monitoring, and security work without creating meaningful value. Choose managed WordPress hosting when you need stronger WordPress-specific support, automatic platform maintenance, integrated staging, managed caching, or help diagnosing plugin and theme issues. A VM provider manages the infrastructure boundary; it does not automatically become your WordPress administrator. A VPS is also a weak fit when: - nobody owns operating-system updates - backups exist but restores are never tested - the site needs application-level support rather than infrastructure control - the team expects cPanel, email hosting, and WordPress support to be included by default - downtime would be expensive but monitoring and recovery are undefined The additional control is valuable only when someone is prepared to use and maintain it. ## WordPress VPS Sizing Depends on Workload Shape WordPress sizing depends more on workload behavior than monthly visitor count. Two sites with the same traffic can need very different resources because one serves cached articles while the other runs WooCommerce, membership plugins, search, imports, and logged-in dashboards. A small WordPress site can begin around 2 GB RAM when the stack is lean and traffic is modest. A 4 GB configuration provides safer headroom for PHP-FPM, the database, updates, backups, and plugin activity. These are planning ranges, not guarantees. Evaluate these factors before choosing a VM: - **PHP concurrency:** More simultaneous uncached requests require more PHP workers and memory. - **Database activity:** WooCommerce, membership sites, and complex search create more reads and writes. - **Plugin behavior:** Page builders, security scanners, backup plugins, and imports can create CPU and memory spikes. - **Media volume:** Large image libraries increase storage, backup size, and transfer work. - **Background jobs:** Scheduled actions, email queues, feeds, and exports consume resources outside page views. - **Caching:** Full-page and object caching can reduce repeated work but cannot fix slow queries or inefficient plugins. CPU allocation also matters. Shared vCPU is cost-efficient for variable sites. Dedicated vCPU becomes more valuable when checkout, admin work, imports, or scheduled jobs need consistent compute. See [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) for the full decision framework. ## The Hosting Decision Framework Choose the least operationally complex model that meets the site’s real requirements. ![Decision framework comparing shared hosting, WordPress VPS hosting, and managed hosting based on performance needs, control, site complexity, and operational ownership.](https://raff-images.s3.raffusercloud.com/wordpress_vps_hosting_decision_framework_webp_d49c5a8db4.png) ### Choose shared hosting when - the site is a brochure, portfolio, or small content site - traffic and plugin activity are modest - the current provider’s limits are not causing problems - server administration would create more risk than value - the lowest operational burden matters most ### Choose managed WordPress hosting when - WordPress is business-critical but the team lacks Linux administration time - platform updates, staging, caching, and WordPress-focused support are priorities - paying more is acceptable in exchange for reduced maintenance - the site fits the provider’s supported plugins and workflows ### Choose WordPress VPS hosting when - you need root access or custom system packages - shared-hosting limits affect performance or background jobs - WooCommerce or logged-in traffic needs more tuning control - you operate several sites with a documented maintenance process - you need a custom deployment, monitoring, or backup architecture - someone owns security, updates, monitoring, and recovery | Primary need | Best starting model | | --- | --- | | Lowest effort for a small site | Shared hosting | | WordPress-specific convenience and support | Managed WordPress hosting | | Full stack control and custom services | VPS hosting | | Custom WooCommerce tuning | VPS or managed WordPress, based on operational capability | | Several sites with standardized administration | VPS with strong isolation and backup practices | | No in-house server ownership | Managed WordPress hosting | The deciding question is not whether a VPS is more powerful. It is whether infrastructure control solves a problem your team actually has. ## WordPress on Raff Fits Teams That Want Infrastructure Control Raff Linux VMs provide a configurable environment for WordPress workloads that need full server access. You choose the operating system and software stack, while Raff provides the VM, NVMe storage, unmetered bandwidth, DDoS protection, firewall controls, snapshots, automated backup options, and the ability to resize as requirements change. This model is a strong fit for developers, agencies, and small teams that want to control Nginx or Apache, PHP-FPM, MariaDB or MySQL, caching, cron jobs, monitoring, and deployment practices. It is not a managed WordPress service. WordPress core, plugins, themes, PHP configuration, database maintenance, and application security remain your responsibility. Raff uses separate General Purpose and CPU-Optimized VM classes because WordPress workloads do not all need the same CPU behavior. A content site with cacheable traffic may prioritize cost efficiency. A busy store, import process, or admin-heavy site may benefit from more predictable compute. For the deployment workflow, use [How to Install WordPress on Ubuntu 24.04 with Nginx](/learn/tutorials/install-wordpress-ubuntu-24-04-nginx). That tutorial covers the technical installation; this guide owns the decision of whether a VPS is the right hosting model. ## Migration Requires a Rollback Plan, Not Only a File Copy A WordPress migration should preserve both the application and the operating context around it. Before changing DNS, document the current PHP version, extensions, web server rules, cron jobs, email delivery, database size, uploads, redirects, caching, security plugins, and backup process. Prepare the new environment, copy the site, test it on a temporary hostname or local hosts-file override, and verify login, forms, email, payments, scheduled actions, media, redirects, and backups. Keep the old host available until the new site has passed normal business use. The migration is also a good time to remove abandoned plugins, rotate credentials, reduce DNS TTL in advance, and define who can roll traffic back if checkout, login, or database writes fail. ## Conclusion WordPress VPS hosting is the right choice when control over the server, runtime, database, background jobs, or scaling path creates more value than the operational work it introduces. Shared hosting remains efficient for simple sites. Managed WordPress hosting remains safer for teams that want WordPress-focused maintenance and support. Use the [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) to compare the broader server options, then follow the [WordPress installation tutorial](/learn/tutorials/install-wordpress-ubuntu-24-04-nginx) when you are ready to deploy. :::cta Deploy Your Server Create a Linux VM for a WordPress stack you can configure, monitor, back up, and resize around the site’s workload. ::: --- ### VPS Benchmarking Guide: CPU, NVMe, Network, and Real-World Tests URL: https://rafftechnologies.com/learn/guides/vps-benchmarking-guide Description: Learn how to benchmark VPS CPU, NVMe storage, network, consistency, and price-performance without being misled by one synthetic score. A VPS benchmark is a controlled test used to measure how a virtual private server performs across CPU, memory, storage, network, and application workloads. It can help buyers compare VM plans and verify provider claims, but only when the test conditions are repeatable and the results are interpreted in context. A single score does not tell you whether a VPS is right for your workload. A fast CPU result can hide inconsistent disk latency. A 3 Gbps network port does not guarantee the same throughput to every destination. A strong synthetic score may not improve a slow database query or poorly cached application. This guide explains what to test, which results matter, and how to compare VPS performance without being misled by headline numbers. ## What a VPS Benchmark Can and Cannot Tell You A benchmark can show how a server behaves under a defined workload. It can help answer questions such as: - Is CPU performance consistent across repeated runs? - Does the storage deliver strong random I/O as well as sequential throughput? - Is network performance stable to the locations that matter? - Does a dedicated-vCPU plan reduce performance variance? - Does a more expensive plan provide enough additional value? A benchmark cannot prove that an application will always be fast. Real performance also depends on application code, database design, caching, operating-system configuration, traffic shape, external APIs, and user geography. This distinction separates benchmarking from diagnosis. Benchmarking measures the platform under controlled conditions. Performance diagnosis identifies why a real workload is slow. For the diagnostic side, use [Cloud Server Performance Bottlenecks Explained](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). ## Useful VPS Benchmarks Cover Four Performance Layers A credible VPS comparison should cover more than one resource. | Performance layer | What it measures | Why buyers should care | | --- | --- | --- | | CPU | Single-core speed, multi-core throughput, consistency | Affects application logic, builds, workers, databases, and processing jobs | | Memory | Memory access and transfer behavior | Affects databases, caches, runtimes, and multi-service VMs | | Storage | Bandwidth, IOPS, and latency across read/write patterns | Affects databases, logs, package installs, containers, and file operations | | Network | Throughput, latency, packet loss, and route quality | Affects users, APIs, backups, replication, and service-to-service traffic | A fifth layer should be added when the server has a known workload: an application-level test. This may measure requests per second, database transactions, build duration, queue throughput, or another outcome that reflects the real system. The strongest buying decision combines platform benchmarks with one workload-specific test. ## Synthetic Benchmarks and Real-World Tests Answer Different Questions Synthetic benchmarks isolate a resource. Real-world tests measure an outcome. A CPU benchmark can compare compute capacity without requiring your application. A storage benchmark can measure random-read latency under a defined queue depth. A network benchmark can test throughput between two endpoints. These tests are useful because they create repeatable conditions. Real-world tests are closer to business value. They answer questions such as: - How many API requests can the VM process before latency rises? - How long does the production build take? - How many database transactions complete per second? - How quickly can a backup be created and restored? - How many concurrent users can the application support? | Test type | Main advantage | Main limitation | | --- | --- | --- | | Synthetic benchmark | Repeatable and easy to compare | May not reflect the application | | Application load test | Closest to real workload behavior | Harder to reproduce across providers | | Quick benchmark script | Covers several resources quickly | Uses generic settings and external targets | | Long-duration consistency test | Reveals variance and throttling | Requires more time and controlled conditions | Do not choose between synthetic and real-world testing. Use synthetic tests to understand the infrastructure, then use a workload test to confirm that the result matters. ## The VPS Benchmarking Decision Framework Start with the decision you need to make. Running every available benchmark often creates more data without creating more clarity. | Buying question | Most useful test | Result to prioritize | | --- | --- | --- | | Is this VM suitable for a website or API? | CPU plus application load test | p95 latency and sustained request throughput | | Is this plan suitable for a database? | Random storage I/O plus database workload | I/O latency, transaction latency, and consistency | | Should I choose shared or dedicated vCPU? | Repeated CPU and application tests | Variance across runs, not only the best score | | Is the storage genuinely fast? | fio-style random and sequential tests | IOPS, bandwidth, and latency at defined block sizes | | Is the network suitable for users or backups? | Multi-location network tests | Latency, achieved throughput, packet loss, and route stability | | Is the upgrade worth the cost? | Identical tests on both plans | Performance gain per dollar and workload improvement | | Is a provider claim credible? | Repeatable tests at different times | Median result and spread across runs | The correct benchmark is the one that reduces uncertainty around a real buying decision. ## CPU Benchmarks: Compare Speed and Consistency CPU benchmarks commonly report single-core and multi-core performance. Single-core performance matters when a workload depends on one execution thread or has limited parallelism. Many web requests, game loops, scripting tasks, and parts of database execution can be sensitive to single-core speed. Multi-core performance matters when the workload can distribute work across several cores. Build systems, parallel tests, encoding, workers, and data-processing jobs often benefit from more cores. The result that buyers overlook is consistency. A shared-vCPU VM may produce a strong score in one run and a weaker score in another because compute resources are pooled. A dedicated-vCPU VM may produce a similar peak score but lower variance under sustained load. That difference can matter more than the highest number. Compare: - single-core score - multi-core score - completion time - score variation across repeated runs - performance during sustained load - application latency while CPU is busy Do not compare only the advertised CPU model. The same processor family can produce different outcomes depending on clock behavior, CPU allocation, host contention, virtualization, and plan limits. For the CPU allocation decision, read [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). ## Memory Benchmarks: Treat Them as Supporting Evidence Memory benchmarks measure transfer speed and access behavior. They can be useful for databases, caches, JVM workloads, analytics, and servers running several services. However, memory benchmark numbers are usually less useful to buyers than actual memory capacity and workload behavior. A server with fast memory but insufficient RAM may still swap or terminate processes. A server with more RAM may provide a larger database cache and reduce disk activity even when its synthetic memory score is lower. Use memory benchmarks to compare similar plans, not as a substitute for sizing. The more useful questions are: - Does the VM have enough RAM for the working set? - Is swap activity appearing under normal load? - Does application latency improve with more memory? - Can the database keep frequently accessed data in memory? - Do background services compete for memory? Use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) when capacity is the main question. ## NVMe and Storage Benchmarks: IOPS, Bandwidth, and Latency Are Different Storage performance cannot be represented by one number. Sequential bandwidth measures how quickly large continuous files can be read or written. It matters for backups, large file transfers, media processing, and some analytics workloads. Random IOPS measure how many small operations the storage can complete per second. They matter for databases, package managers, container layers, logs, and workloads that access many small blocks. Latency measures how long each operation takes. Average latency is useful, but tail latency is often more important because occasional slow I/O can create visible application pauses. | Storage metric | Best interpreted as | Common workload relevance | | --- | --- | --- | | Sequential read/write bandwidth | Large-file transfer capacity | Backups, media, bulk data movement | | Random read IOPS | Small-block read capacity | Databases, package access, container images | | Random write IOPS | Small-block write capacity | Databases, logs, queues, transactional workloads | | Average latency | Typical I/O response time | General responsiveness | | p95/p99 latency | Slow-operation behavior | User-facing databases and latency-sensitive systems | Tools such as fio can report bandwidth, IOPS, and latency for controlled block sizes, read/write ratios, queue depths, and runtimes. Those settings must remain identical when comparing two servers. Be cautious of storage results when: - the test file is small enough to remain in memory cache - one test uses a different block size or queue depth - the test runs for only a few seconds - read-only results are compared with mixed read/write workloads - a single peak number is presented without latency or consistency “NVMe” describes the storage technology. It does not guarantee identical performance across every provider or VM plan. ## Network Benchmarks: Port Speed Is Not End-to-End Performance Network benchmarks should measure the path your workload will actually use. A provider may advertise a high-capacity network port, but achieved throughput depends on the source and destination, routing, congestion, protocol, packet size, test server capacity, and distance. A 3 Gbps port is a platform characteristic, not a promise that every remote endpoint will receive 3 Gbps. Useful network measurements include: - round-trip latency to important user regions - download and upload throughput - packet loss - jitter for real-time workloads - throughput to backup or object-storage destinations - application-to-database latency when services are separated iperf3 is designed for active network throughput measurements and can report throughput, loss, and related parameters. A meaningful comparison should use several equivalent targets rather than one public speed-test server. Network tests are especially sensitive to geography. Compare servers in equivalent regions and use targets that reflect the audience or dependent systems. A Virginia server and a European server should not be judged from one New York endpoint without acknowledging the location difference. ## Consistency Matters More Than the Best Run The best benchmark result is often the least useful result. Cloud workloads operate throughout the day, not only during a favorable ten-minute window. A plan that reaches a high peak but varies widely may be a weaker choice than a plan with a slightly lower but stable median result. Run equivalent tests more than once and compare: - median result - slowest result - percentage difference between runs - p95 or p99 latency where available - performance at different times of day - behavior during a longer sustained test A practical comparison should include at least three comparable runs. Five or more runs provide a clearer view when performance consistency is central to the buying decision. Variance matters most for: - production databases - latency-sensitive APIs - CI/CD runners - game servers - continuous workers - real-time applications - workloads with strict completion windows For low-risk development or staging servers, occasional variation may be acceptable when the cost advantage is significant. ## Quick Benchmark Scripts Are Screens, Not Final Verdicts Quick scripts are useful because they make initial comparisons easy. YABS, or Yet-Another-Bench-Script, combines CPU and memory testing with fio storage tests and iperf3 network tests. It provides a broad snapshot and is useful for checking whether a new server behaves roughly as expected. A quick script should not be the final decision for a production workload. Its settings are generic, its network targets may not match your users, and a short run may miss long-duration variance. Use different tools for different questions: | Tool or test | Best use | | --- | --- | | YABS | Fast first-pass comparison of CPU, storage, and network | | sysbench | Controlled CPU, memory, file I/O, and database-style workloads | | fio | Detailed storage bandwidth, IOPS, and latency testing | | iperf3 | Network throughput, loss, and route comparisons | | Application load test | Real request, query, job, or build behavior | | Monitoring during production-like load | Resource saturation and tail-latency validation | Quick scripts can consume significant network bandwidth and create CPU or storage pressure. Run them on a disposable test server or during a controlled test window, not casually on a production system. ## Build a Fair VPS Comparison Benchmark results are only comparable when the test conditions are comparable. Record the following for every tested VM: | Test field | What to record | | --- | --- | | Provider and plan | Exact product and billing term | | Region | Data center or cloud region | | CPU model | Reported processor family and architecture | | CPU allocation | Shared or dedicated vCPU | | vCPU and RAM | Exact assigned capacity | | Storage | Type and included capacity | | Operating system | Same distribution and version | | Kernel and tool versions | Versions used during testing | | Test settings | Threads, duration, block size, queue depth, and read/write ratio | | Test time | Date, time, and time zone | | Number of runs | Repetition count | | Price | Current comparable monthly cost | Use the same operating-system image, tool version, test duration, and configuration wherever possible. Disable unrelated background jobs. Allow the server to finish provisioning and updates before testing. Do not compare a freshly booted idle server with a server running production services. Most importantly, compare equivalent product classes. A low-cost shared-vCPU plan and a dedicated-vCPU plan answer different buying needs. The benchmark should reveal the trade-off, not pretend the products are identical. ## Price-Performance Requires More Than Dividing Score by Cost Performance per dollar is useful, but it can become misleading when one score dominates the comparison. A simple CPU-score-per-dollar calculation may favor a plan with weak storage or high variance. A storage-focused calculation may favor a server that is unsuitable for CPU-heavy work. A cheaper server may deliver excellent value for staging but create unacceptable latency in production. Use a weighted scorecard based on the workload. | Workload | Suggested priority | | --- | --- | | Marketing website | Cost, sufficient CPU, latency to users, basic storage | | SaaS API | CPU consistency, p95 latency, memory headroom, network | | Database | Random I/O latency, memory, CPU consistency, backup throughput | | CI/CD runner | Multi-core CPU, build duration, storage, consistency | | Backup server | Sequential throughput, network, storage capacity, cost | | Game server | Single-core performance, jitter, latency, CPU consistency | The best value is the least expensive plan that meets the workload’s performance and reliability requirements. It is not automatically the plan with the largest synthetic score. ## Common VPS Benchmarking Mistakes ### Comparing different regions Distance and routing can dominate network results. Use equivalent regions or explain why the locations differ. ### Comparing different CPU allocation models Shared and dedicated vCPU plans should not be presented as identical products. Consistency is part of the value. ### Running one test once One result cannot show normal variation. Repeat tests and report the median and spread. ### Treating sequential disk speed as database performance Databases often care more about random I/O and latency than large-file transfer speed. ### Treating port speed as achieved throughput The port is one limit in an end-to-end path. Remote routing and endpoint capacity still matter. ### Benchmarking through cache A test dataset that fits in memory can make storage appear faster than the underlying disk behavior. ### Ignoring the application A VPS can win synthetic tests and still perform worse for your workload because of configuration, architecture, or software behavior. ### Testing production without controls CPU, storage, and network benchmarks can affect users and background services. Isolate the test or use a controlled window. ### Using outdated prices Normalize results against current comparable pricing and equivalent billing terms. Introductory promotions and long commitments can distort the comparison. ## How This Applies to Raff VM Plans Raff VM plans use AMD EPYC processors, NVMe storage, and unmetered bandwidth on a 3 Gbps network port. The platform offers General Purpose and CPU-Optimized VM classes, which should be benchmarked as different compute models. General Purpose VMs use shared CPU resources and are designed for websites, development environments, staging, and variable workloads where cost efficiency matters. CPU-Optimized VMs use dedicated CPU resources for workloads that benefit from more consistent compute, such as databases, CI/CD, workers, and latency-sensitive applications. A fair Raff benchmark should therefore compare: - equivalent General Purpose plans against other shared-vCPU plans - equivalent CPU-Optimized plans against dedicated-vCPU plans - identical regions and operating systems - repeated CPU results rather than one peak score - random I/O latency as well as NVMe throughput - network results to relevant U.S. and workload-specific targets - current price and included bandwidth Raff includes unmetered bandwidth, but benchmark traffic still consumes network capacity and can affect the tested workload. Use a new VM or a controlled maintenance window. :::cluster ## When Benchmark Results Should Change Your Buying Decision Benchmark results are useful when they lead to a clear decision. Choose the lower-cost plan when it meets the workload target with enough headroom and acceptable variance. Choose dedicated vCPU when CPU consistency improves a business-critical workload. Choose a storage-strong plan when database or file I/O dominates. Choose a closer region when latency to users matters more than a small synthetic CPU advantage. Do not upgrade because one score looks impressive. Upgrade when the measured improvement affects requests, jobs, queries, build times, user latency, or operational risk. A practical buying rule is: > Define the workload target, run repeatable tests, compare median performance, and pay only for improvements the workload can use. ## Conclusion A useful VPS benchmark compares CPU, memory, storage, network, consistency, price, and one real workload outcome under repeatable conditions. No single score can represent all of those dimensions. Start with a quick benchmark to screen the server. Use controlled tools when a resource matters. Repeat the test to expose variance. Compare equivalent regions and CPU classes. Then validate the decision with the application, database, build, or job that will actually run on the VM. For the next decision, pair this guide with [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu), [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size), and [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). :::cta Deploy Your Server Deploy a Raff VM, run a controlled benchmark, and compare the results against the workload your team actually needs to support. ::: --- ### VPS Uptime SLA Explained: Credits, Exclusions, and What 99.9% Means URL: https://rafftechnologies.com/learn/guides/vps-uptime-sla-explained Description: Learn what a VPS uptime SLA means, how 99.9% converts to downtime, and how credits, exclusions, measurement rules, and claim windows affect buyers. A **VPS uptime SLA** is a provider’s contractual commitment to keep a defined service available for a stated percentage of a measurement period. It also explains what counts as downtime, which events are excluded, how availability is calculated, and what remedy applies if the commitment is missed. A 99.9% SLA does **not** promise zero outages or guarantee that your application will be available 99.9% of the time. It is a conditional service commitment that must be read together with its definitions, exclusions, claim process, and service-credit table. For buyers, the practical question is not simply, “Does this VPS have a 99.9% uptime guarantee?” It is, “What exactly is covered, how much downtime can occur, which failures do not count, and is the remedy meaningful for my workload?” ## What an uptime SLA actually guarantees An uptime percentage becomes useful only when four parts are clear: 1. **Scope:** Which product, region, instance, API, console, network path, or supporting service is covered? 2. **Measurement:** Is availability measured by time, successful requests, individual instances, or an aggregated service pool? 3. **Conditions and exclusions:** Which maintenance events, customer actions, attacks, external network failures, or unsupported configurations are removed from the calculation? 4. **Remedy:** What service credit is available, how is it calculated, and how must the customer claim it? The SLA therefore describes a minimum contractual commitment rather than a complete reliability design. Your VPS can remain technically online while your application is unavailable because of a failed deployment, full disk, database error, firewall rule, expired certificate, or overloaded process. Those application-layer failures may be your operational responsibility rather than provider downtime. This distinction matters when comparing a low-cost plan with a more dependable service. The percentage on a pricing page is only the beginning. The detailed terms determine the commitment’s real value. ## What 99.9% uptime means in real time Availability is commonly calculated with this formula: ```text Availability percentage = (total measured time - counted downtime) / total measured time × 100 ``` Using a 30-day month as a simple reference, the percentages translate into the following approximate maximum downtime: | Availability | Approximate downtime per 30-day month | Approximate downtime per year | |---|---:|---:| | 99% | 7 hours 12 minutes | 3 days 15 hours 36 minutes | | 99.9% | 43 minutes 12 seconds | 8 hours 45 minutes 36 seconds | | 99.95% | 21 minutes 36 seconds | 4 hours 22 minutes 48 seconds | | 99.99% | 4 minutes 19 seconds | 52 minutes 34 seconds | | 99.999% | 25.9 seconds | 5 minutes 15 seconds | These figures are mathematical reference points, not universal credit thresholds. A 31-day month gives a 99.9% allowance of about 44 minutes 38 seconds, while a 28-day month gives about 40 minutes 19 seconds. More importantly, the SLA may exclude maintenance or require an outage to meet a specific definition before any minute is counted. Measurement periods cannot usually be mixed. If an SLA is measured monthly, a perfect month does not normally “bank” availability for a later month. Likewise, the annual figure does not mean one long outage automatically qualifies for a credit if the provider’s contract calculates each billing month separately. ## Read the measurement definition before the headline Two providers can both advertise 99.9% while offering materially different coverage. Review the following details before comparing the percentages. ### What is considered unavailable? Some SLAs count only complete inaccessibility. Others measure failed requests, API responses, regional service availability, or the health of a group of instances. Slow performance, packet loss, intermittent errors, or the failure of one feature may not qualify unless the definition explicitly includes them. A definition can also include a minimum duration. For example, an outage may need to continue for several consecutive minutes before it becomes counted downtime. Several shorter interruptions could affect users without crossing that contractual threshold. ### What is the measurement scope? Determine whether the percentage applies to: - one individual VPS; - all instances in an account; - a specific region; - the compute service only; - attached storage, backups, networking, console access, and APIs separately; - or a broader platform aggregate. A compute SLA does not automatically cover every dependency. If your VM is available but a customer-managed database process has stopped, the compute commitment may still be met. Similarly, a snapshot or backup product may have its own terms. ### Who provides the authoritative data? Your monitoring is essential for understanding user impact, but an SLA may specify that the provider’s own telemetry is authoritative for credit calculations. That creates two legitimate but different records: - **Operational evidence:** what your users and external monitors experienced; - **Contractual evidence:** what the SLA’s defined measurement system recorded. Keep your own timestamps, error logs, support conversations, and affected-resource details even when the provider controls the final calculation. They help you diagnose the incident and submit a complete claim. ## Credits are a billing remedy, not downtime compensation Service credits usually reduce future charges for the affected service. They are not the same as compensation for lost revenue, customer churn, staff time, missed transactions, or reputational damage. Suppose a VPS costs $20 per month and the applicable credit is 10%. The remedy may be $2 in future service credit even if the outage caused a much larger business loss. This does not make the SLA useless. It means the SLA should be treated as: - evidence of the provider’s minimum commitment; - a defined accountability mechanism; - one input into risk and architecture decisions; - not an insurance policy for the business impact of downtime. Read whether credits are automatic or claim-based. Many providers require the customer to open a support request, provide incident details, and file within a limited window. Missing the deadline can remove eligibility even when the outage was real. Also check the credit cap, expiration rules, minimum credit amount, eligible service charges, and whether the credit can be refunded or transferred. A generous percentage can still have limited value when it applies only to a small portion of the monthly bill. ## Exclusions determine the practical value The exclusions section often matters as much as the headline percentage. Common categories include: - announced scheduled maintenance; - emergency maintenance; - customer configuration errors; - customer-installed software and operating-system failures; - resource exhaustion caused by the workload; - malicious traffic or distributed denial-of-service events; - internet or third-party failures outside the provider’s control; - force majeure events; - suspended, overdue, abusive, or non-compliant accounts; - unsupported, preview, or incorrectly configured services. Exclusions are not automatically unreasonable. A provider cannot credibly guarantee every application, third-party network, or customer action. The buyer’s job is to identify which excluded risks still threaten the workload and decide who will control them. For example, an SLA may exclude a broken application deployment. You can reduce that risk with tested releases and rollback procedures. It may exclude customer firewall mistakes. You can reduce that risk with change review and configuration backups. It may exclude a single-server application failure even when the underlying VM remains healthy. You can reduce that risk with process supervision, health checks, backups, and—where justified—redundant architecture. ## The uptime SLA decision framework Use the SLA as a structured buying input rather than a single score. | Decision area | Question to ask | Why it matters | |---|---|---| | Business impact | What happens after 5, 20, or 45 minutes of outage? | Determines whether 99.9% is operationally acceptable. | | Covered service | Does the commitment cover compute only or also storage, networking, backups, and APIs? | Reveals uncovered dependencies. | | Downtime definition | Does degradation count, or only complete inaccessibility? | Affects whether user-visible incidents qualify. | | Measurement window | Monthly, annual, per region, per instance, or aggregated? | Changes how outages are calculated. | | Exclusions | Which likely failure modes are outside the commitment? | Shows which risks remain yours. | | Credit value | What would the actual credit be at your monthly spend? | Prevents treating a percentage as business-loss protection. | | Claim process | What evidence and deadline are required? | Determines whether the remedy is realistically usable. | | Recovery design | Can the workload recover without waiting for a credit decision? | Reliability depends on operations and architecture, not only contract terms. | A simple buyer rule is to compare the **allowed counted downtime** with the **maximum tolerable user impact**. If the workload cannot tolerate the contract’s implied downtime—or important incidents are excluded—the solution requires additional resilience rather than a more optimistic interpretation of the percentage. ## When to choose / when not to choose Choose a VPS with a 99.9% monthly SLA when the workload can tolerate roughly 43 minutes of counted provider-layer downtime in a 30-day month, the exclusions are acceptable, and your team has a practical recovery path for application-level failures. This can be appropriate for many company websites, internal tools, development environments, staging systems, small SaaS products, and business applications with clear backups and operational ownership. Do not choose a provider solely because its headline percentage is higher. A 99.99% claim with narrow definitions, broad exclusions, weak support, or no meaningful remedy may be less useful than a clearly documented 99.9% commitment. You should also avoid treating a single-VM SLA as sufficient for a workload that requires near-continuous availability. In that case, evaluate application redundancy, load balancing, database resilience, backup recovery, and failure isolation separately. A higher SLA is most valuable when its scope and definitions match the service your users actually depend on. It is less valuable when the application has many uncontrolled single points of failure above the infrastructure layer. ### How the wrong choice shows up in practice The wrong interpretation usually appears after the first serious incident. The buyer expects a full refund, but the SLA offers a small future credit. The application was unreachable, but the VM remained online, so the incident does not meet the downtime definition. An external monitor detected several interruptions, but each was shorter than the minimum counted interval. A claim is rejected because it was filed after the deadline or lacked timestamps. Or the provider meets its compute commitment while a customer-managed database, DNS record, or deployment failure keeps the application offline. These outcomes are rarely solved by debating the percentage after the event. They are prevented by reading the terms before purchase and assigning responsibility for every failure layer. ## SLA, SLO, monitoring, and high availability are different These concepts support one another but should not be merged: - **SLA:** the provider’s contractual commitment and remedy. - **SLO:** the reliability target your team sets for the workload. - **Monitoring:** the system that detects and records actual behavior. - **High availability:** an architecture designed to keep serving users when components fail. - **Disaster recovery:** the process for restoring service and data after a severe disruption. An SLA can inform your internal target, but it does not create the target for you. Monitoring tells you what happened, but does not itself prevent an outage. High availability can reduce user impact, but it introduces cost and operational complexity. Disaster recovery limits the damage of major failures, but recovery time may still be longer than the SLA’s allowed downtime. For implementation guidance, keep monitoring decisions in the [cloud server monitoring guide](/learn/guides/cloud-server-monitoring-basics). For architecture-level resilience, see [high availability vs disaster recovery](/learn/guides/high-availability-vs-disaster-recovery-small-teams). This guide remains focused on interpreting the provider commitment. :::cluster ## How Raff's current VPS SLA works Raff’s published Service Level Agreement, last updated May 1, 2026, states a **99.90% monthly service commitment** for Virtual Machines, Block Storage, Snapshots, and Backups. Each service should be evaluated within the scope and definitions of the legal SLA. The current credit schedule is: | Monthly availability in the published SLA | Service credit | |---|---:| | 99.90%–99.0% | 10% of monthly charges for the affected service | | 99.0%–95.0% | 25% | | Below 95.0% | 100% | Credits are capped at the monthly charges for the affected service, apply to future charges, are not cash refunds, and expire after 12 months or when the account ends. The current Raff definition counts downtime when the service is completely inaccessible, returns errors, or provides no API or console response for more than five consecutive minutes. Monthly availability is calculated from total minutes minus counted unavailable minutes, after applying exclusions. Raff’s internal monitoring is the authoritative source for the contractual calculation. Current exclusions include scheduled maintenance announced at least 24 hours in advance, short emergency security or critical maintenance, customer actions or misuse, customer-installed software and configuration failures, DDoS events, force majeure, external internet or third-party failures outside Raff’s control, and accounts that are overdue, suspended, or violating the Terms of Service. A credit request must currently be submitted to support within 30 days with the incident date, time, duration, and affected services. Validated credits are applied in the next billing cycle. These points summarize the published terms for buyer education. The current [Raff Service Level Agreement](/legal#service-level-agreement) remains the controlling document and should be reviewed directly before making a contractual or purchasing decision. ## VPS SLA buyer checklist Before selecting a VPS provider, confirm: - the exact service and region covered; - whether the commitment is monthly or annual; - the formula used to calculate availability; - the minimum outage duration that counts; - whether degraded performance and partial failures qualify; - who supplies the authoritative monitoring data; - scheduled and emergency maintenance treatment; - customer configuration and software exclusions; - DDoS, upstream-network, and force-majeure treatment; - credit percentages and the charges they apply to; - whether credits are automatic or claim-based; - the claim deadline and required evidence; - whether the workload needs redundancy beyond the provider SLA. Use this checklist alongside the [VPS hosting decision guide](/learn/guides/virtual-private-server-hosting) and the analysis of [cheap VPS vs reliable VPS](/learn/guides/cheap-vps-vs-reliable-vps). Price, included resources, support, recovery options, and operational clarity should be evaluated together. ## Summary A VPS uptime SLA is useful when you read it as a complete set of terms rather than a headline percentage. At 99.9%, the mathematical reference is about 43 minutes 12 seconds of downtime in a 30-day month, but only incidents that meet the SLA’s definition and survive its exclusions affect the contractual calculation. The strongest buying decision connects four things: the provider’s commitment, your workload’s tolerance for downtime, the failure modes your team still owns, and the recovery design available when something goes wrong. Service credits create accountability, but they do not restore an application or compensate for the full business impact of an outage. :::cta Deploy Your Server Choose a Raff VM after reviewing the uptime commitment, exclusions, recovery path, and operational ownership required by your workload. ::: ## Sources - [Google SRE: Availability Table](https://sre.google/sre-book/availability-table/) - [Microsoft Learn: How to Read a Service-Level Agreement](https://learn.microsoft.com/en-us/azure/reliability/concept-service-level-agreements) - [Raff Service Level Agreement](/legal#service-level-agreement) --- ### VPS Pricing Models: Monthly Plans, Hourly Billing, and Long-Term Discounts URL: https://rafftechnologies.com/learn/guides/vps-pricing-models-monthly-hourly-discounts Description: Compare monthly VPS plans, hourly and pay-as-you-go billing, long-term discounts, prorated credits, and the pricing model that fits your workload. A **VPS pricing model** is the rule a provider uses to calculate when and how you pay for a virtual server. The most common models are a fixed monthly plan, hourly or per-second pay-as-you-go billing, a monthly-capped usage model, and a discounted long-term term. These models affect flexibility and predictability, but they do not tell you the full cost of the server. A monthly plan is usually easiest for an always-on production workload. Hourly billing is useful for short-lived or irregular servers. Long-term discounts can reduce the effective monthly rate when the workload is stable enough to justify the commitment. This guide focuses only on **billing cadence and commitment structure**. For resource prices, bandwidth, backups, licensing, and the complete monthly budget, use [How Much Does a Cloud Server Cost in 2026?](/learn/guides/cloud-server-cost-2026). ## Billing model and total cost are different decisions The billing model explains how charges accumulate. Total cost explains how much the complete workload costs after every required resource and service is included. A VPS can have simple monthly billing and still become expensive because it needs more RAM, additional storage, backups, software licenses, support, or multiple environments. Another VPS can have granular hourly billing but create a higher bill because it runs continuously at a higher effective rate. Keep these questions separate: | Question | What it evaluates | |---|---| | How often is the server billed? | Hourly, per-second, monthly, yearly, or another term | | Is there a minimum term? | Whether the buyer can leave without paying for the remaining term | | Is usage capped? | Whether hourly charges stop at a published monthly maximum | | What happens when the VM is stopped? | Whether reserved resources continue to generate charges | | What happens when the VM is deleted? | Whether billing ends immediately or unused time becomes a credit | | What is included? | Bandwidth, storage, backups, IPs, support, and other services | | What is the effective monthly cost? | The complete cost after discounts, usage, and add-ons | This distinction prevents a common comparison error: treating a more granular billing unit as proof that a provider is cheaper. ## The main VPS pricing models Most VPS offers fit one of these structures. | Pricing model | How it works | Best fit | Main risk | |---|---|---|---| | Fixed monthly | A known amount renews each month | Always-on websites, apps, databases, and business servers | Paying for an unused server that nobody removes | | Hourly or per-second | Charges accumulate while the provider considers the resource billable | Temporary tests, short projects, CI workers, burst environments | Leaving resources running or assuming “stopped” means free | | Monthly-capped usage | Usage accrues in small units but cannot exceed a stated monthly maximum for the same resource | Teams wanting short-term flexibility with a predictable ceiling | Misunderstanding which resources or add-ons are included in the cap | | Long-term discounted | A lower effective rate is offered for a longer term or usage commitment | Stable production workloads with predictable demand | Committing before the workload, provider, or required size is proven | | Prepaid balance or credits | Charges are deducted from funds added in advance | Budget control, promotions, and consolidated account spending | Confusing the payment method with the underlying billing model | A provider can combine several of these. For example, it may bill usage per second, show a monthly maximum, accept prepaid balance, and offer a separate committed-use discount. Read the lifecycle and refund rules rather than classifying a product from one word on the pricing page. ## Fixed monthly VPS plans A fixed monthly plan charges a known amount for a defined server configuration and billing period. This is the simplest model for a server that needs to remain online continuously. Monthly pricing works well for: - Production websites and applications - Databases and caches - Docker hosts - Remote development environments used every day - Windows business servers - Monitoring and automation services - Any workload expected to run throughout the month The main advantage is forecastability. The team can budget the base server without calculating running hours. This also makes provider comparisons easier when the plans include similar resources. The weakness is operational waste. A forgotten development VM, abandoned staging server, or completed migration environment continues to cost money until someone deletes or cancels it. Monthly pricing does not remove the need for resource ownership and periodic cleanup. A monthly plan may also be prorated when you resize or delete the resource. Proration does not automatically make the product an hourly-billed VPS. It can simply mean that the provider calculates an unused balance or upgrade difference using smaller time units. ## Hourly and pay-as-you-go VPS billing Hourly billing charges for the time a resource is considered active or allocated. Some platforms calculate the final amount per second even though they display an hourly rate. This model is useful when the server has a clear short lifecycle: - A test environment needed for several hours - A temporary migration server - A CI or build worker created for a job - A short benchmark - A training lab - A preview environment - A seasonal or event-based workload The financial benefit depends on deletion discipline. If a temporary server is left running for the full month, granular billing may offer no advantage over a monthly plan and can be more expensive. Also verify what “stopped” means. Some providers continue billing a powered-off VM because CPU allocation, disk, IP addresses, or other capacity remains reserved. DigitalOcean, for example, states that CPU Droplets continue to be billed while powered off and that billing ends when the Droplet is destroyed. The safe rule is: > Do not assume that shutting down the operating system or powering off the VM ends infrastructure billing. Check whether billing stops on shutdown, deallocation, suspension, or deletion. Those actions are not equivalent across providers. ## Monthly-capped hourly billing A monthly-capped model combines granular billing with a ceiling. Usage is calculated in hourly or per-second units, but the same resource does not exceed a published monthly price after enough usage accumulates. This structure can be attractive because it supports both short and long lifecycles: - Delete the VM early and pay for partial usage - Keep it all month and reach the monthly ceiling - Avoid paying more than the stated cap for the base resource However, the cap may apply only to compute. Storage, backups, snapshots, additional IPs, licenses, or traffic can remain separately billable. The provider may also calculate the monthly cap with a specific divisor or billing calendar. Before relying on a cap, confirm: - The exact unit used for billing - The minimum charge - The number of hours used to calculate the monthly maximum - Whether stopped resources remain billable - Whether the cap applies per VM or across the account - Which add-ons remain outside the cap - Whether deleting and recreating the VM resets the calculation A monthly price displayed next to an hourly rate is not enough. The billing documentation should explain how the two numbers interact. ## Long-term discounts and committed pricing Long-term pricing reduces the effective rate in exchange for a longer term, an upfront payment, or a minimum usage commitment. Common structures include: - Paying for a year and receiving free months - A discounted 12-month or 24-month subscription - A one-year or three-year compute usage commitment - A reservation tied to a particular instance family, region, or configuration - A flexible commitment that applies across eligible compute usage Large cloud platforms often separate commitment discounts from the actual server lifecycle. AWS Savings Plans, for example, discount eligible usage in exchange for a one-year or three-year hourly spending commitment. Reserved Instances can apply a discount to a specified configuration, but the buyer pays for the term regardless of whether the expected usage occurs. This means “reserved” or “committed” pricing does not necessarily mean a particular physical server is held for you. Purchasing discounts and capacity reservations can be separate decisions. Long-term pricing is most useful when: - The workload has been stable for several months - The required server size is unlikely to change materially - The provider has already been tested in production - The business can use the committed capacity throughout the term - The discount is meaningful after add-ons and operational costs It is less attractive for an early MVP, an uncertain migration, a short client project, or a workload likely to move to another architecture. The correct comparison is not only the discount percentage. Calculate the cost of unused commitment if the server is downsized, deleted, or migrated early. ## Prepaid balance is not the same as pay-as-you-go pricing A prepaid balance explains how the account pays its bill. It does not necessarily explain how the underlying resource is priced. For example, an account may add funds in advance and then use that balance to pay for: - A monthly VM subscription - Hourly compute - Storage usage - Backups - Additional IP addresses - Several products under one account The words “credits,” “balance,” and “pay as you go” are sometimes used loosely. Confirm whether the provider means: 1. Usage-based resource billing 2. Prepaid account funding 3. Promotional credits 4. Refund credits from deleted or resized resources These are different financial mechanisms. Promotional credits can also have expiration dates, eligible-product limits, or restrictions on refunds. Account balance should not be treated as cash unless the provider’s terms explicitly say it can be withdrawn. ## What stopping, deleting, and cancelling actually change The server lifecycle affects the bill differently across platforms. | Action | Possible billing result | |---|---| | Shut down inside the operating system | VM may remain fully billable because the resource still exists | | Power off in the dashboard | Compute may remain reserved and billable | | Deallocate | Some platforms release compute billing but retain storage and IP charges | | Delete or destroy | Compute billing usually ends, while detached storage or backups may remain | | Cancel renewal | Resource may stay active until the current term ends | | Resize | Provider may charge or credit the difference for the remaining period | Always verify the provider-specific definition. The same interface label can have different billing effects. Deletion also has an operational consequence: local disk data may be removed. Never delete a VM only to stop billing before confirming that required data, backups, snapshots, and configuration have been preserved. ## The VPS pricing-model decision framework Use this framework before selecting a billing model. | Decision area | Question | Better fit | |---|---|---| | Expected lifetime | Will the VM run for hours, weeks, or continuously? | Short: hourly; continuous: monthly or committed | | Utilization pattern | Is demand intermittent or steady? | Intermittent: usage-based; steady: monthly | | Deletion discipline | Will automation or an owner remove temporary resources? | Strong discipline supports hourly savings | | Workload maturity | Is the required size proven? | Proven size supports a longer term | | Provider confidence | Has support, reliability, and performance been validated? | Longer terms only after validation | | Budget preference | Is a stable invoice more important than fine-grained usage? | Stable invoice favors monthly plans | | Resize likelihood | Is the VM likely to change class or architecture soon? | High uncertainty favors flexible terms | | Add-on exposure | Are bandwidth, storage, licenses, or backups separate? | Compare complete bill, not compute cadence | | Exit cost | What happens to unused time or commitment? | Prefer clear refunds, credits, or transferable value | A practical decision rule is: - Choose the shortest flexible model while the workload is uncertain. - Move to monthly pricing when the server becomes continuously required. - Consider a longer term only after the workload and provider are proven. ## When to choose / when not to choose ### Choose a monthly VPS plan when Monthly pricing is usually the right fit when the server will remain online throughout the billing period and the team values a stable invoice. This includes most production websites, SaaS applications, databases, Docker hosts, and business systems. It is particularly useful when the provider includes bandwidth, support, security, or backup allowances in the plan, because the complete monthly cost becomes easier to explain. ### Choose hourly or pay-as-you-go billing when Choose granular usage billing for disposable or short-lived environments with a clear owner and deletion policy. The model works best when automation creates and removes resources, or when the team reliably deletes them after use. Do not select hourly billing only because the displayed hourly number looks small. Estimate the full-month equivalent and include storage, IPs, snapshots, traffic, and licensing. ### Choose a long-term discount when A longer term can make sense after the workload has stable usage, the correct VM size is known, and the provider has already met performance and support expectations. The discount should compensate for the reduced flexibility. Compare the savings with the financial impact of early deletion, downsizing, migration, or architectural change. ### Do not choose a billing model from the headline alone Avoid a plan when the provider does not clearly explain: - When billing starts and stops - Whether powered-off VMs remain billable - How monthly caps are calculated - What happens to unused time - Whether credits expire - Which resources are excluded from the base price - Whether long-term payments are refundable or transferable A simple headline can hide a complicated lifecycle. ### How the wrong choice shows up in practice The wrong pricing model usually becomes visible through waste or constraint. A team chooses hourly billing for a development server, leaves it running for months, and pays more than expected. Another team buys a long-term term before measuring usage, then discovers that the application needs a different VM class. A buyer assumes a stopped server is free, but compute continues to be billed. A monthly plan looks predictable until separate bandwidth, backup, IP, or license charges appear. The opposite problem also occurs. A continuously running production server stays on an expensive on-demand rate even after its usage has been stable long enough for a safe discount. The team preserves flexibility it no longer needs and pays for that flexibility every month. The solution is not one universally best billing model. It is matching commitment length to workload certainty. :::cluster ## How Raff's current VM billing works Raff currently presents VM plans with three term options: **monthly, 1-year, and 2-year**. The current VM page displays a yearly discount and a larger 24-month discount, while the pricing page describes the annual term as two months free and the 2-year term as up to six months free depending on the plan. Raff does **not** present a separate hourly VPS rate. The base product is term-based rather than an hourly compute meter. The current product page also states that deleting a VM returns unused time to the account balance, calculated to the hour. Upgrades charge the difference for the rest of the current period, while downgrades return the unused difference to the balance on a pro-rata basis. That distinction is important: - **Billing model:** monthly, 1-year, or 2-year VM term - **Proration:** unused time or plan differences calculated in smaller time units - **Payment balance:** returned value remains available in the Raff account for other resources Hourly proration does not mean the VM is sold through hourly billing. The product page also distinguishes cancelling renewal from deleting the resource. Cancelling means the subscription remains active until the end of the current period and does not renew. Deleting the VM is the resource-removal action associated with the unused-time balance calculation. Buyers should confirm the current dashboard wording and preserve necessary data before either action. Raff currently includes unmetered bandwidth and DDoS protection with VM plans. Optional add-ons, extra storage or backups beyond the included pool, and additional IP addresses can still affect the complete cost. Because pricing terms can change, review the current [Raff pricing page](/pricing) and [Raff VM page](/products/raff-vm) before purchasing or renewing a longer term. :::cta View Raff Pricing Compare Raff's monthly, 1-year, and 2-year VM terms, then choose the shortest commitment that fits your workload certainty. ::: ## VPS billing checklist Before buying a VPS, verify: - The billing unit and renewal period - Whether the displayed monthly amount is a cap or a subscription price - Whether powered-off or stopped VMs remain billable - The exact action that ends compute charges - Minimum charges and billing granularity - Refund, balance-credit, and expiration rules - Resize proration for upgrades and downgrades - Long-term term cancellation rules - Included bandwidth and overage treatment - Storage, backup, snapshot, IP, and license charges - Whether support is included - Taxes and invoice timing - Who owns deletion of temporary environments Use the [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) for the broader hosting decision. Use [Cheap VPS vs Reliable VPS](/learn/guides/cheap-vps-vs-reliable-vps) to evaluate whether a low price is supported by acceptable reliability and support. Use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) before accepting a long-term discount tied to a specific configuration. ## Summary Monthly, hourly, monthly-capped, long-term, and prepaid models solve different financial problems. Monthly plans make always-on infrastructure easier to budget. Hourly and per-second billing fit short-lived resources when the team reliably removes them. Long-term discounts reward stable demand but reduce flexibility. The most important checks are when billing starts, what action stops it, whether stopped resources remain chargeable, what happens to unused time, and which add-ons sit outside the advertised price. Raff currently uses monthly, 1-year, and 2-year VM terms. It calculates certain unused-time credits and resize differences on a pro-rata basis, but that should not be described as hourly VPS billing. ## Sources - [Raff VM](https://rafftechnologies.com/products/raff-vm) - [Raff Pricing](https://rafftechnologies.com/pricing) - [DigitalOcean Droplet Pricing](https://docs.digitalocean.com/products/droplets/details/pricing/) - [Amazon EC2 Billing and Purchasing Options](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-purchasing-options.html) - [AWS Savings Plans](https://docs.aws.amazon.com/savingsplans/latest/userguide/what-is-savings-plans.html) - Date verified: 2026-07-29 --- ### VPS Setup Checklist: What to Configure After Deployment URL: https://rafftechnologies.com/learn/guides/first-cloud-server-after-provisioning Description: Use this VPS setup checklist after deployment to configure updates, SSH access, firewall rules, monitoring, backups, DNS, and recovery in the right order. A newly deployed VPS is not production-ready just because it is running. **Before you install an application, verify the server, apply updates, create a safer administrator account, configure SSH access and firewall rules, enable monitoring, and define a backup path.** This checklist explains the correct order and the decision behind each step without replacing the detailed setup tutorials. DataForSEO groups the strongest search demand around `how to set up a VPS`, `VPS setup`, and `VPS server setup`. This guide owns the post-deployment checklist intent. Command-by-command Linux hardening remains in the linked tutorials. ## VPS setup checklist at a glance | Priority | Configuration area | Why it comes now | | --- | --- | --- | | 1 | Verify the deployed server | Confirms the image, resources, networking, and access path are correct | | 2 | Apply operating-system updates | Reduces exposure to already-patched vulnerabilities | | 3 | Create an administrative user | Limits routine use of the root account | | 4 | Configure SSH keys | Replaces password-only remote access with stronger authentication | | 5 | Review root and password login | Reduces unnecessary SSH attack paths after key access is proven | | 6 | Configure the firewall | Exposes only the services the workload needs | | 7 | Set automatic security updates | Keeps critical patches moving between maintenance windows | | 8 | Configure hostname, DNS, and time | Prevents service, certificate, logging, and monitoring confusion | | 9 | Enable monitoring and alerts | Detects resource pressure and service failure before users report it | | 10 | Configure backups and restore ownership | Creates a recovery path before production data appears | | 11 | Deploy the workload | Application installation begins only after the server baseline is ready | The exact implementation differs between Linux distributions and Windows Server. The operating principle is the same: verify first, reduce exposure, create visibility, and only then deploy the application. ## Verify the server before changing it Confirm that the VM matches the intended deployment before installing packages or copying data. Review: - operating system and version - kernel and architecture - assigned vCPU and memory - disk capacity and mounted filesystems - public and private IP addresses - DNS resolution - current time and time synchronization - console or recovery access A mismatch is easiest to correct while the server is empty. Also record how emergency access works before changing SSH or firewall settings. A browser-based console or recovery workflow is valuable when a remote-access rule is misconfigured. ## Apply operating-system and package updates Cloud images are maintained baselines, but packages can change between image creation and deployment. Apply available updates before building the application stack. On Ubuntu, package updates, security maintenance, and reboot requirements should follow the current Ubuntu Server documentation. A kernel or core library update may require a reboot before the running system uses the new version. Do not combine the first patch cycle with an application migration or major architecture change. Establish a clean server baseline first. For the exact Ubuntu commands, use [Secure an Ubuntu 24.04 Server](/learn/tutorials/secure-ubuntu-24-04-server). ## Create a non-root administrative account Use a named administrative account for normal operations and grant only the privileges required for the role. Direct root access may be available during provisioning, but it should not become the default operating habit. A named account improves accountability and reduces the chance that every command runs with unrestricted privileges. It does not eliminate risk: an account with unrestricted `sudo` can still gain full control. The value comes from clearer identity, controlled privilege escalation, and the ability to remove one person’s access without rotating a shared root workflow. For a team, avoid shared SSH credentials. Each administrator should use an individual key and an access-removal process. ## Configure SSH key authentication SSH keys are the preferred access method for Linux administration because they avoid password-only remote login and can be issued per person or automation workflow. The private key should remain on the administrator’s trusted device or approved credential system. Only the public key belongs on the server. Protect private keys with appropriate file permissions and, where practical, a passphrase or hardware-backed key. Test key-based access from a second terminal before changing password or root-login settings. Keep the current session open until the new path has been verified. Use [Set Up SSH Keys on Ubuntu 24.04](/learn/tutorials/set-up-ssh-keys-ubuntu-24-04) for the implementation steps. ## Decide how root and password login should work After key access for a named administrator has been tested, review whether direct root login and SSH password authentication are still required. A common production baseline is: - named user access - SSH keys for remote authentication - privilege escalation through `sudo` - direct root login restricted or disabled - password authentication restricted or disabled after testing This is not a universal rule. Break-glass access, configuration-management systems, compliance controls, and team maturity can change the design. The important point is to make the decision explicitly and preserve a tested recovery path. Never close the original session until the new SSH configuration has been tested. Remote-access mistakes are operational incidents, not only security issues. ## Configure a default-deny firewall policy A firewall should allow the minimum inbound access required by the workload. For a public web server, the initial inbound set may include: - the administrative SSH path - HTTP on port 80 - HTTPS on port 443 That does not mean every server should open all three ports. A database-only VM, internal worker, VPN endpoint, or private service needs a different policy. Databases, caches, queues, and administrative dashboards should normally use localhost, a private network, a VPN, a bastion path, or a restricted source range instead of broad public exposure. Allow the administrative path before enabling the firewall. Use [Set Up UFW on Ubuntu 24.04](/learn/tutorials/set-up-ufw-firewall-ubuntu-24-04) for Linux-specific commands and [Firewall Best Practices for Cloud Servers](/learn/guides/firewall-best-practices-cloud-servers) for the policy decision. ## Enable automatic security maintenance deliberately Automatic security updates reduce the time between a security fix becoming available and being installed. They should be configured with an explicit reboot and maintenance policy rather than enabled without operational planning. Decide: - which repositories and update classes are allowed automatically - whether automatic reboots are permitted - when reboots can occur - how failed updates are reported - which updates require staging validation Automatic security maintenance does not replace planned upgrades. Application dependencies, database changes, major distribution upgrades, and configuration changes still need testing and change control. ## Configure hostname, DNS, and time synchronization Server identity and time configuration affect more systems than expected. Set and verify: - a meaningful hostname - forward and reverse DNS where required - the correct time zone for operations - NTP or system time synchronization - DNS records used by the application Incorrect time can break certificate validation, authentication, distributed logs, scheduled tasks, database replication, and incident analysis. Incorrect hostname and DNS configuration can also create confusion in monitoring and automation. Do not point production DNS to the server before the application, TLS, firewall, and health checks are ready. ## Enable monitoring before production traffic A VPS needs both infrastructure visibility and service-level checks. Monitor at least: - CPU use and load - memory and swap - disk space and inode use - disk I/O pressure - network traffic and errors - service status - external application availability - certificate expiry - backup age and failure Resource graphs explain what the VM is doing. External health checks show whether users can reach the service. Application logs and error monitoring explain why the workload is failing. Set alerts with enough context to act. A dashboard that nobody reviews is not an operational control. Use [Cloud Server Monitoring Basics](/learn/guides/cloud-server-monitoring-basics) for the broader monitoring model. ## Define backups before data arrives Backup design should be in place before the server stores production data. Separate the layers: - **Infrastructure snapshot:** fast rollback before risky server changes - **Scheduled VM backup:** broader server recovery according to the selected retention - **Application or database backup:** recovery that understands the workload’s data format - **Off-server copy:** protection from server loss and some account or platform failures A snapshot is not automatically a complete database backup. A database dump is not automatically a complete server recovery plan. Use the mechanism that matches the failure mode. Document: - what is backed up - how often it runs - where copies are stored - who can delete them - how long they are retained - who owns restoration - when the last restore test succeeded Read [Snapshots vs Backups](/learn/guides/snapshots-vs-backups-cloud-server) for the infrastructure distinction. ## Review application and network exposure before deployment Before installing the workload, decide which services belong on the public internet and which should remain internal. A common small application may include: - public reverse proxy or load balancer - application process bound to localhost or a private interface - database reachable only through a private path - administrative access limited by key, source range, VPN, or bastion - backup destination outside the VM One-server deployments can still use clear boundaries. Do not expose a database publicly merely because the application and database share one VM. ## Linux and Windows setup paths are different This guide owns the decision sequence, not one operating system’s commands. For Linux, the work commonly includes SSH, `sudo`, package updates, UFW or another firewall, system services, logs, and unattended security updates. For Windows Server, the equivalent baseline includes administrator access, Windows Update, Remote Desktop policy, Windows Defender Firewall, account controls, monitoring, backup, and application-specific roles. Do not copy Linux controls into Windows terminology or assume a Windows VPS should expose RDP broadly without additional access controls. ## Decision framework: when is the VPS ready? A new VPS is ready for its first workload when the team can answer yes to the following: 1. Does the server match the intended image, region, and resource plan? 2. Are current security updates installed? 3. Is administrative access named, tested, and recoverable? 4. Are unnecessary password and root access paths restricted? 5. Does the firewall expose only required services? 6. Are time, hostname, and DNS correct? 7. Will the team be alerted about service failure, disk exhaustion, and backup failure? 8. Is there a documented backup and restore owner? 9. Are internal services kept off the public interface where practical? 10. Can the workload be rolled back or restored after a failed deployment? A server that is merely reachable is provisioned. A server that passes this checklist is ready to host a workload. :::cluster ## How this applies on Raff A [Raff Linux VM](/products/linux-vm) provides the server environment, operating-system choice, network access, and infrastructure controls needed to build this baseline. The customer still owns operating-system configuration, application security, patch policy, monitoring, and workload recovery unless a managed product explicitly transfers that responsibility. Use [Private Cloud Networks](/products/private-cloud-networks) when application, database, worker, and internal services should communicate without unnecessary public exposure. Use [Data Protection](/products/data-protection) for infrastructure backups and snapshots, then add application-aware backups where the workload requires them. The live [Raff pricing page](/pricing) should be used for current plan selection. This guide intentionally avoids historical plan prices and universal utilization thresholds because the correct VM size depends on the workload, software stack, traffic, and required headroom. ## Conclusion The correct VPS setup order is simple: verify the server, patch it, establish controlled administrative access, reduce network exposure, create monitoring and recovery, and then deploy the application. This page remains a checklist and decision guide. Use the linked tutorials for exact commands, and use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) when capacity—not initial configuration—is the main question. :::cta Deploy Your Server Create a Raff VM, apply a secure baseline, and deploy only after access, monitoring, and recovery are ready. ::: ## Sources - [Ubuntu Server documentation: Security](https://documentation.ubuntu.com/server/explanation/security/) - [Ubuntu Server documentation: OpenSSH](https://documentation.ubuntu.com/server/how-to/security/openssh-server/) - [Ubuntu Server documentation: Automatic updates](https://documentation.ubuntu.com/server/how-to/software/automatic-updates/) - Date verified: 2026-07-29 --- ### SaaS Infrastructure Checklist Before Your First Enterprise Customer URL: https://rafftechnologies.com/learn/guides/startup-infrastructure-checklist-enterprise-customer Description: Use this SaaS infrastructure checklist to prepare access, environments, secrets, backups, monitoring, incident response, and evidence before enterprise onboarding. Your first enterprise customer does not require Fortune 500 infrastructure, but it does require evidence that your SaaS can be operated responsibly. **Before enterprise onboarding, lock down access, separate environments, control secrets, reduce public exposure, define backup and restore ownership, monitor critical services, and document how incidents are handled.** The goal is not to add every security tool. The goal is to remove obvious trust gaps before procurement, security review, or technical due diligence exposes them. ## Enterprise-readiness checklist at a glance | Area | Minimum evidence to prepare | | --- | --- | | Governance | Named owners for production, security, incidents, and recovery | | Identity and access | Named accounts, MFA, least privilege, access removal process | | Environment separation | Distinct development, staging, and production boundaries | | Secrets | No secrets in code; separate credentials by environment; rotation process | | Network exposure | Only required services public; databases and internal services private | | Data protection | Documented backups, retention, restore testing, recovery owner | | Monitoring | Uptime, application errors, infrastructure health, backup failure alerts | | Change control | Review, testing, deployment, and rollback process | | Incident response | Detection, escalation, containment, communication, recovery steps | | Evidence | Architecture diagram, control summary, logs, backup records, and policies | Enterprise buyers are usually evaluating whether your team can explain and prove these controls—not whether your stack is large. ## Start with governance and ownership NIST Cybersecurity Framework 2.0 organizes cybersecurity around six functions: Govern, Identify, Protect, Detect, Respond, and Recover. For a startup, the most important addition is often Govern: someone must own the decisions. Define who owns: - production infrastructure - customer data - identity and access - security questionnaires - incident coordination - backup and restore - vendor and dependency review - customer communication during incidents A control without an owner is usually a temporary habit, not a reliable process. ## Lock down identity and production access Use named accounts for every person with access to production systems. Shared cloud, database, SSH, and admin credentials make access reviews and incident investigation harder. Your minimum baseline should include: - MFA on critical accounts - individual SSH keys or named admin identities - least-privilege roles - separate human and automation credentials - a documented joiner, mover, and leaver process - periodic access review - emergency or break-glass access with controlled use Not every engineer needs direct production access. Separate the ability to develop, approve, deploy, and administer infrastructure where practical. ## Separate development, staging, and production Enterprise buyers expect production changes to follow a controlled path. At minimum, separate: - application configuration - credentials and API keys - databases and storage - deployment targets - DNS and domains - logging and monitoring - customer data Staging does not need to duplicate every production resource. It needs to reproduce the release path and the failure modes most likely to affect customers. Never use live customer data in non-production environments without a defined legal, security, and privacy basis. Prefer synthetic, anonymized, or masked data. Use [Dev vs Staging vs Production](/learn/guides/dev-staging-production-cloud-environments) for the environment decision. ## Build a credible secrets-management process Enterprise questionnaires often ask where secrets are stored, who can access them, and how they are rotated. A responsible minimum is: - no secrets committed to source control - separate secrets per environment - limited retrieval permissions - encrypted storage and transport - rotation after personnel or incident changes - short-lived credentials where supported - an inventory of high-impact credentials - no production secrets in tickets, screenshots, or chat history Environment variables can be acceptable for small systems when the secret source, access path, and rotation process are controlled. As the system grows, a managed secrets store or vault can reduce manual handling. Read [Secrets Management for Cloud Apps](/learn/guides/secrets-management-cloud-apps-env-vars-vaults-managed-stores) for the deeper decision. ## Reduce the public attack surface Expose only services that customers or approved administrators must reach. A common SaaS pattern is: - public load balancer or reverse proxy - application services on private or local interfaces - databases, caches, queues, and internal APIs on private networks - administrative access through restricted source ranges, VPN, bastion, or controlled console paths - backups stored outside the production VM A public IP is not automatically a security failure, but unnecessary public services create avoidable review questions and attack paths. Use [Private Cloud Networks](/products/private-cloud-networks) and [Firewall Best Practices](/learn/guides/firewall-best-practices-cloud-servers) to define the boundary. ## Define backup, recovery, and retention A buyer will eventually ask what happens after accidental deletion, failed deployment, account compromise, or infrastructure loss. Document: - which systems and datasets are backed up - backup frequency - retention periods - storage location and failure domain - who can delete backups - encryption and access controls - recovery point and recovery time objectives - restore steps and responsible owner - date and result of the last restore test Snapshots, VM backups, database-native backups, and object-storage copies solve different problems. Use layered controls rather than one undifferentiated “backup” answer. A successful backup job does not prove recoverability. Enterprise readiness requires restore evidence. ## Monitor infrastructure and customer impact Monitoring should detect both technical pressure and user-facing failure. Track at least: - external service availability - application error rates - latency and failed requests - CPU, memory, disk, and network pressure - database health - queue or worker backlog - certificate expiry - backup age and failure - security-relevant authentication events Define alert ownership, escalation paths, and response expectations. A dashboard without alerts or an on-call owner is documentation, not detection. Use [Cloud Server Monitoring Basics](/learn/guides/cloud-server-monitoring-basics) for the baseline. ## Create a controlled deployment and rollback path Enterprise buyers do not expect zero change. They expect change to be controlled. A credible process includes: - source control and reviewed changes - automated or documented tests - staging validation - restricted production deployment permissions - deployment logs - rollback or forward-fix plan - pre-change backup or snapshot for high-risk work - post-deployment health checks Keep the process proportional. A small team can use a lightweight approval and deployment workflow without building a full internal platform. ## Prepare for incidents before the contract requires it You do not need a large incident-response department, but you need a repeatable sequence. Document: 1. how incidents are detected 2. who becomes incident owner 3. how access is restricted or credentials are rotated 4. how affected systems are isolated 5. how evidence and logs are preserved 6. how service is restored 7. when customers are informed 8. how lessons and corrective actions are recorded Separate technical recovery from customer communication. Both need ownership. NIST CSF 2.0’s Detect, Respond, and Recover functions provide a useful structure without forcing a startup into excessive process. ## Document your architecture and control boundaries Enterprise review becomes easier when the team can explain the system consistently. Prepare: - a current architecture diagram - production data flow - public and private network boundaries - identity and access model - deployment path - backup and restore design - monitoring and alerting coverage - key third-party providers - shared-responsibility boundaries - owner for each critical system Avoid claiming controls you cannot demonstrate. A smaller verified control set is stronger than a polished but inaccurate questionnaire response. ## Evidence enterprise buyers may request Depending on the buyer and data sensitivity, prepare to provide or discuss: - security policy summary - access-control process - incident-response plan - backup and restore evidence - vulnerability and patching process - data-retention and deletion process - subprocessor list - encryption practices - business continuity approach - recent penetration test or vulnerability assessment, where required - compliance roadmap or certifications, if applicable Do not promise a certification, SLA, recovery target, or control unless it is currently supported and approved for customer-facing use. ## Prioritize by customer risk Not every enterprise customer requires the same readiness level. Prioritize based on: - sensitivity of stored data - regulatory obligations - integration depth - number of users - business criticality - contractual recovery or availability requirements - access to the customer’s network or systems - geographic and data-residency requirements A low-risk internal pilot and a production system processing regulated data should not receive the same control plan. ## Decision framework: are you ready for enterprise onboarding? You are ready to begin serious enterprise onboarding when you can answer yes to these questions: 1. Can every production administrator be identified? 2. Is MFA enabled on critical systems? 3. Are production, staging, and development credentials separated? 4. Are secrets stored outside source code? 5. Are databases and internal services kept off unnecessary public interfaces? 6. Can you explain what is backed up and show a successful restore test? 7. Will your team detect service and backup failures before the customer reports them? 8. Is there a documented deployment and rollback path? 9. Does an incident have a named owner and communication process? 10. Can you provide a current architecture diagram and control summary? 11. Are customer-facing claims consistent with implemented controls? 12. Is there a clear roadmap for gaps discovered during review? A “no” does not always block the deal. It identifies work that should be completed, scoped, or disclosed before commitments are made. :::cluster ## How this applies on Raff A [Raff Linux VM](/products/linux-vm) can support a simple production baseline without forcing premature platform complexity. Separate staging and production when release risk and customer expectations justify it, and size each environment from measured workload needs. Use [Private Cloud Networks](/products/private-cloud-networks) to keep application, database, worker, and internal services off unnecessary public paths. Use [Data Protection](/products/data-protection) for infrastructure-level backup and snapshot controls, while maintaining application-aware and database-aware recovery where required. Evaluate [Managed Databases](/products/managed-databases) when database patching, monitoring, backup operations, and failover ownership are becoming larger than the team should manage directly. Enterprise readiness is still shared responsibility. Raff provides infrastructure capabilities; your team owns application security, identity, data handling, operational processes, evidence, and contractual commitments unless a service explicitly states otherwise. ## Conclusion Enterprise readiness is not an architecture-size test. It is an evidence test. A startup is in a credible position when access is controlled, environments are separated, secrets are managed, internal systems are private, backups are restorable, monitoring is actionable, changes are reversible, and incidents have owners. Build the smallest control set you can prove, then expand it according to customer risk and contractual requirements. :::cta Deploy Your Server Build a clear production baseline with controlled compute, private networking, and recovery layers before enterprise onboarding begins. ::: ## Sources - [NIST Cybersecurity Framework 2.0](https://www.nist.gov/cyberframework) - [NIST CSF 2.0 Core](https://www.nist.gov/cyberframework/getting-started/online-learning/online-learning-materials/csf-20-core) - [NIST CSF 2.0 Small Business Quick-Start Guide](https://www.nist.gov/publications/nist-cybersecurity-framework-20-small-business-quick-start-guide) - Date verified: 2026-07-29 --- ### Cloud Server Pricing: What Actually Drives Monthly Cost URL: https://rafftechnologies.com/learn/guides/cloud-server-cost-2026 Description: Understand cloud server pricing beyond the VM plan, including compute, storage, backups, bandwidth, licensing, supporting services, and operating cost. Cloud server pricing is the total recurring cost of running a workload—not only the advertised VM plan. **The real monthly cost includes compute, storage growth, backups, bandwidth policy, operating-system licensing, supporting services, and the operational effort required to keep the environment reliable.** A low starting price can be appropriate for a small website or test server. It becomes misleading when the production workload also needs a database, staging environment, retained backups, additional storage, monitoring, or Windows licensing. The right question is not “What is the cheapest cloud server?” It is: > What is the smallest safe infrastructure setup for this workload, and what will the complete monthly bill include? ## Cloud server pricing at a glance | Cost layer | What you are paying for | When it matters | |---|---|---| | Compute | vCPU and RAM assigned to the VM | Every workload | | Base storage | Operating system, application, database, and local files | Every workload | | Network | Included transfer, egress, public IPs, and private networking | Public or multi-server workloads | | Data protection | Snapshots, scheduled backups, retention, and recovery storage | Any important production data | | Operating system | Linux distribution or Windows licensing path | Windows and licensed software workloads | | Supporting services | Load balancers, databases, object storage, and volumes | Growing or separated architectures | | Operations | Patching, monitoring, incident response, migration, and support | Production environments | | Idle capacity | Unused development, staging, preview, and oversized resources | Teams with multiple environments | A provider’s plan table usually shows only the first line. Budgeting should cover the whole stack. ## The base VM price The base VM price is determined mainly by: - vCPU count - memory allocation - included local storage - compute profile - contract term - operating-system choice - region or infrastructure tier Raff’s live pricing page currently lists monthly Linux Cloud Server plans beginning with a 2 vCPU, 2 GB RAM, and 40 GB NVMe configuration. Plans include unmetered bandwidth, private networking, DDoS protection, monitoring, API access, and an included backup-and-snapshot storage pool. Always use the live [Raff pricing page](/pricing) for the current plan table because prices and packaging can change. The lowest plan is not automatically the cheapest operational decision. A VM that is too small can create slow response times, failed builds, memory pressure, database instability, and avoidable support work. The correct starting plan is the smallest one that supports normal usage with reasonable headroom. ## CPU and RAM drive most sizing decisions CPU and memory usually determine the VM tier before storage does. More vCPUs increase capacity for concurrent requests, API processing, CI/CD builds, background workers, report generation, and database queries. RAM supports application processes, database working sets, operating-system cache, containers, queues, caches, and concurrent Windows sessions. Memory pressure is often more damaging than moderate CPU pressure. When a VM begins swapping or killing processes, the operational cost can exceed the price difference between plans. Use the [VM sizing guide](/learn/guides/choosing-right-vm-size) before comparing monthly totals. ## Storage cost grows after deployment The disk size visible in the plan table is only the initial storage layer. Production storage often expands through: - database growth - uploaded files - logs - container images - build artifacts - package caches - temporary processing files - local backup staging - monitoring data Ask: 1. How much data exists today? 2. How quickly is it growing? 3. Which data must remain on fast block storage? 4. Which files can move to object storage? 5. How much free disk space is required for updates and recovery operations? A server can have enough CPU and RAM but still fail because its disk fills. Storage monitoring and log rotation are cost controls as well as reliability controls. ## Local disk, volumes, and object storage solve different needs | Storage type | Best for | Cost consideration | |---|---|---| | VM local disk | Operating system, application, temporary data | Usually bundled with the VM plan | | Block storage volume | Databases and persistent files that need expandable disk-like access | Added monthly storage cost | | Object storage | Backups, exports, media, archives, and application objects | Capacity and request model differ from disks | | Snapshots | Short-term rollback points | Retention increases storage use | | Backups | Historical recovery and disaster recovery | Schedule, retention, and protected size affect cost | Do not choose storage only by price per gigabyte. Access pattern, durability, recovery time, and application compatibility matter. ## Bandwidth can be included or metered Cloud providers commonly price network traffic in one of three ways: - unmetered bandwidth under an acceptable-use policy - a fixed monthly transfer allowance with overage charges - per-gigabyte egress billing This difference matters for public APIs, file downloads, media delivery, backup transfer, database replication, and multi-server applications. A VM with a low base price can produce a higher bill when outbound traffic is charged separately. Raff’s current Cloud Server plans list unmetered bandwidth and a 3 Gbps public network port. Private networking is included for communication between supported Raff resources. ## Backups are part of production cost A production VM without a recovery plan is cheaper only until recovery is needed. Budget for: - pre-change snapshots - automated backup schedules - retained recovery history - database-aware backups - independent copies where required - restore testing Snapshots support quick rollback. Scheduled backups support retained historical recovery. Important databases may also require logical backups, physical backups, or point-in-time recovery. Raff provides a backup-and-snapshot storage pool with Cloud Server plans and additional data-protection capacity beyond the included amount. Use the live [Data Protection page](/products/data-protection) and [pricing page](/pricing) when calculating the monthly total. The budget should follow the Recovery Point Objective and Recovery Time Objective. Read [RPO vs RTO for Cloud Backups](/learn/guides/cloud-server-backup-rpo-rto-snapshots) before selecting retention. ## Windows pricing requires a licensing decision Windows VM cost can include more than compute and storage. The final amount may depend on: - selected VM resources - Windows Server version - evaluation, provider licensing, or eligible BYOL path - Remote Desktop Services requirements - SQL Server or other Microsoft software - number of users - backup and storage needs A Windows VM page may show an infrastructure starting price while production licensing is billed or arranged separately. Confirm the full production licensing path before comparing providers. Linux is usually the simpler cost model for websites, APIs, containers, and open-source databases. Windows is justified when the workload depends on RDP, IIS, .NET Framework, Windows-only applications, Active Directory, or another Microsoft-specific requirement. Use the current [Windows VM product page](/products/windows-vm) and applicable Microsoft licensing guidance for the real total. ## Supporting services change the architecture cost A single VM may be enough at launch. As the workload grows, the bill can expand through architecture decisions. | Requirement | Possible additional service | |---|---| | Separate application and database | Second VM or managed database | | Higher availability | Additional application VM and load balancer | | Private service communication | Private networking and firewall design | | Expandable persistent disk | Block storage volume | | User uploads or backup objects | Object storage | | Deployment isolation | Staging or preview environment | | Database operations | Managed database service | | Container orchestration | Kubernetes nodes and control services | These costs are justified when they reduce a specific reliability, security, or operating risk. The mistake is adding services without defining which problem each one solves. ## Managed services vs self-managed infrastructure A self-managed database on a VM may have a lower visible infrastructure price. A managed database may include backups, updates, monitoring, failover features, or simplified maintenance. | Area | Self-managed | Managed service | |---|---|---| | OS patching | Your team | Provider-managed service layer | | Database updates | Your team | Depends on service policy | | Backup design | Your team | Often integrated | | Monitoring | Your team | Often included or integrated | | Failover | Must be designed | May be included by tier | | Direct monthly price | Often lower | Often higher | | Engineering effort | Higher | Lower for covered operations | The cheaper invoice is not always the cheaper operating model. Include team time and incident ownership in the decision. ## Idle infrastructure creates silent cost Cloud waste often comes from resources that were useful when created but no longer have an owner. Typical examples include: - abandoned test VMs - oversized staging servers - preview environments left online - unused volumes - old snapshots - duplicate databases - temporary migration servers Every non-production resource should have an owner, a purpose, an expiry or review date, and a deletion or archive rule. ## Monthly, annual, and prepaid billing Billing structure affects cash flow as well as price. Raff’s pricing page currently describes monthly subscriptions, one-year subscriptions with a longer-term discount, two-year subscriptions with a larger discount, and prepaid balance usage for supported resources. Raff does **not** use an hourly-billing promise as the core Cloud Server offer. Compare providers by converting both offers to the same expected usage period and included features. Longer commitments are appropriate when the workload is stable, migration risk is low, and the discount is worth more than the lost flexibility. Monthly terms are safer for validation, migration, and changing workloads. ## How to calculate the real monthly cost ```text Monthly infrastructure cost = base compute + additional storage + backups and snapshots + operating-system and software licensing + supporting services + network charges + monitoring or support charges + idle resources ``` Then add the operating cost: ```text Total operating cost = monthly infrastructure cost + engineering time + maintenance + incident response + migration and recovery work ``` Not every team needs to assign an exact dollar value to engineering time. It should still be included in the comparison. ## Decision framework Use this order when evaluating cloud server pricing: 1. **Define the workload.** Document the application, users, data, and performance expectations. 2. **Choose the smallest safe VM.** Include normal headroom, not speculative multi-year growth. 3. **Add persistent data costs.** Include disk growth, volumes, objects, logs, and uploads. 4. **Add recovery.** Define RPO, RTO, backups, snapshots, and restore testing. 5. **Confirm network pricing.** Understand allowances, egress, public IPs, and private networking. 6. **Confirm licensing.** Separate infrastructure pricing from Windows and application licenses. 7. **Add required services.** Include databases, load balancers, and additional environments only when justified. 8. **Choose the billing term.** Balance flexibility against commitment discounts. 9. **Assign ownership.** Review cost and utilization regularly. 10. **Use the live price.** Verify final plan and add-on pricing before purchase. :::cluster ## How Raff fits the cost model Raff Cloud Servers use plan-based pricing with selectable monthly and longer subscription terms. Current plans include NVMe storage, unmetered bandwidth, private networking, DDoS protection, monitoring, API and Terraform access, and an included backup-and-snapshot storage pool. This structure reduces several common variable costs, but teams should still budget for larger VM resources, additional storage, retained protection beyond the included pool, Windows and application licensing, extra environments, managed databases, and other platform services. Start with the workload and verify the final amount on the live [pricing page](/pricing). Do not copy an old starting price into an internal budget or customer proposal. ## Conclusion Cloud server pricing is a workload decision, not a single number. The base VM establishes CPU, RAM, and local storage. The real monthly cost adds data growth, recovery, licensing, supporting services, network policy, idle infrastructure, and operational ownership. Choose the smallest safe starting architecture, verify current prices before deployment, monitor actual usage, and resize or separate services only when evidence supports the change. :::cta View Raff Pricing Compare current Cloud Server plans and calculate the complete cost of your workload. ::: ## Sources - [Raff Pricing](/pricing) - [Raff Cloud Servers](/products/raff-vm) - [Raff Data Protection](/products/data-protection) - [Raff Windows VM](/products/windows-vm) - [Raff FAQ](/faq) - Date verified: 2026-07-29 --- ### Cloud Migration Checklist: Inventory, Cutover, Rollback, and Validation URL: https://rafftechnologies.com/learn/guides/cloud-migration-checklist-small-teams Description: Use this cloud migration checklist to inventory dependencies, select a migration strategy, rehearse cutover, define rollback, validate data, and retire the source safely. A cloud migration checklist reduces the chance that a workload moves successfully at the infrastructure level but fails at the business level. **The safest migration starts with a complete dependency inventory, a tested target environment, explicit cutover and rollback criteria, and post-migration validation before the source system is retired.** For a small team, the goal is not to move everything at once. It is to move one well-understood workload without losing data, access, integrations, or the ability to recover. ## Migration begins with scope, not server provisioning “Move the application to the cloud” is not a complete scope. Define exactly what is moving: - application runtime - database - files and uploads - scheduled jobs - DNS records - certificates - user accounts - secrets and API keys - monitoring - backups - integrations - licensing dependencies The migration boundary should be clear enough that the team can say what remains on the source system and what must work on the target system. ## Choose the migration strategy Common migration strategies include: | Strategy | What changes | Best fit | Main risk | |---|---|---|---| | Rehost | Move the workload mostly as-is | Stable applications needing a faster move | Carries old design problems forward | | Replatform | Change selected infrastructure components | Workloads that benefit from a new database, proxy, storage, or runtime model | More testing and operational change | | Refactor | Redesign application architecture | Workloads whose current design blocks scale or reliability | Highest delivery risk and effort | | Replace | Move the business process to SaaS or another product | Commodity workflows that are expensive to operate internally | Migration and vendor-dependency trade-offs | | Retain | Keep the workload where it is | Hardware-linked, unsupported, or low-value systems | Continued responsibility for the old environment | | Retire | Decommission the workload | Duplicated or unused systems | Hidden users or dependencies may remain | Small teams usually reduce risk by separating migration from modernization. Rehost or lightly replatform first when the workload is stable, then improve the architecture after the move has been validated. ## Select a safe first workload A good first migration has: - a known owner - documented users - clear data boundaries - limited dependencies - a measurable success condition - a practical rollback path Good early candidates often include a website, staging environment, internal dashboard, automation service, isolated business application, or self-hosted tool. Workloads such as email, identity infrastructure, shared file systems, payment systems, and undocumented legacy software usually require deeper discovery before cutover. ## Build the dependency inventory A migration fails when an undocumented dependency remains connected to the old environment. Inventory these areas: | Area | Capture | |---|---| | Application | Version, runtime, packages, startup process, service accounts | | Database | Engine, version, size, extensions, users, connection strings | | Files | Paths, permissions, ownership, growth, sensitive data | | Network | Public IPs, private IPs, firewall rules, allowlists, outbound access | | DNS | Records, TTLs, certificates, redirects, mail-related records | | Automation | Cron, Task Scheduler, CI/CD, report jobs, cleanup jobs | | Integrations | APIs, webhooks, identity providers, CRM, email, payments | | Access | SSH keys, RDP users, VPN, admin accounts, emergency access | | Licensing | Windows, database, commercial software, activation requirements | | Recovery | Backup method, retention, restore procedure, current RTO and RPO | | Operations | Logs, metrics, alerts, dashboards, escalation contacts | The inventory does not need to be long. It must be complete enough to predict what will break when the source endpoint changes. ## Define success before the move A migration is successful when business workflows operate correctly—not when the target VM boots. Define acceptance tests such as: - users can sign in - expected records and files exist - read and write operations succeed - uploads and downloads work - scheduled jobs run - notifications and webhooks arrive - certificates and redirects are correct - backup jobs complete - monitoring and alerts are active - performance remains within an acceptable range Assign an owner to each test. The person who understands the business workflow should validate it, not only the person who built the target server. ## Establish RTO, RPO, and the migration window Recovery Time Objective defines how long the workload can remain unavailable. Recovery Point Objective defines how much recent data can be lost. These objectives affect the migration method: | Requirement | Migration implication | |---|---| | Downtime is acceptable | Offline copy and all-at-once cutover may be simplest | | Downtime must be short | Pre-sync data and perform a final delta sync | | No writes can be lost | Freeze writes or use a controlled replication method | | Rollback must be fast | Keep the source ready and make traffic routing reversible | | Data changes after cutover | Plan how new target data would be handled during rollback | Do not choose a maintenance window only from technical convenience. Confirm business users, application owners, and support contacts will be available. ## Protect the source before migration Before changing production: - take a current backup - verify the backup completed - restore it into a separate environment - document the restore duration - record current configuration - preserve access to DNS, certificates, credentials, and licensing information A snapshot can provide a useful rollback point, but application-consistent recovery may also require database-aware backups, file copies, and exported configuration. ## Build and validate the target environment Create the target before the cutover window whenever possible. Validate: - operating-system and runtime compatibility - CPU, memory, storage, and network sizing - firewall and private-network rules - administrator access - application configuration - database connectivity - certificate handling - logging and monitoring - backup policy - time synchronization - outbound dependencies Test with production-like data where policy permits. Remove or protect sensitive information in non-production environments. ## Rehearse the migration A rehearsal reveals missing tasks and unrealistic timing. The rehearsal should record: - task order - expected duration - owner - prerequisite - validation method - rollback action A cutover runbook can be a simple shared table. The value comes from explicit sequence and ownership, not from document length. Rehearse the most failure-prone activities: - final data synchronization - application startup - database connection changes - DNS or load-balancer changes - SSH or RDP access - core business tests - rollback routing ## Decide between all-at-once and phased cutover ### All-at-once cutover Traffic and users move to the target in one event. It fits workloads where the application and data layers must move together or where running both environments is impractical. The main risks are concentrated downtime and a narrower decision window. ### Phased cutover Traffic, users, locations, or components move gradually. It can reduce exposure by validating the target under partial load. It also adds complexity when data must remain consistent across both environments. Use phased cutover only when the application, routing, and data model support it safely. ## Define the cutover sequence A practical cutover sequence is: ```text Confirm readiness ↓ Freeze writes or ingestion where required ↓ Take final backup ↓ Complete final data synchronization ↓ Start and validate target services ↓ Change DNS, load balancer, or user access path ↓ Run acceptance tests ↓ Monitor and approve ``` The exact order depends on the workload. A database-backed application may need the app and database cut over together. A static site may require only final file synchronization and DNS change. ## DNS planning DNS is often part of cutover, but it should not be the only rollback mechanism considered. Before migration: - confirm who controls the domain - inventory all relevant records - understand current TTLs - prepare target records - confirm certificates cover the required hostnames - test the target through a temporary hostname or local host override where practical Lowering TTL can shorten how long resolvers cache an old record, but it does not create instant global change. Plan for mixed traffic during propagation. ## Define rollback before cutover Rollback criteria must be specific. Examples: - users cannot authenticate - data writes fail - critical integration is unavailable - error rate exceeds the agreed threshold - latency is unacceptable for core workflows - data validation fails - recovery exceeds the approved migration window Assign one person to decide whether to fix forward or roll back. The rollback plan must also address data created after cutover. Redirecting traffic to an old database can lose new transactions if the source became stale. Possible strategies include: - keeping the target read-only until acceptance - freezing writes during validation - synchronizing target changes back before rollback - accepting and documenting a defined data-loss window The correct method depends on the workload’s RPO and data model. ## Validate immediately after cutover Run functional and operational tests. ### Functional validation - login and authorization - create, read, update, and delete workflows - file upload and download - search and reporting - notifications and integrations - payment or customer-critical actions ### Operational validation - CPU, memory, disk, and network behavior - logs and error tracking - backup execution - monitoring and alerts - certificate validity - scheduled jobs - security exposure - expected billing resources Compare target performance with a pre-migration baseline where possible. ## Keep a warranty period Do not immediately delete the source environment. Keep it available for a defined warranty period while: - normal business cycles complete - scheduled jobs run - backups execute - users report issues - logs and performance stabilize During this period, make it clear which environment is authoritative. An old environment that remains writable can create data divergence. ## Decommission deliberately Retire the source only after approval. Confirm: - the target passed acceptance testing - business owners approved the move - new backups were restored successfully - monitoring is active - data retention requirements are satisfied - DNS and firewall records are clean - old credentials and access paths are removed - source data is securely retained or deleted according to policy - licenses and subscriptions are closed where appropriate Decommissioning is part of the migration, not an unrelated cleanup task. ## Windows workload considerations Windows migrations may require additional review for: - Windows Server licensing path - Remote Desktop access and user count - RDS requirements - SQL Server licensing - application vendor support - domain or identity dependencies - mapped drives and file permissions - services and Task Scheduler jobs - hardware-bound activation Confirm technical compatibility and licensing before the cutover window. A Windows application that launches successfully may still have unsupported licensing or multi-user requirements. ## How this applies on Raff Raff Cloud Servers can host Linux and Windows migration targets. A practical Raff migration may combine: - [Cloud Servers](/products/raff-vm) for compute - [Private Cloud Networks](/products/private-cloud-networks) for internal application and database traffic - [Volumes](/products/volumes) for compatible persistent block storage - [Object Storage](/products/object-storage) for files, archives, and backup objects - [Data Protection](/products/data-protection) for snapshots and scheduled backups Choose the target size from the workload’s measured behavior and migration headroom. Verify current plans and product capabilities on the live product pages rather than relying on historical prices. ## Cloud migration checklist ### Discovery - Migration owner assigned - Workload boundary defined - Dependencies inventoried - Users and integrations identified - Licensing reviewed - RTO and RPO agreed ### Target readiness - Target architecture selected - Access and firewall rules configured - Data migration method tested - Monitoring and backups configured - Acceptance tests documented - Restore verified ### Cutover readiness - Runbook rehearsed - Migration window approved - Final backup prepared - Data freeze rules defined - DNS or routing change prepared - Rollback criteria and decision owner confirmed ### Post-cutover - Business workflows validated - Data reconciled - Performance reviewed - Backups and alerts verified - Warranty period started - Source made read-only or controlled - Decommission approval scheduled :::cluster ## Conclusion A safe cloud migration is a controlled business change, not only a server transfer. Inventory the full workload, choose the right migration strategy, test recovery, rehearse the cutover, define rollback criteria, validate real user workflows, and preserve the source until the target has completed a successful warranty period. Move one well-understood workload first. Repeat the process only after the team has proven it can operate and recover the new environment. :::cta Deploy Your Server Prepare a Linux or Windows cloud target for your next workload migration. ::: ## Sources - [AWS Prescriptive Guidance: Pre-cutover stage](https://docs.aws.amazon.com/prescriptive-guidance/latest/best-practices-migration-cutover/pre-cutover-stage.html) - [AWS Prescriptive Guidance: Cutover stage](https://docs.aws.amazon.com/prescriptive-guidance/latest/best-practices-migration-cutover/cutover-stage.html) - [AWS Prescriptive Guidance: Application migration process](https://docs.aws.amazon.com/prescriptive-guidance/latest/cutover-runbook/app-migration.html) - [Raff Cloud Servers](/products/raff-vm) - [Raff Data Protection](/products/data-protection) --- ### Bastion Host vs VPN vs Public SSH: Choosing the Right Access Model URL: https://rafftechnologies.com/learn/guides/bastion-host-vs-vpn-vs-public-ssh Description: Compare public SSH, bastion hosts, and VPN access models for cloud servers, private networks, databases, Windows RDP, and small-team infrastructure. Bastion host vs VPN vs public SSH is a decision about how administrators and trusted users reach cloud servers, private networks, databases, and internal tools. The right model depends on what is being protected, who needs access, how many resources must be reached, and what the team can operate consistently. A simple development VM and a production environment with databases, Windows systems, and multiple administrators need different access boundaries. The goal is not to remove all access. The goal is to create deliberate access: named users, limited permissions, private services, reviewable paths, and recoverable administration. ## Why access architecture matters Every administrative path is a security boundary. Common access targets include: - Linux SSH administration - Windows RDP access - private databases - internal dashboards - monitoring systems - backup systems - application management interfaces The access model should answer: | Question | Why it matters | |---|---| | Who needs access? | Prevents shared accounts and uncontrolled permissions | | What resources do they need? | Limits unnecessary reach | | Is access temporary or permanent? | Determines review requirements | | How is identity verified? | Prevents anonymous access | | How is access removed? | Supports offboarding and security hygiene | The best access model is the one the team can maintain, monitor, and review. ## Public SSH: simple but directly exposed Public SSH means the SSH service is reachable from the internet. Example: ```bash ssh user@server-ip ``` This is common for developers because it is fast and simple. A new Linux VM can be deployed, an SSH key added, and administration can begin immediately. Public SSH is not automatically insecure. The risk comes from unmanaged exposure. ### Public SSH baseline controls Use: - SSH keys instead of passwords - unique keys per administrator - disabled password login where practical - restricted firewall rules - regular patching - login monitoring - key removal during offboarding - no public database exposure ### When public SSH becomes a poor fit Review the model when: - multiple administrators need access - contractors or external users are involved - the workload stores sensitive data - the server supports revenue operations - the environment contains multiple private services - access history must be audited A simple access model can be secure, but temporary solutions often become permanent without review. ## Bastion host: controlled SSH entry A bastion host is a dedicated access gateway used to reach private servers. Instead of exposing SSH on every server: ```text Admin device → Bastion host → Private servers ``` The bastion becomes the controlled entry point. ### When a bastion fits Use a bastion when: - multiple Linux servers need administration - production servers should not expose SSH publicly - database administration requires controlled access - several administrators need a common access path - consultant or MSP access must be tracked Benefits include: | Benefit | Value | |---|---| | Reduced exposure | Private servers stay private | | Central access | One entry point is easier to manage | | Better visibility | Access can be logged centrally | | Consistent policy | SSH controls are standardized | | Easier reviews | User access is easier to audit | ### Bastion responsibilities A bastion is a security boundary and should remain simple. Maintain: - hardened OS - minimal installed services - patching - individual user accounts - SSH key management - access logs - firewall restrictions - emergency recovery access Do not turn the bastion into an application server, database host, or general-purpose utility machine. ## VPN: private network access A VPN creates a private path between approved users and internal resources. Example: ```text Admin device → VPN → Private network → Servers and services ``` VPNs are useful when users need access to multiple private systems rather than only one SSH endpoint. ### When a VPN fits Use a VPN for: - multiple private servers - private databases - internal dashboards - Windows RDP workloads - distributed teams - office-server replacement scenarios - internal tools A VPN is often the better choice when Linux, Windows, databases, and applications all need private connectivity. ### VPN responsibilities A VPN should not become a flat trusted network. Maintain: - named users - strong authentication - limited routes - network segmentation - device controls where needed - access reviews - logs - offboarding procedures Being connected to a VPN should not automatically mean unlimited access. ## Bastion vs VPN vs Public SSH comparison | Factor | Public SSH | Bastion | VPN | |---|---|---|---| | Setup complexity | Lowest | Medium | Medium | | Main purpose | Direct server administration | Controlled SSH entry | Private network access | | Best fit | Simple workloads | Multiple private servers | Multiple internal resources | | Public exposure | SSH endpoint exposed | Bastion endpoint exposed | VPN endpoint exposed | | Linux SSH | Strong fit | Strong fit | Possible through private network | | Windows RDP | Not ideal | Limited | Strong fit | | Database access | Avoid public access | Controlled admin path | Private access | | Team scaling | Weak without process | Strong | Strong | | Auditability | Depends on server logs | Centralized | Depends on identity/logging | Simple rule: - Public SSH optimizes speed. - Bastion optimizes controlled SSH access. - VPN optimizes private resource access. ## Choose by team and workload ### Solo developer A single developer managing a test VM may use public SSH with strong keys and basic firewall rules. ### Small production team A team with multiple administrators should move toward: - unique identities - access reviews - restricted ports - bastion or VPN where appropriate ### Distributed team Remote teams often benefit from private access models because users connect from different locations and devices. ### MSP or consultant access External access requires: - named users - expiration policies - audit logs - scoped permissions - clear ownership ### Production databases Databases should normally remain private. Use a private path through VPN, bastion, or internal networking rather than exposing database ports publicly. ## Modern private access models Access is no longer limited to traditional VPNs and bastions. Identity-based private access tools and mesh VPN solutions can simplify access for distributed teams. These models can help when: - users work from multiple locations - contractors need controlled access - RDP should not be public - internal tools need identity-based access - the team wants simpler private networking The principles remain the same: - identify users - restrict resources - review permissions - remove access when no longer needed - monitor important activity The tool changes. The security model does not. ## Practical architecture patterns ### Simple Linux VM ```text Admin device → Restricted SSH → Linux VM ``` Good for low-risk workloads. Controls: - SSH keys - firewall rules - patching - backups - monitoring ### Production Linux environment ```text Admin device → Bastion → Private application/database servers ``` Good when multiple servers exist. Controls: - hardened bastion - private servers - logging - individual accounts ### Mixed Linux and Windows environment ```text User device → VPN/private access → Linux, Windows, databases ``` Good for business environments. Controls: - identity-based access - network segmentation - private services - RDP restrictions ## How this applies on Raff Raff Cloud Servers support practical access design for Linux and Windows workloads. Common patterns: | Workload | Access approach | |---|---| | Development Linux VM | SSH keys and restricted firewall | | Production Linux servers | Private networking and controlled admin path | | Multiple private servers | Bastion or VPN access | | Windows RDP workload | Private access or restricted RDP | | Private database | Internal network only | Raff provides Linux and Windows Cloud Servers, firewall controls, private networking options, snapshots, backups, and full administrator control. Start simple, reduce public exposure, keep private services private, and introduce bastion, VPN, or identity-based access when the workload requires stronger boundaries. ## Access model checklist Before choosing an access model, confirm: ### Identity - Every administrator has a named account - Shared credentials are avoided - Offboarding removes access - Access ownership is clear ### Exposure - Public ports are documented - Databases are private - RDP is restricted - SSH exposure is intentional ### Operations - Keys and credentials are reviewed - Logs are available - Emergency access is documented - The team can operate the chosen model ### Architecture - Public traffic is separated from admin traffic - Private services use private paths - Permissions follow least privilege - Access is reviewed as the team changes :::cluster ## Conclusion Public SSH, bastion hosts, and VPNs solve different access problems. Public SSH is fast and simple but requires careful hardening. Bastion hosts provide controlled SSH access to private servers. VPNs provide private connectivity to multiple internal resources. Choose the simplest model that provides the required security boundary. As workloads become more important, move from direct access toward controlled private access, identity management, and regular reviews. :::cta Explore Private Cloud Networks Build private communication paths between your cloud resources. ::: ## Sources - [NIST Zero Trust Architecture](https://csrc.nist.gov/pubs/sp/800/207/final) - [Raff Private Cloud Networks](/products/private-cloud-networks) - [Raff Cloud Servers](/products/raff-vm) --- ### Cloud Security Fundamentals for Developers and Small Teams URL: https://rafftechnologies.com/learn/guides/cloud-security-fundamentals Description: Learn the cloud security fundamentals small teams need across identity, network exposure, server hardening, secrets, recovery, monitoring, and incident response. Cloud security is the operating discipline used to protect cloud accounts, servers, applications, networks, and data from unauthorized access, avoidable exposure, loss, and disruption. **For developers and small teams, the strongest security baseline is not a large toolset. It is consistent control over identity, public exposure, patching, secrets, recovery, monitoring, and incident ownership.** Cloud platforms secure the infrastructure they operate. Your team still controls who can change resources, which services are exposed, how the guest operating system is maintained, where credentials live, and whether the workload can be recovered. ## The cloud security decision framework Use five questions for every workload: 1. **What must be public?** 2. **Who can administer it?** 3. **What can the workload reach after compromise?** 4. **Which data must survive deletion, corruption, or ransomware?** 5. **Who responds when a security signal appears?** These questions turn security from a generic checklist into an architecture decision. | Security area | Minimum practical control | Common failure | |---|---|---| | Identity | MFA and individual privileged accounts | Shared credentials or one unprotected owner account | | Administration | Restricted SSH, RDP, console, and API access | Management paths broadly exposed | | Network | Public edge separated from private services | Database, cache, or dashboard exposed publicly | | Server | Supported software and recurring patching | Forgotten packages and default services | | Application | Controlled secrets and dependency updates | Credentials stored in code or reusable images | | Data | Backups, recovery points, and restore tests | Backups that cannot rebuild the service | | Detection | Actionable logs and alerts with an owner | Large log volume that nobody reviews | | Response | Isolation, rotation, recovery, and communication plan | Decisions invented during the incident | A practical priority order is: 1. Protect identities that can change infrastructure. 2. Reduce unnecessary public exposure. 3. Limit privileges and lateral movement. 4. Patch internet-reachable software. 5. Protect secrets and recovery data. 6. Monitor signals that trigger action. 7. Rehearse isolation and restoration. ## Shared responsibility: what the provider secures and what you secure The provider normally operates the physical data center, virtualization layer, and platform services. The customer remains responsible for workload configuration. Your team typically owns: - cloud account security - API keys and access tokens - guest operating-system updates - SSH and RDP configuration - application security - firewall and security-group rules - database exposure - secrets and encryption keys - backups and restore testing - user onboarding and offboarding A secure platform does not make an exposed database or shared administrator password safe. Provider controls and customer configuration must work together. ## Start with a lightweight threat model A small-team threat model can fit in one table. Record: - workload purpose - business owner - public endpoints - administrative paths - sensitive data - internal dependencies - privileged credentials - acceptable downtime and data loss - recovery location Then ask: - What can an unauthenticated internet user reach? - What can a normal user do after login? - What can a compromised application process reach? - What can an administrator delete or change? - Can one compromised credential affect production, DNS, source code, and backups? - How would the service be rebuilt if the VM were unavailable? Threat modeling is valuable because the highest-risk path is often not the most visible one. A public website may be expected; an exposed database port, CI token, or backup credential is not. ## Identity is the first control plane Cloud accounts, domain registrars, DNS providers, source repositories, CI/CD systems, password managers, backup consoles, and email recovery accounts can all affect production. ### Require MFA for privileged access Start with: - cloud platform administrators - email accounts used for recovery - DNS and domain accounts - source control - CI/CD - backup and monitoring administration Use phishing-resistant MFA when practical. Any supported MFA is preferable to relying on a password alone, but stronger methods reduce phishing and session-theft risk more effectively. ### Use individual identities Each administrator should have a named identity and their own SSH key, Windows account, or platform user. Avoid: - shared root passwords - one SSH key copied to every laptop - generic administrator accounts used by multiple people - personal tokens embedded permanently in automation Individual identities improve offboarding, investigation, and least-privilege enforcement. ### Separate human and machine access A CI/CD job, monitoring agent, application, and human administrator should not all use the same credentials. Machine identities should receive only the permissions required for their task. A deployment job that restarts one service should not automatically receive unrestricted billing, networking, backup deletion, and account administration rights. ## Public and private access are different security boundaries A service can be publicly reachable without its administration path being public. A practical model is: ```text Internet users ↓ HTTPS entry point ↓ Application tier ↓ private network Database, cache, queue, monitoring, and internal tools ``` Public exposure should normally be limited to the edge users require. | Component | Typical exposure | |---|---| | Website or public API | Public HTTPS | | SSH or RDP | Restricted or private admin path | | Application runtime port | Localhost or private network | | Database | Private application and admin access | | Cache or queue | Private approved-service access | | Monitoring dashboard | Private or strongly authenticated | | Backup system | Private and tightly restricted | Private networking reduces reachability, but it is not automatic authorization. Apply firewall or security-group rules inside private networks as well. A compromised application server should not gain unrestricted access to every internal resource merely because all systems share one VPC. NIST’s zero-trust guidance emphasizes that network location alone should not create implicit trust. Identity, resource sensitivity, and explicit authorization still matter. ## Firewall strategy: allow required paths, deny the rest A cloud firewall or security group should describe intended communication. For a small web application, that may mean: - public HTTPS to the edge - administrative access from approved sources - application-to-database traffic over private IPs - monitoring traffic from known systems - no public database, cache, or management ports Review both inbound and outbound behavior. Broad outbound access can allow compromised workloads to download tools, contact command infrastructure, or exfiltrate data. Do not keep temporary migration or troubleshooting rules indefinitely. Every public rule should have a reason, owner, and review date. ## Server hardening should reduce maintenance surface A secure server is not the one with the most packages. It is the one with the smallest supported service inventory required for the workload. ### Patch by exposure and impact Prioritize: 1. authentication and remote-access vulnerabilities 2. internet-facing operating-system and application flaws 3. privilege-escalation issues 4. public frameworks and runtimes 5. internal components reachable from exposed workloads Use a recurring maintenance window. Create a recovery point before high-impact changes and test important updates outside production where practical. ### Remove unnecessary software and services Disable or remove: - demonstration applications - unused web panels - development servers - old runtimes - default accounts - temporary migration tools - packages installed for one-time troubleshooting Review listening ports after deployment and major changes. ### Avoid unnecessary root or administrator execution Run applications under dedicated service accounts with limited file and process permissions. A compromised web process should not automatically control the operating system, all application data, and backup credentials. ## Separate environments and failure boundaries Development, staging, and production should not share unrestricted trust. Separate where practical: - credentials - VPCs or network segments - databases - object storage buckets - CI/CD permissions - monitoring and backup deletion rights A staging compromise should not expose production secrets. A developer token should not automatically manage every production environment. Environment separation also limits accidental changes. Security protects against mistakes as well as malicious activity. ## Secrets and software supply-chain controls Secrets include API keys, database passwords, private keys, signing keys, deployment tokens, and backup credentials. Do not store long-lived secrets in: - Git repositories - container images - reusable VM templates - public cloud-init scripts - shared chat messages - broadly accessible documentation Use protected CI/CD variables, a suitable secret-management system, or controlled runtime injection. Rotate secrets when they are exposed, shared improperly, or owned by someone who has left the team. For dependencies: - keep lockfiles - pin production image versions deliberately - track base images and runtimes - review automated update proposals - rebuild images when security fixes are required - remove abandoned packages An application built from outdated dependencies can remain vulnerable even when the VM is fully patched. ## Recovery is part of security Backups and restore procedures reduce the impact of accidental deletion, ransomware, data corruption, failed updates, and compromised administrator accounts. Define: - Recovery Point Objective (RPO) - Recovery Time Objective (RTO) - backup frequency - retention - recovery-point deletion permissions - off-server or isolated copies - restore test schedule Snapshots are useful rollback points before risky changes. Scheduled backups provide recovery history. Databases may also need database-aware backups or point-in-time recovery. A successful backup job is not proof of recovery. Test restoration into an isolated environment and confirm the application can start, authenticate users, access data, and complete critical workflows. ## Protect the recovery path from production compromise A recovery system that uses the same credentials and administrative boundary as production may fail during the same incident. Reduce this risk by separating: - backup credentials - backup deletion rights - retention policies - recovery documentation - emergency administrator access The exact design depends on workload importance, but the principle is durable: production compromise should not automatically erase every recovery option. ## Monitoring should lead to an action Small teams should prioritize high-value signals. Monitor: - privileged logins - failed authentication - new users, keys, and tokens - firewall and security-group changes - unusual outbound traffic - application availability and error rate - disk and storage growth - backup failures - certificate expiration - important dependency vulnerabilities Every alert should have: - an owner - a severity - an expected first action - an escalation path Collecting logs without review does not create detection. Fewer high-quality alerts are often more useful than an unowned stream of events. ## Prepare a short incident runbook A practical runbook should answer: 1. Who leads the response? 2. How is an affected VM isolated? 3. Which accounts and tokens must be rotated? 4. How are DNS and public traffic controlled? 5. Where are recent recovery points? 6. How is a replacement environment created? 7. What evidence should be preserved? 8. Who communicates with customers or partners? 9. When is outside support required? Review the runbook with the people expected to use it. Recovery plans should not depend on one person being available. ## Security depth by workload | Workload | Minimum practical posture | |---|---| | Disposable test VM | Restricted admin access, no important data, deletion date | | Public website | HTTPS, patching, narrow firewall, recovery for content and configuration | | Internal tool | Strong authentication, private or restricted access, named owner | | Customer application | MFA for admins, monitoring, secrets management, tested recovery | | Production database | No broad public access, private path, database-aware backups | | Windows business workload | Restricted RDP, individual users, patching, data protection | | CI/CD runner | Scoped credentials, isolated jobs, short-lived secrets, logging | Apply a shared baseline to every production workload, then increase controls according to data sensitivity, exposure, and business impact. ## How this applies on Raff Raff provides infrastructure components that can support this model: - [Cloud Servers](/products/raff-vm) for Linux and Windows compute - [VPC](/products/vpc) and [Private Cloud Networks](/products/private-cloud-networks) for isolated internal traffic paths - cloud firewall and security-group controls for allowed communication - platform monitoring for server resource visibility - [Data Protection](/products/data-protection) for snapshots and scheduled backups A practical Raff baseline is: 1. Protect the Raff account and recovery email with MFA where supported. 2. Use individual SSH keys or Windows administrator identities. 3. Restrict administrative ports before production use. 4. Expose only the application edge that users require. 5. Keep databases and internal services on private paths. 6. Apply security-group rules inside the VPC. 7. Patch the operating system and application stack. 8. Configure recovery points according to RTO and RPO. 9. Test a restore in an isolated environment. 10. Monitor access, application health, storage, and backup status. 11. Record the workload owner and incident process. Product capabilities can evolve. Verify the current dashboard and live product pages before designing around a specific workflow. ## Cloud security maturity levels ### Level 1: protect the basics - MFA - individual administrators - SSH keys or restricted RDP - narrow firewall rules - recurring updates - backups ### Level 2: reduce blast radius - private networking - environment separation - scoped application identities - centralized secrets - monitored access changes - tested restore ### Level 3: improve resilience and auditability - structured access reviews - isolated backup administration - automated configuration - actionable alerting - incident exercises - documented recovery ownership Security maturity should grow with business impact. Do not add complexity without ownership, but do not leave production on the same controls used for a disposable test VM. :::cluster ## Conclusion Cloud security for developers and small teams is a repeatable operating model. Protect privileged identities, expose only what users need, separate public and private traffic, restrict lateral movement, patch reachable software, keep secrets out of code, preserve independent recovery paths, monitor actionable signals, and rehearse incident response. The best security baseline is not the most complicated one. It is the one applied consistently to every important workload and reviewed whenever architecture, users, or business risk changes. :::cta Explore Security Review Raff’s security and infrastructure controls for your production workloads. ::: ## Sources - [NIST SP 800-207: Zero Trust Architecture](https://csrc.nist.gov/pubs/sp/800/207/final) - [NIST SP 800-207A: Zero Trust Access Control for Cloud-Native Applications](https://csrc.nist.gov/pubs/sp/800/207/a/final) - [CISA: Require Multifactor Authentication](https://www.cisa.gov/audiences/small-and-medium-businesses/secure-your-business/require-multifactor-authentication) - [Raff VPC](/products/vpc) - [Raff Cloud Servers](/products/raff-vm) - [Raff Data Protection](/products/data-protection) --- ### Production VPS Checklist for SaaS Apps URL: https://rafftechnologies.com/learn/guides/production-vps-checklist-saas-app Description: Use this production VPS checklist to validate SaaS capacity, access, traffic paths, storage, backups, monitoring, restore testing, and scaling decisions before launch. A production VPS is ready for a SaaS launch only when the team can explain how traffic reaches the app, who can administer the server, where persistent data lives, how failures are detected, and how the service is restored. **The goal is not to eliminate every risk before launch. It is to make the remaining risks visible, owned, and recoverable.** Use this checklist to choose one of three outcomes: - **Launch:** the current design has enough headroom and a tested recovery path. - **Fix first:** the architecture can stay, but access, backups, monitoring, or capacity needs correction. - **Redesign:** one VM carries a failure mode that resizing alone will not solve. ## Production readiness is narrower than a product launch checklist This guide covers the VPS and surrounding infrastructure. It does not replace product work such as billing, onboarding, legal pages, analytics, customer support, or launch communications. A launch-ready server should have: - measured CPU, memory, disk, and network behavior - one intended public traffic path - restricted administrative access - protected secrets - controlled persistent storage - backups aligned with RPO and RTO - a tested restore and rollback procedure - infrastructure and application health checks - a named incident and recovery owner ## Use evidence instead of universal utilization thresholds There is no reliable rule that every SaaS VM becomes unsafe at one CPU, memory, or disk percentage. Resource behavior depends on the runtime, database, traffic pattern, background work, caching, and storage growth. Review each resource using measured behavior: | Resource | Launch signal | Fix or redesign signal | |---|---|---| | CPU | Spikes recover and request latency stays acceptable | Sustained saturation or queue growth under expected load | | Memory | Working set remains stable with no repeated OOM events | Swapping, OOM kills, or unbounded process growth | | Disk capacity | Growth rate and retention are known | Logs, uploads, temporary files, or database growth are unbounded | | Disk performance | Deploys, queries, and writes complete predictably | Storage latency blocks requests or background jobs | | Network | Expected transfer and dependencies are understood | User traffic, backups, or uploads compete unpredictably | | Database | Queries, migrations, and backups complete in the required window | Locks, slow queries, or recovery needs dominate the VM | Size from realistic tests and operating headroom, not the cheapest plan that starts the application. ## Make the traffic path easy to explain A small SaaS stack should have one intended public entry point. ```text DNS ↓ HTTPS reverse proxy or load balancer ↓ Application service ↓ Database, cache, queue, and storage ``` ![Simple SaaS production VPS architecture with DNS, HTTPS, app server, database, backups, and object storage](https://raff-images.s3.raffusercloud.com/saas_production_vps_architecture_diagram_a4beea651f.png) Before launch, confirm: - only required user-facing ports are public - application runtime ports cannot bypass the intended edge - databases, caches, queues, and metrics endpoints use private or restricted paths - old staging domains and test routes are removed - TLS, redirects, and DNS records are correct - health checks test a meaningful application response ## Review access and secrets Development shortcuts should not become permanent production access. Check: - every administrator has an individual identity - SSH keys and Windows accounts have named owners - shared or unknown credentials are removed - root or administrator privilege is limited to people who need it - former teammates and contractors are offboarded - SSH, RDP, and admin panels are restricted - secrets are not stored in source code, images, screenshots, or chat - deployment and automation tokens have limited scope - emergency access is documented and protected A public application does not require public administration. Use [Private vs Public Admin Access](/learn/guides/private-vs-public-admin-access) for the access-model decision. ## Decide where persistent data belongs The VM disk is usually appropriate for the operating system, application runtime, deployment files, and bounded working data. It becomes risky when independently valuable data can fill the server or must be recovered on a different schedule. | Data | Practical starting point | Move or separate when | |---|---|---| | Application code | VM disk and repeatable deployment | Deployments depend on manual server state | | Database | Same VM can fit an early workload | Performance, scaling, or recovery needs become independent | | User uploads | VM disk for small bounded use | Uploads grow, need independent delivery, or complicate backups | | Logs | Local short retention | Long retention, search, audit, or incident needs grow | | Exports and archives | Temporary local storage | Files must outlive the VM or be shared externally | ![Decision matrix showing ready, fix, and redesign states for a production VPS checklist](https://raff-images.s3.raffusercloud.com/production_vps_readiness_decision_matrix_16e2f1467b.webp) Object storage is often the better destination for uploads, media, exports, and backup objects because those files can scale independently from application compute. Block storage or a separate database layer may be appropriate when state requires a different performance or recovery boundary. ## Prove backup, restore, and rollback NIST defines RPO as the point in time to which data must be recovered after an outage and RTO as the acceptable recovery duration before business impact becomes unacceptable. Before launch, write both targets and verify that the current design can meet them. A minimum recovery test should prove: 1. A usable recovery point exists. 2. Required credentials and encryption keys are available. 3. Replacement compute and storage can be created. 4. Database and file data restore successfully. 5. The application starts with compatible configuration. 6. DNS, certificates, secrets, and private paths can be restored. 7. A critical user workflow succeeds. 8. Measured data loss and recovery time meet the targets. A snapshot before a deployment helps with short rollback. It should not be the only retained recovery control. Read [Cloud Snapshots vs Backups](/learn/guides/snapshots-vs-backups-cloud-server) for the distinction. ## Monitor the service users experience Server metrics are necessary but insufficient. A VM can be reachable while authentication, payments, background workers, webhooks, or database writes are failing. Monitor both layers: ### Infrastructure - CPU and memory pressure - disk capacity and storage latency - network behavior - process and service status - backup completion - certificate expiration ### Application - health endpoint - request latency and error rate - login or another core user journey - queue depth and failed jobs - database connection and query behavior - important webhook or integration failures CISA recommends logging user activity, administrator actions, network events, and system changes, then assigning alerts and response ownership. Keep the alert set small enough that someone will act on it. ## Choose single VM, larger VM, or split architecture ### Launch on one VPS A single VPS can be a sound starting point when: - the workload is early and understandable - the database and uploads are bounded - realistic tests show sufficient headroom - backups and restore have been tested - one-server downtime matches the business tolerance - the team benefits from operational simplicity ### Resize the VPS Resize when the architecture is still appropriate but measured CPU, memory, or storage demand requires more capacity. A larger VM is not a complete fix for: - uploads that grow without limit - a database needing a separate recovery target - background jobs blocking user requests - a requirement for host-level redundancy - an exposed or undocumented access model ### Split services Separate a component when it creates a distinct scaling, security, availability, or recovery boundary. Common candidates are databases, workers, object storage, and public edge services. The added reliability is useful only when the team can operate the extra components. ## How this applies on Raff [Raff Cloud Servers](/products/raff-vm) provide Linux and Windows VM foundations with NVMe storage, unmetered VM bandwidth, SSH key or console access, and full server control. Verify current plan sizes and prices on the live product page rather than relying on a historical price in an evergreen guide. A practical early architecture may use: - one Raff Linux VM for the reverse proxy, application, and worker - [Object Storage](/products/object-storage) for user uploads, media, archives, or backup objects - [Data Protection](/products/data-protection) for snapshots and scheduled infrastructure recovery - [Private Cloud Networks](/products/private-cloud-networks) when application and database services are separated Start simple, but make storage, access, monitoring, and recovery explicit before real customer data arrives. ## Production VPS launch checklist ### Capacity - Realistic workload test completed - Resource bottlenecks identified - Growth and headroom understood - Disk growth and log retention bounded ### Traffic and security - Public entry path documented - Only required ports exposed - Admin access restricted - Individual users and keys reviewed - Secrets protected and scoped ### Data and recovery - Persistent data inventory complete - RPO and RTO written - Backups scheduled - Restore tested - Deployment rollback documented ### Operations - Infrastructure and app health checks active - Alerts reach a named owner - Logs support troubleshooting and incident review - Runbook records deploy, rollback, and restore actions - First post-launch review is scheduled :::cluster ## Conclusion A production VPS is ready when the team understands its limits and can recover it. Measure workload behavior, keep the public traffic path simple, restrict administration, separate persistent data when the failure boundary requires it, test restoration, and monitor the application rather than only the VM. Launch on one server when simplicity is an advantage; resize or split components when evidence shows a different boundary is needed. :::cta Explore Raff VM Choose a cloud VM foundation for the first production version of your SaaS application. ::: ## Sources - [NIST Recovery Point Objective](https://csrc.nist.gov/glossary/term/recovery_point_objective) - [NIST Recovery Time Objective](https://csrc.nist.gov/glossary/term/recovery_time_objective) - [CISA: Use Logging on Business Systems](https://www.cisa.gov/audiences/small-and-medium-businesses/secure-your-business/use-logging-on-business-systems) - [Raff Cloud Servers](/products/raff-vm) - [Raff Object Storage](/products/object-storage) - [Raff Data Protection](/products/data-protection) --- ### Stale Infrastructure Cleanup: Server Decommissioning Checklist URL: https://rafftechnologies.com/learn/guides/stale-infrastructure-risk-old-servers-forgotten-keys-abandoned-services Description: Use this stale infrastructure and server decommissioning checklist to remove old servers, forgotten keys, abandoned services, DNS, storage, and data safely. Stale infrastructure is any server, service, credential, storage resource, network rule, or hostname whose current owner, purpose, access boundary, or retention need is unclear. **The safest response is not immediate deletion. It is a controlled decommissioning process: identify dependencies, reduce exposure, preserve required evidence or data, revoke access, test shutdown, and then remove every associated resource.** This guide focuses on the decision between keeping, restricting, rebuilding, archiving, and decommissioning old cloud infrastructure. ## Stale infrastructure is broader than idle infrastructure Idle infrastructure is mainly a cost problem. Stale infrastructure is an ownership, security, reliability, and data-governance problem. | Resource state | Meaning | Primary concern | |---|---|---| | Active | Current owner and business purpose are known | Normal operations | | Idle | Resource is not being used but may still have an owner | Cost and lifecycle | | Stale | Purpose, owner, patching, exposure, or access is unclear | Security and reliability | | Abandoned | No confirmed owner or business value remains | Removal and data handling | | Dangerous | Stale resource is publicly exposed, privileged, or connected to sensitive data | Immediate containment | A powered-off VM can still be stale if its disks, snapshots, credentials, DNS records, or data copies remain. A running server can be legitimate when it has an owner, current purpose, patching plan, monitoring, and recovery path. ## Use a keep, restrict, rebuild, archive, or decommission decision Every suspected stale resource should end with a recorded decision. | Decision | Use it when | |---|---| | Keep | The resource is active, owned, supported, and correctly exposed | | Restrict | It may still be needed, but its public access or privileges are too broad | | Rebuild | The workload is required, but the existing server state cannot be trusted or explained | | Archive | The active service can end, but data, configuration, or evidence must be retained | | Decommission | No current business, technical, legal, or recovery requirement remains | | Investigate | Dependencies or ownership are not yet understood | Use these questions: 1. Who owns the resource now? 2. Which business process or customer depends on it? 3. What traffic, users, keys, tokens, or services can reach it? 4. Which data does it store or process? 5. When was it last patched, monitored, backed up, and used? 6. Can it be recreated from code, documentation, or a clean image? 7. What must be retained before removal? 8. What is the rollback plan if a hidden dependency appears? A resource without a known owner and current purpose should be treated as stale until evidence proves otherwise. ## Build the complete resource inventory Deleting only the VM often leaves the risky or billable parts behind. Inventory the complete workload boundary: - VMs and container hosts - attached and detached disks - snapshots and backups - object storage buckets and exports - public and private IPs - load balancer targets and routes - firewall and security-group rules - DNS records and certificates - Linux and Windows users - SSH keys and RDP access - API keys, service accounts, and CI/CD tokens - databases, caches, and queues - monitoring checks and alerts - licenses and vendor integrations - infrastructure-as-code definitions NIST Cybersecurity Framework 2.0 emphasizes maintaining inventories of systems, software, services, and cloud resources. Decommissioning is safer when the inventory reflects dependencies rather than only visible compute instances. ## Prioritize the highest-risk stale items Review these first: | Item | High-risk signal | |---|---| | Public server | Unsupported software, no owner, no monitoring | | SSH key | Unknown owner, shared private key, former contractor | | Windows account | Public RDP, shared Administrator access, departed user | | API token | Broad privilege, unknown integration, no rotation owner | | Database copy | Production data in test, demo, or migration environments | | Firewall rule | Public port with no current service owner | | DNS record | Hostname points to an old or uncontrolled target | | Backup credential | Can restore or delete recovery points without clear ownership | | Detached volume | Unknown data and no retention decision | | Old certificate | Still valid for a retired hostname or service | Contain exposure before completing a long investigation. Restrict public routes, remove broad admin sources, disable unexplained credentials, or isolate the system when business impact permits. ## Old servers should be owned, rebuilt, or retired Servers drift as packages, users, services, secrets, and configuration change. Warning signs include: - unsupported operating-system or runtime versions - missed security updates - unknown listening services - former users or unexplained SSH keys - broad SSH or RDP exposure - old secrets in files, shell history, images, or deployment scripts - no current monitoring - no verified backup or restore path - manual changes that are not documented Patch and keep a server when it is understood and supportable. Rebuild it when the workload is required but the server state is unclear. Retire it when the workload no longer has a valid purpose. A larger or newer VM does not correct unknown trust. Rebuilding from a controlled baseline is often safer than trying to prove every historical change was legitimate. ## Forgotten credentials are separate decommissioning objects Removing dashboard access does not remove direct server or application access. Review: - SSH authorized keys - Linux users and sudo groups - Windows users and local Administrators - RDP permissions - VPN, bastion, and mesh membership - API keys and personal access tokens - CI/CD and deployment credentials - database users - backup and monitoring credentials - emergency or break-glass accounts CISA documents SSH authorized keys as a persistence mechanism. An unexplained key should be removed or investigated even when the associated person no longer appears in the cloud dashboard. For every credential, record: - owner - purpose - systems it can reach - privilege scope - storage location - recent use where evidence exists - rotation or removal action Rotate shared credentials that departing users or contractors could access. Removing one named account is insufficient when secrets were shared. ## Abandoned services create hidden attack surface A server may still be needed while some services on it are stale. Common examples include: - old admin panels - debug endpoints - database management interfaces - temporary file servers - webhook receivers - test APIs - monitoring dashboards - migration tools - legacy application ports Map listening ports to running processes and owners. Then compare them with firewall, load balancer, reverse proxy, and DNS configuration. A service without a current owner should not retain a public route. When dependency risk is unclear, restrict access first, observe impact, and remove it after validation. ## Stale data copies require a retention and sanitization decision Temporary infrastructure often contains non-temporary data. Examples include: - restored backups - production database clones - migration test datasets - customer exports - uploaded documents - logs containing personal or security information - copied secrets and certificates Before deletion, identify the data owner, sensitivity, legal or contractual retention requirement, and approved disposal method. NIST SP 800-88 Revision 2 provides current guidance for media sanitization and disposal based on information sensitivity. In cloud environments, the customer may not directly sanitize physical media, but the principle still applies: deletion, encryption-key handling, retained snapshots, exported copies, and provider workflows must match the required confidentiality outcome. Do not create a long-lived archive merely because deletion feels risky. An archive needs an owner, retention period, access control, encryption plan, and final disposal date. ## DNS, certificates, and routes must be removed deliberately Infrastructure may remain reachable after compute is shut down. Review: - public DNS records - private DNS records - wildcard records - legacy API hostnames - load balancer routes - reverse-proxy configuration - TLS certificates - health checks - monitoring endpoints - webhooks and allowlists A public hostname should map to a current owner and intended service. Retired hostnames should not point to old servers, reused IPs, or uncontrolled external services. Plan DNS changes around TTL, client caching, integrations, and rollback requirements. Remove obsolete certificates and external validation records after confirming they are no longer required. ## Use a controlled server decommissioning checklist AWS Well-Architected guidance recommends a standardized process that verifies whether the workload and associated resources are still used, coordinates with owners, records metadata, protects required data, and removes related resources. ### 1. Identify the candidate Record: - resource name and location - owner or suspected owner - purpose - users and customers - public and private addresses - attached resources - creation and last-known-use dates ### 2. Discover dependencies Check: - DNS and load balancer routes - inbound and outbound connections - scheduled jobs - application integrations - monitoring and backup jobs - database and storage connections - CI/CD and infrastructure-as-code references - licenses and vendor allowlists ### 3. Decide what must be retained Preserve only what has a defined reason: - business records - required logs - configuration - encryption keys or certificates needed for restoration - database exports - recovery points - audit evidence Assign an owner and expiry to every retained copy. ### 4. Reduce exposure Before shutdown, where practical: - remove public routes - restrict firewall rules - disable unnecessary users - revoke unexplained keys and tokens - make data read-only - isolate the service from production ### 5. Announce and schedule the change Notify workload owners and affected users. Define: - shutdown window - validation period - rollback owner - monitoring plan - final deletion date ### 6. Stop the workload and observe Shut down or disable the service during a controlled window. Monitor for: - failed jobs - user reports - integration errors - DNS requests - unexpected connections - monitoring alerts A defined observation period can reveal hidden dependencies without immediately destroying the rollback path. ### 7. Remove access and integrations Revoke: - users and groups - SSH keys and RDP access - API tokens and service accounts - firewall rules - VPN or bastion access - webhook endpoints - deployment jobs - monitoring and backup jobs ### 8. Delete associated resources Remove or archive according to policy: - VM - disks and volumes - snapshots and backups - object storage data - load balancer routes - IP allocations - DNS records - certificates - licenses - infrastructure-as-code references ### 9. Verify completion Confirm: - no public route remains - no credential still references the retired system - no billable storage or networking resource was missed - required records are retained with an owner and expiry - documentation and inventory are updated - the rollback window is formally closed ## Decommissioning and disaster recovery are different decisions A recovery point supports restoration. It should not become indefinite storage by accident. Before keeping a snapshot or backup, define: - which incident it protects against - retention period - restoration owner - access and deletion permissions - encryption-key requirements - final disposal date Read [Cloud Server Backup Strategy](/learn/guides/cloud-server-backup-strategies) for recovery design. Read [Cloud Snapshots vs Backups](/learn/guides/snapshots-vs-backups-cloud-server) for the difference between short rollback points and retained recovery. ## Review cadence should follow change rate Use event-driven reviews after: - employee or contractor departure - migration completion - incident response - product or customer demo - major architecture change - application retirement - account or project consolidation A practical recurring baseline is: | Review | Typical focus | |---|---| | Monthly light review | Public VMs, temporary environments, firewall exceptions, unknown owners | | Quarterly deep review | Credentials, disks, snapshots, DNS, data copies, service dependencies | | Annual lifecycle review | Retention, licenses, legacy applications, long-term archives | High-change MSP, SaaS, and contractor-heavy environments may need more frequent review. ## How this applies on Raff A Raff cleanup review may include: - [Linux VM](/products/linux-vm): active servers, SSH keys, users, packages, and services - [Windows VM](/products/windows-vm): RDP users, local Administrators, patching, and application ownership - [Security](/products/security): public ports, firewall rules, and administrative exposure - [Data Protection](/products/data-protection): snapshots, backups, restore needs, and retention - [Volumes](/products/volumes): attached and detached persistent storage - [Object Storage](/products/object-storage): exports, archives, uploads, and backup objects Verify current dashboard capabilities and product behavior before relying on a specific deletion, retention, or restore workflow. ## Stale infrastructure cleanup checklist ### Ownership and purpose - Every resource has a named owner - Current business purpose is documented - Users and dependencies are identified - Temporary resources have an expiry ### Access and exposure - Public ports and routes are justified - SSH keys and RDP users are current - API tokens and service accounts have owners - Former users and contractors are removed ### Data and recovery - Data sensitivity is known - Required retention is documented - Recovery points have owners and expiry dates - Disposal follows an appropriate sanitization process ### Decommissioning - Shutdown was announced - Hidden dependencies were tested - Observation and rollback windows were completed - DNS, routes, credentials, storage, and licenses were removed - Inventory and documentation were updated :::cluster ## Conclusion Stale infrastructure is unknown trust left active. The safest cleanup process identifies the complete workload boundary, prioritizes exposed and privileged resources, preserves only data with a defined requirement, tests shutdown before destruction, revokes every access path, and removes associated storage, DNS, networking, certificates, and automation. A server decommissioning checklist is complete only when the VM and everything that depended on it have reached an intentional final state. :::cta Explore Security Review Raff’s security and infrastructure controls before restricting, rebuilding, or retiring cloud workloads. ::: ## Sources - [NIST Cybersecurity Framework 2.0](https://www.nist.gov/cyberframework) - [NIST SP 800-88 Rev. 2: Guidelines for Media Sanitization](https://csrc.nist.gov/pubs/sp/800/88/r2/final) - [CISA: SSH Authorized Keys](https://www.cisa.gov/eviction-strategies-tool/info-attack/T1098.004) - [AWS Well-Architected: Implement a Decommissioning Process](https://docs.aws.amazon.com/wellarchitected/latest/framework/cost_decomissioning_resources_implement_process.html) - [Raff Security](/products/security) --- ### Incident Response Plan for Small Teams: Triage, Containment, and Recovery URL: https://rafftechnologies.com/learn/guides/server-incident-response-small-teams-triage-containment-recovery Description: Build a small-team incident response plan covering triage, evidence, containment, recovery, communication, validation, and post-incident review. An incident response plan defines how a team detects, declares, contains, investigates, recovers from, and learns from a security or reliability incident. **For a small team, the plan should make the first decisions obvious: who owns the incident, what is affected, whether data or privileged access is at risk, which evidence must be preserved, how harm will be contained, and which rollback, restore, failover, or rebuild path is safe.** The plan does not need enterprise complexity. It needs clear authority, tested recovery options, reliable contacts, and a record of decisions. ## An incident response plan is a decision system A useful plan answers six questions before pressure arrives: 1. What conditions require an incident to be declared? 2. Who becomes the incident owner? 3. How is severity determined? 4. Which containment actions are authorized? 5. Which recovery path applies to each workload? 6. Who communicates internally and externally? NIST SP 800-61 Revision 3 treats incident response as part of broader cybersecurity risk management rather than an isolated emergency activity. Preparation, detection, response, recovery, and improvement depend on controls that exist before the incident begins. ## Define what counts as an incident Not every alert is an incident. Not every incident is a security breach. | Event | Typical handling | |---|---| | Brief CPU spike with no user impact | Operational investigation | | Failed deployment with visible errors | Reliability incident | | Customer-facing outage | Availability incident | | Suspected stolen SSH key or admin token | Security incident | | Unexpected database deletion or corruption | Data-integrity incident | | Malware, unauthorized process, or unexplained persistence | Security incident | | Backup job failure with no immediate outage | Recovery-readiness incident | | One noisy alert with no supporting evidence | Validate before escalation | Declare an incident when coordination, containment, recovery, customer communication, or evidence preservation is needed beyond routine troubleshooting. A practical rule is: > Treat suspected compromise of privileged access, customer data, or an internet-facing production system as high severity until evidence reduces the risk. ## Use impact, scope, and confidence for triage Severity should reflect business and technical risk rather than how alarming the first alert looks. ### Impact - Are customers unable to use a critical function? - Is sensitive or regulated data involved? - Are transactions, writes, or files being lost or corrupted? - Is revenue, support, or business continuity affected? ### Scope - One process, one VM, one service, or multiple systems? - One user or many customers? - Is the issue spreading through credentials, networking, automation, or shared storage? ### Confidence - Confirmed incident or unverified signal? - Known cause or unexplained behavior? - Reliable logs and timestamps available? A simple severity model may be: | Severity | Example | Response posture | |---|---|---| | Critical | Confirmed privileged compromise, active data destruction, major multi-service outage | Immediate ownership, containment, executive/customer decision path | | High | Customer-facing outage, suspected compromise, serious corruption | Rapid coordination and frequent updates | | Medium | Degraded service, failed deployment, contained access issue | Assigned owner and structured remediation | | Low | No user impact, isolated warning, weak signal | Validate and handle during normal operations | Severity can change as evidence improves. Record why it changed. ## Assign roles even when one person holds several Small teams may not have separate security, operations, support, and communications staff. The roles still need to exist. | Role | Responsibility | |---|---| | Incident owner | Sets priority, approves major actions, and maintains the next decision | | Technical lead | Investigates scope and proposes containment and recovery | | Communications owner | Manages internal, customer, partner, or leadership updates | | Scribe | Records timestamps, evidence, hypotheses, actions, and outcomes | | Business owner | Confirms customer impact and recovery priorities | One person can hold several roles, but the team should know who has final authority to isolate a server, rotate credentials, stop writes, restore data, or communicate externally. ## The first 15 minutes should create control The initial response should reduce confusion, not solve everything immediately. ### Confirm the signal Check at least two useful sources where possible: - monitoring and health checks - application and infrastructure logs - customer reports - deployment history - authentication events - database or storage behavior - firewall and network changes ### Declare an owner and severity Record: - incident start time or earliest known signal - affected workload - current customer impact - suspected security or data risk - incident owner - next update time ### Freeze unnecessary changes Pause unrelated deployments, configuration changes, cleanup actions, and migrations that could alter evidence or create new variables. ### Choose the immediate objective The first objective is usually one of these: - stop ongoing harm - restore customer availability - preserve data integrity - protect credentials - prevent spread - verify whether the alert is real Trying to pursue every objective at once can create conflicting actions. ## Preserve evidence before destructive actions Evidence helps determine scope, root cause, customer impact, and whether a restored environment is safe. Useful evidence may include: - application, system, authentication, and firewall logs - process lists and listening ports - active network connections - deployment and configuration history - cloud activity records - affected files and timestamps - database logs and transaction history - suspicious accounts, SSH keys, tokens, or scheduled tasks - monitoring graphs - a snapshot or disk copy when appropriate Do not assume a snapshot is clean. It may preserve compromised or corrupted state. Its value may be evidence, rollback, or later analysis rather than direct production restoration. Avoid rebooting, deleting processes, rotating every credential, or wiping a server before considering which evidence will disappear. When continued operation causes greater harm, containment takes priority; document what could not be preserved. ## Choose containment according to the failure Containment reduces harm while the team prepares recovery. | Containment action | Appropriate when | Main risk | |---|---|---| | Restrict firewall rules | Public exposure is unnecessary or suspicious | May block users or integrations | | Isolate a VM | Compromise or lateral movement is possible | Immediate service interruption | | Disable an account or key | One identity is suspected | Hidden dependencies may fail | | Rotate credentials | A secret may be exposed | Automation and services may break | | Stop application writes | Corruption or destructive changes continue | Availability becomes limited | | Remove a load balancer target | One backend is unhealthy | Remaining capacity may be insufficient | | Roll back a deployment | Recent release is likely responsible | Database or schema changes may be incompatible | | Shut down the service | Continued operation creates greater harm | Full outage | Containment and recovery are different decisions. A firewall block may stop harm but not restore a trusted service. A restart may restore service but fail to remove the cause. For administrative exposure decisions, use [Private vs Public Admin Access](/learn/guides/private-vs-public-admin-access). For network rules, use [Cloud Firewall Best Practices](/learn/guides/firewall-best-practices-cloud-servers). ## Use the right recovery path Recovery depends on what failed and whether the current environment can still be trusted. | Incident | Likely recovery choice | |---|---| | Bad application release | Roll back or fix forward | | Failed OS or package update | Snapshot rollback or rebuild | | Resource exhaustion | Reduce load, resize, scale, or optimize | | Database corruption | Stop harmful writes and restore to an approved recovery point | | Deleted files | Restore selected files or data | | Compromised credential | Revoke, rotate, review scope, and validate affected systems | | Suspected VM compromise | Rebuild from a trusted baseline and restore verified data | | Host or storage loss | Recreate infrastructure and restore from retained protection | | Network misconfiguration | Restore known-good rules and validate allowed and denied paths | ### Roll back Use rollback when a recent controlled change is the likely cause and the previous version remains compatible with current data and configuration. ### Restore Use restore when data or system state must return to a known recovery point. Confirm the expected data-loss window and restoration time. ### Rebuild Use rebuild when the existing server cannot be trusted, its state is poorly understood, or repair would leave uncertainty about persistence, credentials, or hidden changes. ### Fail over Use failover only when the secondary path is tested and data consistency is understood. An untested standby can turn one incident into two. Read [Cloud Server Backup Strategy](/learn/guides/cloud-server-backup-strategies) and [High Availability vs Disaster Recovery](/learn/guides/high-availability-vs-disaster-recovery-small-teams) when designing the recovery model. ## Validate recovery before declaring resolution A service is not recovered merely because the VM responds to a ping or the process is running. Validate: - critical user workflows - authentication and authorization - database reads and writes - queues and background jobs - integrations and webhooks - file and object access - DNS, TLS, and routing - monitoring and alerting - backup jobs - administrator access - security indicators related to the incident Define a warranty period after recovery. Continue monitoring the original failure signal, customer impact, resource behavior, and suspicious activity before closing the incident. ## Communication should state facts, impact, actions, and timing Internal updates should answer: - What is affected? - What is the current impact? - What is confirmed and what remains a hypothesis? - What action is happening now? - Who owns the next decision? - When is the next update? Customer communication should avoid unsupported cause statements. It should describe observed impact, current mitigation, available workarounds, and the next expected update. Do not wait for perfect certainty before acknowledging a customer-visible outage. Do not declare a security breach, data loss, or root cause without evidence and the appropriate business or legal review. Reporting and notification obligations vary by jurisdiction, contract, data type, and customer relationship. The plan should identify who evaluates those obligations rather than asking engineers to improvise legal decisions during the incident. ## Keep one reliable incident timeline The timeline should record: - timestamp - observation or evidence - action taken - person responsible - reason for the decision - result - next step Separate facts from hypotheses. Example: | Time | Record | |---|---| | 14:05 | Monitoring detects elevated API errors | | 14:08 | Incident declared; customer login affected | | 14:11 | Recent deployment identified as leading hypothesis | | 14:16 | New deployments paused; rollback approved | | 14:24 | Error rate returns to baseline | | 14:31 | Login and billing workflows validated | A clear timeline supports handoffs, customer updates, post-incident review, and evidence preservation. ## Build the plan before the incident Preparation should include: - workload inventory and business owners - severity definitions - incident roles and contact methods - out-of-band communication path - administrator and emergency access - log locations and retention - known containment actions - rollback and rebuild procedures - backup and restore ownership - customer communication templates - vendor and support contacts - decision path for legal, privacy, insurance, or contractual review Store the plan somewhere accessible when the main production environment, identity provider, documentation system, or chat platform is unavailable. Exercise it with realistic scenarios such as: - public SSH key compromise - failed database migration - ransomware or destructive file encryption - expired certificate - accidental firewall lockout - deleted production data - failed deployment during off-hours The exercise should test decisions, access, contacts, and recovery—not only whether a document exists. ## Post-incident review should produce owned changes A review should answer: 1. What happened? 2. When did impact begin and end? 3. How was the incident detected? 4. What increased or reduced the impact? 5. Which containment and recovery actions worked? 6. Which assumptions were wrong? 7. What should change? Actions should have owners and due dates. Examples include: - restrict public administration - improve alert quality - increase log retention - add deployment rollback checks - test database restoration - remove stale credentials - separate application and database recovery - add a customer communication template - document emergency access Avoid a review that ends only with “be more careful.” Improve the system, process, or recovery path that allowed the incident to grow. ## Incident response depth by scenario | Scenario | First priority | Recovery bias | |---|---|---| | Failed deployment | Stop further changes and validate rollback | Roll back or fix forward | | Availability outage | Restore critical service safely | Restart, reroute, resize, or restore | | Credential compromise | Revoke access and determine scope | Rotate, validate, and rebuild where trust is lost | | Suspected malware | Isolate and preserve evidence | Clean rebuild and verified data restore | | Database corruption | Stop harmful writes | Point-in-time or approved backup restore | | Data deletion | Prevent further deletion | Granular or full restore | | DDoS or traffic flood | Protect availability and origin systems | Filter, rate-limit, reroute, or scale | | Configuration error | Restore known-good state | Revert and validate dependencies | ## How this applies on Raff A Raff incident response plan may use: - [Cloud Servers](/products/raff-vm) for existing workloads or clean replacement VMs - [Security](/products/security) to restrict exposed traffic paths - [Private Cloud Networks](/products/private-cloud-networks) to isolate internal service communication - [Data Protection](/products/data-protection) for infrastructure recovery points - [Volumes](/products/volumes) and [Object Storage](/products/object-storage) where workload data or retained evidence requires compatible storage A practical response may restrict a public route, preserve relevant state, deploy a clean replacement server, restore verified data, validate the application, and then retire the affected environment deliberately. Verify current product capabilities, restore behavior, network controls, and dashboard workflows before relying on a specific emergency action. ## Incident response checklist ### Declare and coordinate - Incident owner assigned - Severity and affected workload recorded - Customer, data, and privileged-access risk assessed - Next update time set - Unrelated changes paused ### Investigate and preserve - Signal confirmed with available evidence - Timeline started - Relevant logs and state preserved - Facts separated from hypotheses - Scope and spread assessed ### Contain - Immediate objective selected - Access, traffic, writes, or affected systems restricted as needed - Credential actions coordinated with dependencies - Evidence impact documented ### Recover - Rollback, restore, rebuild, failover, or scaling path selected - Recovery point and expected data loss confirmed - Critical workflows validated - Monitoring and backups verified - Warranty period started ### Close and improve - Customer and internal updates completed - Timeline finalized - Root and contributing causes documented - Improvement actions assigned - Temporary rules, accounts, and resources removed :::cluster ## Conclusion An incident response plan helps a small team make reliable decisions while evidence is incomplete and pressure is high. Define when to declare an incident, assign authority, triage by impact and scope, preserve evidence, contain the specific failure, and choose the correct rollback, restore, rebuild, or failover path. Validate real user workflows before declaring recovery, keep one timeline, and turn the post-incident review into owned improvements. :::cta Explore Security Build clearer containment and recovery boundaries for your Raff cloud workloads. ::: ## Sources - [NIST SP 800-61 Rev. 3: Incident Response Recommendations](https://csrc.nist.gov/pubs/sp/800/61/r3/final) - [NIST Cybersecurity Framework 2.0](https://www.nist.gov/cyberframework) - [CISA Incident and Vulnerability Response Playbooks](https://www.cisa.gov/sites/default/files/2024-08/Federal_Government_Cybersecurity_Incident_and_Vulnerability_Response_Playbooks_508C.pdf) - [Raff Security](/products/security) - [Raff Data Protection](/products/data-protection) --- ### Best VPS Hosting Providers: How to Compare Your Options URL: https://rafftechnologies.com/learn/guides/best-vps-hosting-providers Description: Compare the best VPS hosting providers by performance, support, pricing, locations, backups, and lock-in using a transparent decision framework. The best VPS hosting provider is the company whose compute model, performance consistency, support boundary, recovery options, network footprint, and complete monthly cost match a specific workload. There is no universal winner. A provider that is ideal for a self-managed application in Europe may be a poor fit for a U.S.-focused workload, a Windows deployment, or a team that needs managed operating-system support. Raff is included in this guide because we operate a VPS platform, but this is not a ranking designed to make Raff win every category. The comparison uses the same evidence for each provider and identifies where DigitalOcean, Hetzner Cloud, Vultr, Amazon Lightsail, OVHcloud, and Raff can be strong fits. Prices and product details change, so verify the live plan, region, and contract before buying. Use the [VPS provider decision framework](/learn/guides/how-to-choose-a-vps-provider) first when you need a full evaluation checklist. This guide turns that framework into a practical shortlist. ## The Best VPS Hosting Provider Depends on the Workload “Best VPS hosting” is a commercial search term, but the decision behind it is architectural. The correct provider depends on what the server must do, where users are located, how much variance the application can tolerate, and who owns daily operations. A useful shortlist starts with non-negotiable requirements: - required operating system and software licensing; - shared or dedicated CPU preference; - minimum memory, storage, and network capacity; - user and dependency geography; - expected transfer and traffic patterns; - backup frequency, retention, and restore target; - acceptable downtime and recovery time; - unmanaged, managed, or co-managed responsibility; - API, Terraform, image, and networking requirements; - migration and exit constraints. A developer hosting a staging environment may prioritize low entry cost, fast provisioning, and API access. A SaaS application with sustained compute may prioritize dedicated CPU and predictable performance. A content platform may care more about bandwidth policy and storage expansion. An agency may value a simple control panel and documentation. A global application may reject a provider with only one suitable region, regardless of its compute value. This is why provider lists that declare one universal winner are usually incomplete. They often compare headline prices without normalizing transfer, backups, support, CPU allocation, billing period, or region. They may also combine managed hosting, unmanaged cloud VMs, and simplified application platforms as though they provide the same operating model. Before comparing providers, confirm that VPS is the correct infrastructure model and estimate the required server size. The [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) covers that earlier decision. Once the requirement is clear, eliminate providers that fail a mandatory condition. Score only the remaining options. ## A Transparent Scorecard Prevents Affiliate-Style Rankings A provider comparison should show the decision method before presenting the shortlist. The following 100-point model keeps the evaluation consistent while allowing the weights to change by workload. | Evaluation category | Default weight | Evidence to verify | | --- | ---: | --- | | Workload and compute fit | 15 | OS support, shared or dedicated CPU, memory, storage, images, and architecture | | Performance consistency | 15 | Repeated CPU, storage, network, and application-level results | | Complete monthly cost | 15 | Compute, backups, storage, transfer, IPs, licensing, support, and renewal terms | | Reliability and recovery | 12 | SLA scope, maintenance rules, snapshots, backups, restore path, and recovery time | | Support and responsibility | 10 | Platform support, guest OS ownership, management scope, and escalation | | Location and network fit | 10 | Regions, routes, latency, bandwidth policy, private networking, and DDoS handling | | Security and access controls | 8 | Firewall, console, credentials, isolation, account controls, and incident process | | Scaling and automation | 8 | Resize paths, API, CLI, Terraform, images, load balancing, and adjacent services | | Portability and exit path | 4 | Data export, snapshots, DNS independence, reproducibility, and cancellation | | Documentation clarity | 3 | Current product, billing, limit, SLA, and recovery documentation | Score each category from 1 to 5. Multiply the score by the weight and divide by 5. A provider receiving 4 out of 5 in a 15-point category earns 12 points. Do not let a high total override a failed requirement. A provider with an excellent overall score should still be removed when it lacks the required region, operating system, licensing path, backup design, or management scope. The default weights are appropriate for a general production workload, but they are not fixed: - increase performance and compute weight for builds, databases, game servers, and sustained application workloads; - increase location and network weight for latency-sensitive APIs, media delivery, or distributed users; - increase support and recovery weight when the internal team has limited infrastructure capacity; - increase cost weight for fleets of small servers or high-transfer workloads; - increase automation and portability weight when infrastructure is managed as code. The score should be supported by evidence, not impressions. Record the exact plan, region, date, billing assumptions, test method, and source page. If a provider does not publish enough information, mark the category as unverified rather than awarding an average score. The purpose is not to manufacture a mathematically precise winner. It is to expose assumptions. Two teams can use the same scorecard and reach different conclusions because their workloads and operating capabilities are different. :::cluster ## Six VPS Providers Fit Different Production Priorities The following providers represent distinct operating models and buyer priorities. The order is not a ranking. Each can be the strongest option when its advantages match the workload and its limitations are acceptable. ### Raff is a strong fit for transparent U.S.-east VM deployments Raff VM is designed for developers, founders, small teams, and service providers that want a direct cloud VM model without a hyperscaler-sized catalog. General Purpose plans use shared CPU resources, while CPU-Optimized plans use dedicated CPU resources. The platform uses AMD EPYC processors and NVMe storage. Raff publishes a 3 Gbps unmetered public bandwidth policy for VM plans, with the live plan and acceptable-use conditions controlling the final offer. The platform includes firewall controls, private networking, console access, snapshots, automated backups, API access, and Terraform support. Its published SLA states a 99.90% monthly commitment for Virtual Machines and specified supporting services. The focused scope is also the main limitation. Raff currently operates a focused `us-east` footprint. It is not the automatic choice for teams requiring several global regions, a very broad hardware catalog, or fully managed guest operating-system administration. Those needs should move the comparison toward a provider built around them. Raff is strongest when the buyer values visible resource classes, a straightforward VM product, unmetered bandwidth, direct infrastructure support, and a U.S.-east deployment. Review the current [Raff VM page](/products/raff-vm), [pricing](/pricing), and SLA before assigning a score. ### DigitalOcean is a strong fit for developer experience and a broad cloud ecosystem DigitalOcean calls its virtual machines Droplets. Its official product and documentation emphasize Linux-based VMs, an intuitive control panel, CLI, API, Terraform integration, resizing, cloud firewalls, volumes, load balancers, autoscaling, and globally distributed data centers. That makes DigitalOcean a natural shortlist candidate for developers and product teams that value polished documentation and adjacent services. Its plan families cover basic shared-resource workloads as well as CPU-, memory-, storage-, and general-purpose use cases. DigitalOcean also uses predictable monthly caps, while its current pricing documentation states that Droplet billing moved to per-second granularity in 2026. The tradeoff is that the complete bill can extend beyond the VM. Backups, storage, load balancing, transfer beyond included policies, and other services need to be normalized against alternatives. Buyers should also confirm that the selected Droplet class provides the CPU allocation and consistency required by the workload. DigitalOcean is a strong fit when a mature developer workflow and integrated cloud services matter more than minimizing the base VM price. ### Hetzner Cloud is a strong fit for self-managed price-performance Hetzner Cloud offers shared-resource and dedicated-resource server classes, along with firewalls, volumes, load balancers, private networks, backups, snapshots, rescue tools, and API-based management. Its published locations include European, U.S., and Singapore options. Hetzner is frequently shortlisted by experienced operators seeking strong compute value. Its regular-performance shared plans suit variable workloads, while dedicated-resource classes are designed for sustained CPU requirements. The platform is particularly attractive when the team can manage Linux servers directly and is comfortable evaluating each add-on separately. The complete comparison must include network geography, support expectations, public IP charges, backup behavior, and operational ownership. Hetzner documentation notes that public IPs are separate from the server resource, and its backup behavior should be reviewed carefully because server-bound backups can be removed when a server is deleted. Hetzner Cloud is a strong fit for self-managed teams that prioritize price-performance and can work within its location, support, and product model. ### Vultr is a strong fit for location choice and flexible compute categories Vultr offers Cloud Compute shared-CPU instances and additional optimized, GPU, and bare-metal categories. Its current documentation supports deployment and management through the console, API, CLI, and Terraform, with custom ISO and operating-system options available for suitable use cases. The broad location selection is useful when a workload needs to be close to a particular audience or dependency. Vultr can also be attractive when a team wants to start with a general-purpose VM and later evaluate more specialized compute without changing vendors. The category labels still require careful interpretation. Shared Cloud Compute is designed for bursty general-purpose workloads; sustained production workloads may need an optimized class. Compare the exact CPU model, storage behavior, transfer allowance, region availability, and backup cost instead of treating every Vultr instance as equivalent. Vultr is a strong fit when location flexibility and a wider compute catalog carry significant weight. ### Amazon Lightsail is a strong fit for simplified entry into AWS Amazon Lightsail packages virtual servers with a simplified AWS experience. It supports Linux and Windows instances, preconfigured application blueprints, managed databases, containers, object and block storage, load balancers, CDN distributions, DNS, static IPs, firewalls, and snapshots. Lightsail is useful for websites, small applications, WordPress deployments, and teams that want an easier starting point than assembling the same architecture directly from multiple AWS services. It can also integrate with other AWS services through VPC peering. AWS provides a guided path to export a Lightsail snapshot and create an EC2 instance when a project outgrows the simplified model. The limitation is that simplicity narrows flexibility. Buyers should understand the boundary between Lightsail and the broader AWS platform, the effect of bundle transfer allowances, and the operational work required after a blueprint is deployed. Moving to EC2 can expand capability but also changes the cost and management model. Amazon Lightsail is a strong fit when a predictable bundle, application blueprints, and an AWS growth path matter more than granular infrastructure control. ### OVHcloud VPS is a strong fit for bandwidth and built-in network protection OVHcloud's current VPS offer emphasizes unlimited traffic, plan-dependent public bandwidth, included anti-DDoS protection, daily backup on listed plans, API and control-panel management, and an integrated KVM console. That combination can be useful for websites, VPNs, game servers, development environments, and other workloads where transfer policy and DDoS handling matter. The provider also operates a larger infrastructure portfolio, which may be relevant to teams considering dedicated or broader cloud services later. The buyer should still verify the exact regional availability, backup retention, management boundary, CPU model, SLA, and fair-use conditions for the selected plan. “Backup included” does not replace application-aware data protection or an independent restore test. “Unlimited traffic” also needs to be read with the plan's bandwidth and acceptable-use rules. OVHcloud VPS is a strong fit when included traffic, anti-DDoS protection, and a familiar VPS control model are high-priority requirements. | Provider | Strongest shortlist reason | Main condition to verify | | --- | --- | --- | | Raff | Transparent VM classes, unmetered bandwidth, direct model | Focused `us-east` footprint and unmanaged guest OS scope | | DigitalOcean | Developer experience, documentation, adjacent cloud services | Complete cost and selected Droplet resource class | | Hetzner Cloud | Self-managed price-performance | Region, support scope, public IP, and backup behavior | | Vultr | Location choice and compute variety | Shared versus optimized class and regional plan details | | Amazon Lightsail | Simplified AWS entry and blueprints | Bundle limits and transition to broader AWS services | | OVHcloud VPS | Traffic policy, anti-DDoS, and included VPS features | Exact plan, location, SLA, and recovery scope | ## Performance Claims Need Repeated, Comparable Tests Provider marketing can identify hardware classes and plan features, but it cannot prove how a workload will perform. Benchmarking should use identical plans, regions, operating systems, settings, and test windows whenever possible. At minimum, compare: - single-core and multi-core CPU performance; - sustained CPU behavior and variance; - sequential storage throughput; - random read and write IOPS; - storage latency; - network throughput to relevant destinations; - latency from the actual user base; - one application-level task such as a build, database query set, or page-generation test. Run at least three iterations and compare medians rather than publishing the best result. Longer tests are important for detecting shared-resource contention, throttling, noisy-neighbor effects, and storage variance. A shared-CPU plan can show an excellent short burst while delivering less predictable performance under sustained load. Use the exact same plan class. Comparing a dedicated-vCPU product with an entry shared-vCPU product may answer a budget question, but it does not answer which provider has the better equivalent compute model. The [VPS Benchmarking Guide](/learn/guides/vps-benchmarking-guide) provides a repeatable methodology. It also explains why CPU family names, “NVMe” labels, and port-speed claims need real workload context. Benchmarks should not dominate the entire decision. A provider can lead one synthetic test and lose on region latency, recovery, support, or complete cost. The useful result is the minimum plan that meets the workload target with acceptable variance. ## Support, Backups, and SLAs Define Operational Risk The provider's operating model becomes most visible during failure. Compare support, backups, and the SLA as one risk system rather than three unrelated features. Start with the responsibility boundary: | Responsibility | Unmanaged VPS provider | Managed service | Customer | | --- | --- | --- | --- | | Physical host and virtualization | Provider | Provider | No | | VM lifecycle and platform networking | Provider | Provider | Shared configuration | | Guest OS updates and hardening | Usually customer | May be included | Yes when unmanaged | | Application, database, and code | Usually customer | Often limited or excluded | Usually customer | | Backup feature availability | Provider | Provider | Scope must be configured and verified | | Restore decision and validation | Shared | May be assisted | Customer owns business recovery | | Monitoring and incident response | Not implied | May be included | Required when unmanaged | A “24/7 support” label does not tell you whether the provider will debug an operating-system update, repair a database, restore application data, or investigate a networking issue inside the VM. Ask for written examples of included and excluded tasks. Backups require the same detail. Verify schedule, retention, storage separation, failure alerts, restore process, restore time, deletion behavior, and whether file-level recovery is available. Snapshots are useful before changes, but a snapshot attached to the same account is not automatically a complete disaster-recovery design. Read the SLA itself rather than the headline percentage. Confirm what counts as downtime, which services are covered, measurement period, exclusions, maintenance rules, credit levels, claim deadline, and maximum compensation. The [VPS Uptime SLA guide](/learn/guides/vps-uptime-sla-explained) explains how similar percentages can represent different commitments. :::cta Explore Raff VM Compare Raff VM resources, bandwidth, backups, automation, and pricing against the same provider scorecard. ::: ## Pricing Must Include Traffic, Protection, and Exit Costs The cheapest advertised VPS is not necessarily the lowest-cost production option. Normalize the bill around the same workload and month. ```text Complete monthly cost = VM plan + block or object storage + backups and snapshots + outbound transfer or overage + public IPv4 + operating-system licensing + load balancing and network services + monitoring or management + support tier + taxes, commitments, and renewal effects ``` Billing models also change risk. Monthly caps can make a continuously running server predictable. Per-second or hourly billing can reduce cost for temporary environments. Annual commitments can lower an apparent monthly rate while increasing migration friction. Promotional prices should be separated from normal renewal prices. Traffic policy is especially important. Providers may offer unmetered transfer, a monthly allowance, pooled bandwidth, per-gigabyte billing, or a policy that combines “unlimited” traffic with a fixed port speed and fair-use terms. Estimate normal and peak transfer before comparing. Protection is another common gap. A low VM price can become less attractive when required backups, retained snapshots, block storage, public IPs, or management are added. Conversely, an included feature has value only when its scope meets the recovery requirement. Exit costs are operational as well as financial. Document how to export databases, application data, images, DNS, firewall rules, and infrastructure definitions. Confirm what happens to backups after cancellation and whether a migration requires overlapping service for several days or weeks. The [Cloud Server Pricing Guide](/learn/guides/cloud-server-cost-2026) provides a deeper cost model. Use live provider pricing pages for final numbers because plans, exchange rates, taxes, and included features can change. ## Raff VM Is Strongest for Transparent U.S.-East Deployments Raff should be evaluated with the same rules applied to every other provider. The platform offers General Purpose shared-CPU VMs and CPU-Optimized dedicated-CPU VMs using AMD EPYC processors and NVMe storage. Raff VM plans publish a 3 Gbps unmetered public bandwidth policy. Platform capabilities include firewall controls, private networking, console access, snapshots, automated backups, API access, and Terraform support. Raff's published SLA states a 99.90% monthly commitment for VMs and specified supporting services. Buyers should read the controlling SLA for measurement, exclusions, credits, and claim rules. They should also verify current plan resources and protection costs on the live pricing page. From my work building Raff's product and buyer experience, the most important comparison is not whether a plan can produce one impressive benchmark. It is whether a customer can understand the CPU allocation, bandwidth policy, protection options, monthly bill, support boundary, and upgrade path before deploying. Ambiguity in any of those areas becomes operational work later. Raff's strongest fit is a developer, founder, small team, or service provider deploying in `us-east` and looking for a direct VM model with transparent resource classes and unmetered bandwidth. A buyer requiring several global regions, specialized hardware across many categories, or fully managed application and guest-OS administration should choose a provider that explicitly covers those requirements. This honest boundary is part of the decision. Raff does not need to win every workload to be the correct provider for the workloads it is designed to serve. ## Choose a Provider by Eliminating Failed Requirements The best VPS hosting provider is the one that survives the workload's non-negotiable filters and achieves the strongest evidence-backed score for the remaining priorities. Use this sequence: 1. Write the workload, region, resource, recovery, and management requirements. 2. Remove providers that fail any mandatory condition. 3. Normalize the exact plan, billing period, transfer, backup, IP, licensing, and support costs. 4. Run repeated benchmarks in the intended region. 5. Read the SLA, backup, support, acceptable-use, and cancellation terms. 6. Test the control panel, console, API, and restore workflow where possible. 7. Record the decision and the conditions that would trigger a future review. Choose Raff when its focused `us-east` model, VM resource classes, bandwidth policy, and direct infrastructure tooling match the workload. Choose DigitalOcean when developer experience and a broader integrated ecosystem carry more weight. Choose Hetzner when self-managed price-performance is central. Choose Vultr when location and compute variety matter. Choose Lightsail when simplified AWS entry is the priority. Choose OVHcloud when its traffic and network-protection model fits the workload. None of those statements is permanent. Providers change plans, regions, policies, and product scope. Recheck high-risk assumptions before deployment and repeat the comparison when the workload, monthly bill, or recovery requirement changes. ### Sources - [Raff VM](/products/raff-vm) - [Raff Pricing](/pricing) - [Raff Service Level Agreement](/legal#service-level-agreement) - [DigitalOcean Droplets](https://www.digitalocean.com/products/droplets) - [DigitalOcean Droplet pricing](https://www.digitalocean.com/pricing/droplets) - [Hetzner Cloud server overview](https://docs.hetzner.com/cloud/servers/overview/) - [Vultr Cloud Compute documentation](https://docs.vultr.com/products/compute/instances/cloud-compute) - [Amazon Lightsail features](https://aws.amazon.com/lightsail/features/) - [OVHcloud VPS](https://www.ovhcloud.com/en/vps/) - Date verified: 2026-08-03 --- ### VPS Bandwidth and Transfer Costs Explained URL: https://rafftechnologies.com/learn/guides/vps-bandwidth-transfer-costs Description: Understand VPS bandwidth, data transfer, egress fees, port speed, unmetered traffic, and how to estimate the real monthly network cost. VPS bandwidth describes how quickly a virtual server can move data, while data transfer describes how much data moves during a billing period. **A 3 Gbps port is a speed limit, not a monthly transfer allowance; an unmetered VPS is a billing model, not a promise of infinite throughput.** For buyers, the practical task is to separate four terms that providers often place next to one another: port speed, monthly transfer, egress pricing, and acceptable-use conditions. A plan can have a fast network port but a small transfer allowance. Another can include several terabytes and charge for overage. An unmetered plan can remove per-gigabyte billing while still being subject to physical network limits and abuse controls. This guide focuses specifically on **VPS bandwidth and transfer economics**. For the complete server budget—including compute, storage, backups, licensing, and supporting services—use [Cloud Server Pricing: What Actually Drives Monthly Cost](/learn/guides/cloud-server-cost-2026). For billing cadence and commitment terms, use [VPS Pricing Models](/learn/guides/vps-pricing-models-monthly-hourly-discounts). ## VPS Bandwidth, Transfer, Egress, and Port Speed Are Different The most important buying mistake is treating these terms as interchangeable. | Term | What it measures | Typical unit | Buyer question | |---|---|---|---| | Bandwidth or throughput | How quickly data can move at a moment in time | Mbps or Gbps | How fast can the server send or receive traffic? | | Data transfer | Total volume moved over time | GB, GiB, TB, or TiB per month | How much traffic is included before another rule applies? | | Egress | Data leaving the provider, region, or service boundary | GB or GiB | Which outbound paths create charges? | | Ingress | Data entering the provider or service | GB or GiB | Is inbound traffic free, counted, or charged? | | Port speed | Maximum link rate assigned to the server interface | Mbps or Gbps | What is the network interface ceiling? | | Transfer allowance | Included monthly traffic volume | TB per month | What happens after the allowance is used? | | Unmetered bandwidth | Traffic is not normally billed by transferred volume | Plan-specific wording | Are there overage fees, caps, or acceptable-use conditions? | A provider may advertise a **1 Gbps port** and include **4 TB of transfer**. The server can potentially send traffic quickly, but after the monthly allowance is consumed, the provider may charge overage, reduce speed, or apply another policy. Another provider may advertise **unmetered bandwidth on a 3 Gbps port**. That means the customer is not normally billed by each transferred gigabyte, but the connection still has a finite rate and real-world performance still depends on routing, protocol overhead, destination capacity, congestion, and workload behavior. The safest comparison keeps speed and volume in separate columns. ## Port Speed Does Not Equal Monthly Transfer Port speed is an instantaneous rate. Monthly transfer is an accumulated quantity. The theoretical conversion is: ```text maximum transfer volume = port speed × time ÷ 8 ``` The division by eight converts bits into bytes. At continuous full utilization for a 30-day month: | Port speed | Theoretical 30-day transfer | Practical meaning | |---|---:|---| | 100 Mbps | 32.4 TB decimal | Maximum mathematical volume if the port stays saturated continuously | | 1 Gbps | 324 TB decimal | About 294.7 TiB before protocol and real-world effects | | 3 Gbps | 972 TB decimal | About 884 TiB before protocol and real-world effects | These are mathematical ceilings, not expected customer usage and not guaranteed sustained throughput to every destination. A 3 Gbps port does not mean every single connection downloads at 3 Gbps. One transfer may be limited by latency, TCP behavior, disk speed, application processing, the remote endpoint, or the route between networks. A high port speed mainly gives the workload more room for concurrent traffic and short bursts. It can help when many users, downloads, API calls, backup jobs, or services communicate at the same time. It does not remove application bottlenecks. When comparing VPS providers, ask both: 1. What is the assigned or shared port speed? 2. What transfer policy applies to traffic crossing that port? ## VPS Providers Use Four Common Transfer Models Most VPS bandwidth pricing fits one of four structures. | Model | How it works | Main benefit | Main risk | |---|---|---|---| | Fixed allowance | The plan includes a stated amount of monthly transfer | Easy to understand while usage stays below the allowance | Overage or throttling after the allowance | | Pooled allowance | Transfer allowances are combined across eligible servers in an account or region | Efficient when some VMs use less traffic than others | Pooling rules may be complex or reset monthly | | Per-GB egress | Outbound traffic is billed by destination, service, or tier | Fine-grained billing for low-transfer workloads | Traffic growth can create a large variable bill | | Unmetered | Normal traffic is not charged by transferred volume | Predictable infrastructure cost | Buyers may confuse unmetered with infinite or ignore usage policies | The same provider can use different models for different products. VM traffic, object storage, managed databases, CDNs, load balancers, and serverless functions may each have separate transfer rules. That product boundary is essential. A provider saying “free egress” for functions does not automatically mean object storage downloads are free. A VM with an included traffic allowance does not prove that cross-region database traffic follows the same allowance. ### Fixed transfer allowances A fixed allowance includes a stated amount of data transfer in the plan. The provider then defines what counts toward that amount and what happens after it is consumed. Amazon Lightsail, for example, includes a data transfer allowance with instance plans. Its current documentation explains that both inbound and outbound traffic count toward the allowance, but after the allowance is exceeded, charges apply only to eligible outbound transfer. It also documents free private-IP transfer paths in the same region under defined conditions. A fixed allowance can be predictable when the workload stays comfortably below it. It becomes risky when traffic is seasonal, download-heavy, or capable of sudden growth. ### Pooled transfer allowances DigitalOcean currently pools included outbound transfer across a team’s Droplets. Its documentation states that each Droplet plan contributes an allowance, inbound traffic is free, additional outbound public-interface transfer costs $0.01 per GiB, and VPC traffic uses the private interface rather than the public transfer pool. Pooling can be useful for accounts with several servers because an idle VM can contribute allowance to a busier one. Buyers still need to confirm which products participate, whether traffic rolls over, and how deleted or newly created resources affect the pool. ### Destination-based egress pricing Large cloud platforms may price transfer according to source region, destination, service tier, public or private path, and cross-region architecture. Google Cloud’s current network pricing, for example, separates ingress from data transfer out and applies different rates based on destination and volume tier. This model can be manageable for low-traffic internal systems. It requires more careful estimation for public downloads, APIs, media, backup replication, and multi-region services. ### Unmetered bandwidth Unmetered bandwidth means the provider does not normally calculate the bill from each gigabyte transferred under the stated product policy. It is a pricing and packaging decision. It does not mean: - infinite network capacity; - guaranteed full-port throughput to every destination; - immunity from congestion or remote-end limitations; - permission for abusive traffic; - that every product in the provider catalog has the same policy; - or that good architecture, caching, monitoring, and abuse prevention are unnecessary. The correct interpretation is: **normal eligible traffic does not create a usage-based transfer overage under the published policy.** ## Unmetered and Unlimited Should Not Be Treated as Identical Hosting pages often use “unmetered” and “unlimited” loosely. Buyers should rely on the detailed product and legal wording rather than the headline alone. Unmetered is the more precise term because it describes the billing method. Traffic is not normally metered into a per-GB invoice line. The network still has a port rate, finite infrastructure, security controls, and acceptable-use boundaries. When a provider uses “unlimited,” verify what it actually means: - Is there a fixed monthly transfer cap? - Is the port throttled after a threshold? - Are sustained-transfer workloads restricted? - Are media, proxy, VPN, backup, or file-distribution workloads treated differently? - Can the provider intervene for abuse or network harm? - Is the policy the same for IPv4 and IPv6? - Does it apply to public, private, and cross-region traffic? The strongest provider language explains both the commercial promise and the operational boundary. ## Ingress and Egress Rules Can Produce Different Bills Ingress is traffic entering the service. Egress is traffic leaving it. Many providers charge little or nothing for inbound traffic but charge for outbound traffic because outbound delivery creates a cost boundary. Typical traffic directions include: | Traffic flow | Direction from the VPS | Common treatment | |---|---|---| | User uploads a file to the VPS | Ingress | Often free, but may count toward an allowance | | VPS sends a web page or API response | Egress | Often counted or billed | | VPS downloads operating-system packages | Ingress | Often free or counted within an allowance | | VPS sends a backup to an external provider | Egress | Often counted or billed | | Database replicates to another region | Egress and cross-region | May have a separate rate | | Two servers communicate over private networking | Private east-west traffic | May be free, included, or separately priced | | Traffic crosses a public IP between nearby services | Public egress | Can be billed even when resources are in one provider | Do not assume that “same provider” means “free traffic.” The path matters. A private IP, public IP, regional boundary, NAT gateway, load balancer, CDN, or managed service can change the billing classification. For architecture-level treatment of public and private paths, use [Public vs Private Networking](/learn/guides/private-networking-public-vs-private-traffic). This guide stays focused on transfer volume and cost. ## The Workload Determines Whether Bandwidth Pricing Matters Bandwidth is a minor cost factor for some workloads and the dominant factor for others. ### Low-transfer workloads Transfer policy may have little financial impact for: - small internal dashboards; - low-traffic development servers; - administrative tools; - private automation; - lightweight websites with cached assets; - or servers used mainly for remote command-line work. For these workloads, CPU, RAM, storage, support, and recovery may matter more than the transfer model. ### High-transfer workloads Bandwidth policy becomes important for: - software and file downloads; - media delivery; - image-heavy websites; - public APIs with large responses; - customer exports; - backup replication; - large migrations; - container and package mirrors; - game-server traffic; - VPN or proxy workloads permitted by the provider; - and applications experiencing launch or campaign spikes. A low base VM price can become irrelevant when outbound transfer is the largest line item. ### Chatty architectures The application can also create transfer through internal design. A service may repeatedly move large payloads between app, database, object storage, analytics, and external APIs. The right response is not always to find cheaper egress. It may be to reduce unnecessary data movement, compress payloads, cache results, keep tightly coupled services near one another, or move large files into the right storage and delivery layer. Unmetered traffic removes one billing variable. It does not make a wasteful architecture efficient. ## Estimate Monthly VPS Transfer Before Comparing Plans A useful estimate begins with the units that actually generate traffic. ```text monthly transfer = events per month × average bytes per event ``` Then add every major traffic source: ```text estimated outbound transfer = web responses + API responses + downloads + backup replication + database or service traffic crossing billable boundaries + deployment and artifact traffic ``` Use decimal or binary units consistently. Providers may bill in GB/TB or GiB/TiB. One TB is 1,000 GB, while one TiB is 1,024 GiB. The difference becomes material at high volume. ### Website example A website serves 250,000 page views per month with an average transferred page weight of 2 MB after caching and compression. ```text 250,000 × 2 MB = 500,000 MB ≈ 500 GB decimal per month ``` The origin VPS may send less if a CDN serves most cached assets. It may send more if pages contain uncached images, downloads, API calls, or large responses. ### File-download example A product serves 20,000 downloads of a 500 MB file. ```text 20,000 × 500 MB = 10,000,000 MB ≈ 10 TB decimal ``` This workload can exceed a typical included allowance even though the VM itself needs modest CPU and RAM. ### API example An API returns 50 million responses per month with an average response size of 25 KB. ```text 50,000,000 × 25 KB ≈ 1.25 TB decimal ``` Request headers, TLS overhead, retries, logging, uploads, and upstream calls can add more traffic. ### Backup example A server sends one 300 GB full backup each week and a 20 GB incremental backup each day to an external destination. ```text 4 × 300 GB = 1,200 GB 30 × 20 GB = 600 GB estimated monthly outbound backup traffic = 1.8 TB ``` If the backup target is inside the same provider or private network, the billing treatment may differ. Verify the actual path. ### Add headroom After calculating normal usage, add headroom for: - traffic growth; - retries; - bot traffic; - deploys and package downloads; - backup re-runs; - migration windows; - seasonal peaks; - and measurement differences. A 25% to 50% planning margin is often more useful than pretending the estimate is exact. High-risk campaigns or public launches may justify a larger margin. ## The VPS Bandwidth Decision Framework Use this framework before selecting a provider or plan. | Decision area | Question | Why it matters | |---|---|---| | Port speed | What is the public network rate and is it shared? | Defines burst and concurrency headroom | | Included transfer | How much monthly traffic is included? | Establishes the base allowance | | Counting method | Does ingress, egress, or both consume the allowance? | Changes how quickly the allowance is used | | Overage | What happens after the allowance? | Determines variable cost or throttling risk | | Pooling | Are allowances pooled across servers? | Can reduce waste across multiple VMs | | Private traffic | Is VPC or same-region traffic free or included? | Affects multi-server architectures | | Cross-region traffic | Is transfer between regions billed separately? | Important for replication and disaster recovery | | Product boundary | Do VM, storage, databases, functions, and CDN use different rules? | Prevents false assumptions across services | | Billing unit | GB or GiB? TB or TiB? | Affects high-volume calculations | | Monitoring | Can usage and projected overage be viewed? | Helps prevent surprise bills | | Policy | Are fair-use, abuse, proxy, media, or sustained-use conditions documented? | Defines operational eligibility | | Workload fit | Is the app low-transfer, bursty, or continuously high-transfer? | Determines whether the network model is financially important | A practical rule is: - Choose a fixed allowance when the workload is predictable and stays comfortably below it. - Choose pooled transfer when several servers have uneven traffic and the pooling rules are clear. - Accept per-GB egress only after modelling traffic spikes and architecture paths. - Prefer unmetered transfer when predictable billing is important and the workload fits the provider’s published policy. :::cluster ## Bandwidth Claims Need Real-World Context A provider can truthfully offer a fast port while a user experiences lower application throughput. Network speed is only one component of delivery. Common limits include: - remote endpoint capacity; - round-trip latency; - packet loss; - TCP congestion control; - single-connection limits; - encryption overhead; - application worker capacity; - CPU usage; - disk read speed; - database response time; - reverse-proxy configuration; - and geographic distance. Test the workload pattern, not only a synthetic speed test. A file server needs sustained transfer testing. An API needs concurrency and latency testing. A backup job needs end-to-end throughput to the actual destination. A media workload needs origin, cache, and user-path testing. A high port rate is valuable, but it should not be used as proof that the entire application will achieve the same rate. ## CDN Use Changes Origin Traffic but Does Not Remove Transfer Planning A content delivery network can reduce traffic sent directly from the VPS by caching assets closer to users. That is useful for images, JavaScript, CSS, software files, video segments, and other cacheable objects. However, the origin still sends traffic when: - an object is not cached; - the cache expires; - content changes; - a region has a cold cache; - requests bypass the CDN; - dynamic API responses remain uncached; - or the CDN retrieves large files repeatedly. The CDN may also have its own request and transfer pricing. Compare the combined cost: ```text origin VPS cost + origin-to-CDN traffic treatment + CDN request cost + CDN delivery cost ``` Do not assume that adding a CDN makes bandwidth free. It changes where traffic is served and which pricing model applies. ## Migration and Backup Traffic Can Create Temporary Spikes Transfer estimates often focus on normal user traffic and miss operational events. A migration can involve: - copying VM disk data; - transferring database dumps; - synchronizing object files; - running repeated validation copies; - replicating databases before cutover; - and maintaining old and new environments at the same time. Backup recovery can also move large volumes in a short period. A plan that comfortably supports normal monthly traffic may still create overage during a migration or restore. Before switching providers, estimate both steady-state and transition traffic. The [cloud vendor lock-in guide](/learn/guides/cloud-vendor-lock-in-small-teams) covers the broader exit-risk decision; this guide owns only the transfer-cost component. ## Raff VM Bandwidth and Transfer Policy Raff’s current Cloud Server pricing lists **unmetered bandwidth** on visible VM plans and a **3 Gbps public network port**. The current pricing and VM pages state that normal VM traffic does not create a per-GB transfer or egress charge. Raff’s FAQ describes Cloud Servers as having no inbound or outbound transfer charges and identifies suspicious or abusive usage as an exception. For buyers, that means: - normal eligible VM traffic is not billed by transferred gigabyte; - the public interface has a stated 3 Gbps port rate; - traffic growth does not create a normal VM overage line item; - real throughput still depends on route, endpoint, protocol, and workload; - and acceptable-use and abuse controls still apply. This policy should not be generalized to every product without checking its live page. Raff Object Storage currently has a separate model with included monthly egress and a per-GB charge after that allowance. Raff Functions has its own pricing model in which requests and egress are currently free. Product-specific pricing remains controlling. Raff’s unmetered VM model is most relevant for teams running public APIs, downloads, customer-facing applications, backup transfers, and unpredictable traffic patterns where a per-GB overage would make the monthly bill harder to forecast. Use the live [Raff VM page](/products/raff-vm), [Raff pricing page](/pricing), FAQ, and current legal terms before deployment because packaging and policies can change. ## VPS Bandwidth Buyer Checklist Before purchasing a VPS, verify: - The public port speed - Whether the port is dedicated or shared - The monthly transfer allowance - Whether ingress, egress, or both count - The overage rate and billing unit - Whether traffic is pooled across servers - Whether unused allowance rolls over - Whether private-network traffic is free - Whether public-IP traffic between provider resources is counted - Cross-zone and cross-region pricing - IPv4 and IPv6 treatment - Load-balancer, NAT, CDN, database, and storage transfer rules - Usage-monitoring and alerting tools - Throttling or suspension behavior - Acceptable-use and abuse conditions - Migration and backup traffic requirements - The workload’s expected normal and peak transfer Use [How to Choose a VPS Provider](/learn/guides/how-to-choose-a-vps-provider) for the complete provider-evaluation framework. Use [Cheap VPS vs Reliable VPS](/learn/guides/cheap-vps-vs-reliable-vps) when the low headline price may be hiding reliability, recovery, or transfer trade-offs. ## Bandwidth Should Be Compared as Both Capacity and Cost VPS bandwidth has two dimensions: how quickly the server can move data and how the provider prices the total volume moved. A fast port without a suitable transfer allowance can create overage risk. A large allowance with a slow port can limit burst performance. Unmetered bandwidth can make costs more predictable, but it does not create infinite capacity or replace acceptable-use rules, monitoring, caching, and sound architecture. Estimate the workload from page views, response sizes, downloads, backups, replication, and operational traffic. Then compare port speed, transfer allowance, overage, private paths, product boundaries, and policy wording separately. Raff VM currently combines a 3 Gbps public network port with unmetered VM bandwidth and no normal per-GB inbound or outbound transfer charge. Review the live product and pricing pages before purchase, then choose the smallest safe VM whose compute, storage, and network model all fit the workload. :::cta Explore Raff VM Compare current Raff VM plans, network speed, included traffic policy, and complete monthly pricing for your workload. ::: ## Sources - [Raff Pricing](https://rafftechnologies.com/pricing) - [Raff VM](https://rafftechnologies.com/products/raff-vm) - [Raff FAQ](https://rafftechnologies.com/faq) - [Why Raff Includes Unmetered Bandwidth](https://rafftechnologies.com/blog/why-we-include-unmetered-bandwidth-on-every-plan) - [DigitalOcean Droplet Pricing and Bandwidth Billing](https://docs.digitalocean.com/products/droplets/details/pricing/) - [Amazon Lightsail Data Transfer](https://docs.aws.amazon.com/lightsail/latest/userguide/amazon-lightsail-faq-data-transfer-allowance.html) - [AWS Data Transfer Charge Definitions](https://docs.aws.amazon.com/cur/latest/userguide/cur-data-transfers-charges.html) - [Google Cloud Network Pricing](https://cloud.google.com/vpc/network-pricing) - Date verified: 2026-08-03 --- ### What Is a VPS Used For? Workloads You Can Host URL: https://rafftechnologies.com/learn/guides/what-is-a-vps-used-for Description: Learn what a VPS is used for, which workloads fit virtual servers, and when websites, apps, databases, Docker, automation, or Windows need another hosting model. A **VPS is used to run websites, applications, APIs, development environments, databases, containers, automation tools, remote desktops, and other software that needs an independent server environment**. It is most useful when a workload needs root or administrator access, predictable CPU and memory, custom software, network control, or better isolation than shared hosting provides. The important question is not whether a VPS can technically run a workload. A general-purpose server can run many things. The real question is whether the workload fits a VPS operationally: can it run safely on one server or a small number of servers, can your team manage the operating system, and can you protect the data and restore the service when something fails? This guide is a routing guide for VPS workload fit. It explains the major categories you can host, the limits to check, and which specialist Raff guide owns each detailed decision. For the broader server-selection process, start with the [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting). ## A VPS Is a General-Purpose Server Environment A virtual private server gives you an isolated operating-system environment with allocated compute, memory, storage, networking, and administrative access. Depending on the plan and operating system, you normally connect through SSH for Linux or Remote Desktop for Windows. That makes a VPS more flexible than shared hosting. You can install packages, choose a web server, run application processes, open required ports, configure users, create firewall rules, attach storage, schedule jobs, and control how the workload is deployed. The flexibility is broad, but not unlimited. Every service on the VPS shares the same finite CPU, RAM, disk, network capacity, and failure domain. A server that runs a website, database, background workers, monitoring, and backups must have enough capacity for all of them together. A useful way to think about VPS fit is: ```text VPS fit = software compatibility + sufficient resources + manageable operating responsibility + acceptable failure risk ``` If one of those parts is missing, another hosting model may be safer or simpler. ## Common Workloads You Can Host on a VPS The following table gives a high-level routing view. It is intentionally not a sizing table or a deployment tutorial. Each specialist page owns the deeper decision. | Workload | Typical VPS fit | Main requirement | Detailed owner | |---|---|---|---| | Websites and CMS platforms | Strong when control is needed | Web stack, updates, backups, traffic planning | [VPS for Web Hosting](/learn/guides/vps-for-web-hosting) | | Web applications and APIs | Strong for one-server or small multi-server apps | Runtime, reverse proxy, processes, monitoring | [VPS for Application Hosting](/learn/guides/vps-for-application-hosting) | | Development and staging | Strong | SSH access, disposable environments, cost control | [Best VPS Hosting for Developers](/learn/guides/best-vps-hosting-for-developers) | | Databases | Conditional | Fast storage, memory, access control, tested backups | [VPS for Databases](/learn/guides/vps-for-databases) | | Docker and self-hosted stacks | Strong for bounded Compose workloads | RAM, persistent volumes, private networking | [VPS for Docker Containers](/learn/guides/vps-for-docker-containers) | | Windows business software and remote desktop | Strong when Windows Server is required | Licensing, RAM per user, RDP security | [Windows VPS Hosting](/learn/guides/windows-vps-hosting-small-teams) | | Automation and background workers | Strong | Process supervision, logs, retries, resource limits | This guide provides the routing decision | | File services and private tools | Conditional | Storage growth, permissions, backup and bandwidth | Evaluate storage and recovery first | | Build, CI, and test workers | Conditional | CPU profile, temporary lifecycle, cleanup ownership | Developer and VM-sizing guides | | High-availability distributed systems | Weak as a single-VPS design | Redundancy, failover, orchestration, managed services | Consider Kubernetes or a broader cloud architecture | A VPS is strongest when the workload is understandable and bounded. The more services, users, data, and uptime requirements you add, the more important architecture and operational ownership become. ## Websites and Content Management Systems A VPS can host business websites, WordPress, PHP applications, static sites, client sites, landing pages, internal portals, and other web workloads. It becomes useful when shared hosting is too restrictive because the project needs: - root access; - a specific PHP, Node.js, Python, or database version; - custom Nginx or Apache configuration; - background jobs; - stronger resource isolation; - staging and production environments; - direct access to logs; - or more control over security and backups. A simple brochure site does not automatically need a VPS. Static hosting, shared hosting, or managed WordPress can be easier when the team does not need server access and does not want to maintain an operating system. For websites, the fit decision depends on control and responsibility rather than prestige. Use [VPS for Web Hosting](/learn/guides/vps-for-web-hosting) for the complete comparison with shared and managed hosting. Workload-specific migration decisions remain in the shared-hosting and migration cluster rather than this page. ## Applications, APIs, and SaaS Products A VPS can run application runtimes such as Node.js, Python, PHP, Go, Java, .NET, and containerized stacks. Common examples include: - SaaS MVPs; - REST or GraphQL APIs; - customer portals; - internal dashboards; - admin panels; - mobile-app backends; - background workers; - queues and scheduled jobs; - small production applications; - and staging environments. This is one of the clearest VPS use cases because an application often needs a real server environment but does not yet need a distributed platform. A typical setup may include a reverse proxy, application process, database connection, background worker, logs, firewall rules, SSL, and backups. The app can run on one VPS while the database runs locally, on another VM, or as a managed service depending on risk and scale. A VPS becomes less suitable when the application already requires automatic horizontal scaling, many distributed services, multi-region failover, managed event infrastructure, or complex platform governance. At that point, a managed app platform, Kubernetes, or hyperscaler architecture may be a better match. Use [VPS for Application Hosting](/learn/guides/vps-for-application-hosting) for the detailed application decision. This routing guide does not replace that page's ownership of app architecture, process management, and production-readiness considerations. ## Development, Testing, and Staging Environments Development workloads are often a strong VPS fit because they benefit from isolation, remote access, and easy replacement. A VPS can provide: - a clean Linux or Windows environment; - consistent package versions for a team; - remote access from different devices; - a place to test deployments; - a staging copy of an application; - a temporary migration or benchmark environment; - CI or build capacity; - and a server that can be deleted when the work is complete. The main risk is waste rather than architecture. Development and staging servers are frequently left online after the project, branch, test, or migration has ended. Every temporary environment should have an owner, a purpose, and a deletion or review date. Build and test workloads can also be CPU-intensive. A shared-CPU plan may be appropriate for occasional jobs, while sustained builds or compute-heavy tests may need dedicated CPU. The [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers) guide owns the deeper developer-workload evaluation, and VM sizing belongs in the LC02 sizing cluster. ## Databases and Stateful Services A VPS can host PostgreSQL, MySQL, MariaDB, Redis-compatible services, document databases, development databases, and small production databases. Technically, installation is straightforward. Operationally, databases require more care because they store state. A database VPS needs: - enough RAM for the working set and connections; - suitable CPU for query activity; - fast and sufficiently large storage; - restricted network access; - database-aware backups; - storage monitoring; - update ownership; - and a tested restore procedure. Running the app and database on one VPS can be practical for an MVP or small internal tool. It concentrates risk, however. If the server fails or fills its disk, both the application and database are affected. A managed database may be the better fit when the workload needs automatic failover, point-in-time recovery, managed replication, high availability, or reduced database-operations responsibility. Use [VPS for Databases](/learn/guides/vps-for-databases) for the complete self-hosted-versus-managed decision. Database engine operations and migration procedures remain in the LC07 database cluster. ## Docker Containers and Self-Hosted Software A VPS is a common host for Docker Compose stacks and self-hosted tools. The server provides CPU, memory, storage, and networking; Docker packages the services into containers. Common VPS container workloads include: - web apps and APIs; - automation tools; - dashboards; - monitoring tools; - project-management software; - private developer tools; - application plus database stacks; - reverse proxies; - caches and queues; - and small internal services. Docker makes deployment repeatable, but it does not remove infrastructure responsibility. Containers still consume RAM and CPU. Images, logs, volumes, and database files still consume disk. Persistent volumes still need backups. Internal services still need private networking and carefully controlled ports. A single VPS with Docker Compose is often enough before Kubernetes. Kubernetes becomes relevant when the workload needs multi-node scheduling, service discovery, horizontal scaling, self-healing across nodes, or platform-level deployment automation. Use [VPS for Docker Containers](/learn/guides/vps-for-docker-containers) for the specialist decision. Container fundamentals and implementation tutorials remain in LC11. ## Windows Remote Desktop and Business Applications A Windows VPS can host software that requires Windows Server, administrator access, Remote Desktop, IIS, Microsoft frameworks, or Windows-only business applications. Common examples include: - accounting and tax software; - trading platforms; - IIS-hosted applications; - remote business desktops; - legacy Windows applications; - administrative tools; - and small multi-user business environments. Windows workloads are usually more memory-sensitive than lightweight Linux services. The correct plan depends on the operating system, software stack, concurrent users, background services, and whether the workload uses a database. Licensing also matters. The compute price and Windows license may be separate. Multi-user Remote Desktop scenarios can require additional Microsoft licensing beyond a Windows Server instance license. The [Windows VPS Hosting for Small Teams](/learn/guides/windows-vps-hosting-small-teams) guide owns the broader Windows use-case decision. Detailed Windows software, versions, RDP security, and sizing belong in the Windows Server Hub rather than this LC01 routing page. ## Automation, Bots, Workers, and Scheduled Tasks A VPS can run long-lived processes that do not need a public website. Examples include: - scheduled scripts; - data imports and exports; - webhook processors; - notification services; - queue workers; - monitoring agents; - private bots; - report generation; - file-processing jobs; - and integration middleware. These workloads fit a VPS when they need a stable network identity, continuous execution, custom dependencies, or more control than a serverless runtime provides. The main questions are operational: - What restarts the process after failure or reboot? - Where do logs go? - How are secrets stored? - What prevents a runaway job from consuming the whole server? - How are failed tasks retried? - Does the job need persistent disk or external storage? - Is continuous monthly billing sensible for an intermittent task? A system service, process manager, or container can keep the workload running. A serverless function or managed job platform may be better when tasks are short, event-driven, highly intermittent, and fit the platform's execution limits. ## File Storage, Backups, and Media Delivery Need Careful Boundaries A VPS disk can store files, uploads, reports, and application assets. That does not make it the best replacement for every storage product. Use local or attached block storage when software expects a filesystem or low-latency disk. Use object storage when applications access files through an API, when capacity should grow independently, or when data should be separated from the VM lifecycle. A VPS used as a file server needs: - enough disk capacity and growth margin; - user and permission controls; - backup outside the same failure domain; - transfer and bandwidth planning; - retention rules; - and a recovery procedure. Media delivery and large public downloads can also create heavy network demand. A CDN or object-storage delivery path may be more appropriate than serving every file directly from one VPS. The [VPS Bandwidth and Transfer Costs](/learn/guides/vps-bandwidth-transfer-costs) guide owns transfer economics. Storage product selection should follow the relevant storage cluster and product documentation. ## The VPS Workload-Fit Decision Framework Use this framework before deciding that a workload belongs on a VPS. | Decision area | Strong VPS fit | Warning sign | |---|---|---| | Server control | The workload needs custom packages, ports, users, or OS settings | A standard managed runtime already supports everything required | | Workload shape | One VM or a small number of VMs can support it | It already requires many distributed services or nodes | | Demand | Traffic is stable or can be handled through planned resizing | Immediate horizontal autoscaling is essential | | Team capability | Someone owns updates, access, monitoring, and recovery | Nobody wants to administer the server | | Data | Backups and restore steps can be defined | The workload needs managed replication and automatic failover | | Cost | A clear monthly server plan helps forecasting | Usage is extremely intermittent and serverless billing is more efficient | | Availability | Planned maintenance and single-server recovery are acceptable | Near-continuous service requires redundant architecture | | Compliance | Required controls can be configured and documented | The workload needs a managed compliance scope not provided by the service | | Growth | Vertical resizing and gradual separation are practical | The system is already designed for large-scale distributed operation | A strong VPS workload is usually understandable in one diagram. The team knows which processes run, where data lives, what ports are open, how the service is backed up, and who responds when it fails. ## When a VPS Is Usually a Good Choice A VPS is usually a good fit when several of these statements are true: - You need root or administrator access. - You need to install custom software or runtimes. - Shared hosting or a managed plan is too restrictive. - The workload can run on one server or a few clearly defined servers. - Traffic and resource usage are reasonably predictable. - You prefer visible plan pricing over many usage-based line items. - Someone can manage updates, firewall rules, access, monitoring, and backups. - The service can tolerate planned maintenance or a documented restore process. - You want to start with a simple architecture and expand only after demand is proven. This does not mean a VPS is automatically the cheapest or easiest option. It means the control and simplicity are useful for the workload. ## When Another Hosting Model May Be Better Another model may be better when: - the site is simple and does not need server access; - the team wants a managed deployment platform instead of operating an OS; - the application needs automatic horizontal scaling from the beginning; - the database requires managed high availability and automatic failover; - the workload needs physical hardware or specialized devices; - usage consists of short event-driven tasks that fit serverless execution; - the system needs multi-region resilience; - or nobody owns server security and recovery. This section establishes the boundary only. The next LC01 guide, **When a VPS Is Not the Right Hosting Model**, owns the full negative-fit comparison with shared hosting, app platforms, dedicated servers, Kubernetes, and other alternatives. ## Match the VPS Size to the Whole Stack The VM must support every process running on it, not only the headline application. A workload profile should include: - operating-system overhead; - application runtime; - web server or reverse proxy; - database; - cache; - background workers; - monitoring agents; - logs; - backup jobs; - traffic peaks; - storage growth; - and maintenance headroom. A server that is comfortable during normal traffic can still run out of memory during a deployment, backup, import, or traffic spike. Start modestly, but leave enough capacity for expected pressure. Detailed RAM, CPU, storage, and bottleneck guidance belongs in LC02. Use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) rather than treating this routing guide as a sizing calculator. ## Production VPS Workloads Need an Operating Owner A VPS becomes production infrastructure when users, revenue, staff, or important data depend on it. At that point, someone must own: - operating-system updates; - software updates; - firewall and access rules; - SSH keys or RDP access; - secrets and credentials; - monitoring and alerts; - disk-capacity reviews; - backup schedules; - restore testing; - incident response; - and documentation. The provider operates the underlying infrastructure. The customer still owns the operating system and application unless a managed service explicitly says otherwise. A VPS without an operating owner is often less reliable than a simpler managed product, even when the VPS has stronger resources. ## How Raff Fits General VPS Workloads Raff VM is designed for workloads that need a clear virtual-server model: defined CPU, RAM, NVMe storage, operating-system access, network connectivity, and plan pricing. Current Raff Cloud Server pages list: - Linux and Windows VM options; - full administrative access; - NVMe storage; - unmetered VM bandwidth; - a 3 Gbps public network port; - one public IPv4 address with optional IPv6; - free private networking between supported resources; - DDoS protection; - VM resizing; - monitoring; - and backup and snapshot options. These characteristics make Raff relevant for websites, apps, APIs, development environments, Docker stacks, internal tools, automation, and Windows workloads that fit one VM or a small number of VMs. Raff is not the correct destination for every workload. A managed database can be safer when database operations are the main problem. Raff Apps can be simpler when a team wants application deployment without managing an operating system. Kubernetes becomes relevant when container orchestration is a real requirement. Object Storage is more appropriate when files should scale independently from the VM disk. That product boundary is intentional. Start with the workload, then select the Raff product—or another model—that removes the right operational burden. :::cta Explore Raff VM Compare current VM plans after defining the workload, operating responsibility, data, and recovery requirements. ::: ## VPS Workload Checklist Before deploying, confirm: - The operating system supports the required software. - The application and dependencies can run within the selected CPU and RAM. - Storage capacity includes logs, updates, uploads, and growth. - Data is backed up outside the same single failure point. - Required ports are documented and unnecessary ports remain closed. - Public and private traffic paths are understood. - Someone owns patching, monitoring, credentials, and incidents. - The workload can tolerate the chosen recovery time. - The monthly cost includes licensing, storage, backups, and likely growth. - There is a clear condition for resizing, separating services, or changing platforms. If those answers are clear, a VPS is usually a controlled infrastructure decision rather than an experiment. ## Choose a VPS by Workload, Not by Possibility A VPS can technically host a wide range of software. That flexibility is useful only when the workload also fits the server's resource limits, operating model, and failure risk. Use a VPS for websites, applications, APIs, development environments, Docker stacks, automation, remote Windows workloads, and carefully managed databases when server-level control creates real value. Use a simpler managed product when the workload does not need that control. Move to a broader architecture when one server or a small VM layout no longer meets scaling or availability requirements. The best VPS use case is not “anything that can run on Linux or Windows.” It is a workload your team can explain, operate, secure, monitor, and recover. ## Sources - [Raff VM](https://rafftechnologies.com/products/raff-vm) - [Raff Pricing](https://rafftechnologies.com/pricing) - [Raff FAQ](https://rafftechnologies.com/faq) - [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) - [VPS for Web Hosting](/learn/guides/vps-for-web-hosting) - [VPS for Application Hosting](/learn/guides/vps-for-application-hosting) - [VPS for Databases](/learn/guides/vps-for-databases) - [VPS for Docker Containers](/learn/guides/vps-for-docker-containers) - Date verified: 2026-08-03 --- ### When a VPS Is Not the Right Hosting Model URL: https://rafftechnologies.com/learn/guides/when-not-to-use-a-vps Description: Learn when not to use a VPS, the main VPS limitations, and when shared hosting, an app platform, managed database, serverless, Kubernetes, dedicated hardware, or object storage fits better. A **VPS is not the right hosting model when the workload does not need server-level control, nobody can operate the guest operating system safely, or the application already requires managed scaling, high availability, specialized hardware, or platform services that one virtual server cannot provide cleanly**. A virtual private server is flexible, but flexibility is not automatically an advantage. It transfers responsibility for operating-system updates, access control, firewall rules, application deployment, monitoring, backups, and recovery to the customer unless a managed service explicitly covers those tasks. A simpler managed platform can be safer for a standard application, while a larger architecture can be necessary for distributed or hardware-sensitive workloads. This guide explains the main VPS limitations, the warning signs that another model fits better, and how to choose between shared hosting, an app platform, managed databases, serverless services, Kubernetes, dedicated hardware, and storage products. For the positive-fit side of the decision, read [What Is a VPS Used For?](/learn/guides/what-is-a-vps-used-for). ## A VPS Is the Wrong Choice When Control Creates More Work Than Value A VPS gives the customer an independent operating system, allocated compute, memory, storage, networking, and administrative access. That control is useful when the workload needs custom packages, long-running services, specific ports, direct process control, or a server layout the team understands and can maintain. The same control becomes a disadvantage when the workload does not benefit from it. A team that only needs to deploy a conventional web application may not gain much from configuring Linux users, SSH access, Nginx, TLS, process supervision, log rotation, backups, and security updates. A business with a simple website may be safer on managed hosting. A critical database may need managed recovery and failover rather than a self-administered database process on one VM. The decision is therefore not: ```text Can this software run on a VPS? ``` Most server software can. The better question is: ```text Does operating this software on a VPS remove more constraints than it creates? ``` If the answer is no, another hosting model is probably better. ## The Main VPS Limitations VPS limitations are not only technical limits. They include the operating model, failure domain, scaling method, and responsibility boundary. | Limitation | Why it matters | Better alternative when the limitation is decisive | |---|---|---| | Guest OS administration | Someone must patch, secure, monitor, and recover the server | Managed hosting or an app platform | | Single-server failure domain | App, workers, and data may fail together | Multi-VM architecture, managed database, or Kubernetes | | Manual scaling | Vertical resizing or manual service separation may be required | App platform, autoscaling service, or Kubernetes | | Finite local storage | VM disk growth and replacement must be planned | Object storage or attached block storage | | Self-managed state | Databases and uploads need independent backup and restore planning | Managed database or object storage | | No automatic application lifecycle | Deployment, restart, rollback, and health checks need tooling | App platform | | Limited hardware control | GPUs, special accelerators, or physical isolation may be unavailable | Dedicated or specialized infrastructure | | Operational concentration | One small team may own too many infrastructure tasks | Managed services or an operations partner | | Cost during idle periods | A monthly VM continues running when the workload is inactive | Serverless or scale-to-zero platform | A VPS remains useful despite these limits when the team values control and can operate the environment. It becomes the wrong model when the limits conflict with the workload's most important requirement. ## Use a Negative-Fit Decision Framework Use this framework before selecting a VPS. | Decision area | A VPS may still fit when... | A VPS is probably the wrong model when... | |---|---|---| | Server control | Custom packages, services, ports, or OS settings are required | The app fits a standard managed runtime | | Team capability | Someone owns patching, access, monitoring, backups, and incidents | Nobody can reliably administer the server | | Availability | Planned maintenance and a restore process are acceptable | Automatic failover and redundant service are mandatory | | Scaling | Vertical resizing or planned service separation is enough | Demand requires automatic horizontal scaling | | Data | Backups and recovery can be designed and tested | Point-in-time recovery, replicas, or managed failover are required | | Workload duration | The service runs continuously | Work is short, intermittent, and event-driven | | Hardware | Standard virtual CPU, memory, and storage are sufficient | GPUs, custom devices, physical tenancy, or very large local capacity are required | | Storage | Files can live on a defined disk with clear backups | Files need independent, API-based, highly scalable storage | | Operations | Infrastructure control creates business value | Infrastructure work distracts from the product without improving it | | Architecture | One server or a few clear servers can support the system | The design already depends on many distributed services | :::cluster This framework creates a clean boundary with other Raff content. [The VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) owns the broad buying decision. [What Is a VPS Used For?](/learn/guides/what-is-a-vps-used-for) owns positive workload routing. This page owns the negative-fit signals and the alternative hosting model. ## Shared or Managed Hosting Is Better for Simple Websites A VPS is usually unnecessary for a simple brochure website, portfolio, local-business site, low-traffic blog, or standard content-management project when the site does not need custom server software. Shared or managed hosting may be better when: - the website uses a standard CMS; - traffic is modest; - no custom runtime or background service is needed; - the team does not need root access; - the provider already handles updates, certificates, and basic backups; - and nobody wants to maintain a server. Moving a simple website to a VPS can add tasks without improving the visitor experience. The team may now need to manage the operating system, web server, PHP or runtime versions, database, TLS renewal, firewall, monitoring, and recovery. A well-operated shared or managed hosting plan can be safer than a poorly maintained VPS. More control only helps when the website needs that control and someone can use it responsibly. The migration decision is owned by [When Should a Small Business Move from Shared Hosting to a VPS?](/learn/guides/shared-hosting-vs-vps-small-business). This guide establishes the opposite boundary: stay on the simpler model while the website remains simple and the current environment is not limiting the business. ## An App Platform Is Better When the Team Wants to Deploy Code, Not Manage Servers An app platform can be the better choice when the workload fits a supported runtime or Dockerfile and the team wants the platform to handle the deployment lifecycle. A managed application platform can reduce work around: - builds and deployments; - HTTPS and domain routing; - process restarts; - environment variables; - deployment logs; - preview environments; - workers and scheduled jobs; - application-level scaling; - and connections to managed data services. Choose an app platform instead of a VPS when: - the app uses a conventional runtime; - operating-system access is not important; - the team values Git-based deployment more than server customization; - platform-managed restarts and health checks are useful; - preview environments improve the development workflow; - and the cost of managed convenience is justified by saved engineering time. A VPS becomes attractive again when the application needs unsupported system packages, unusual network behavior, direct operating-system debugging, custom daemons, a nonstandard server layout, or a cost structure that is easier to manage on one or a few VMs. The full control-versus-convenience comparison belongs to [Cloud VM vs App Platform](/learn/guides/cloud-vm-vs-app-platform-startups). Raff Apps is the Raff product path for teams that want deployment automation without managing the guest operating system, while Raff VM remains the path for teams that need the whole server. ## A Managed Database Is Better When Data Operations Are the Main Risk A database can run on a VPS, but the ability to install PostgreSQL or MySQL is not the same as having a production-ready database service. A self-managed database on a VPS requires ownership of: - database updates; - access rules; - memory and connection tuning; - storage growth; - backup schedules; - backup monitoring; - restore testing; - replication, if used; - failover procedures; - and incident response. A managed database is often better when: - the data is difficult or impossible to recreate; - automatic backups and point-in-time recovery are important; - the workload requires replicas or automatic failover; - the team lacks database-administration experience; - application and database scaling should be independent; - or database operations would consume too much product-engineering time. Running the app and database on the same VPS may be reasonable for a prototype, development environment, or small internal tool. It is a weaker fit when one VM becomes the only copy of important state and the recovery plan has not been tested. Use [VPS for Databases](/learn/guides/vps-for-databases) for the full self-hosted-versus-managed decision. Raff Managed Databases is the product path when the team wants the database lifecycle handled separately from the VM. ## Serverless Is Better for Short, Intermittent, Event-Driven Work A VPS is billed and operated as a continuously available server. That can be inefficient when the workload runs only for a few seconds after an event and remains idle most of the time. Serverless functions or managed jobs may be better for: - webhook handlers; - scheduled lightweight tasks; - small data transformations; - notification triggers; - image or document operations that fit execution limits; - API endpoints with highly intermittent demand; - and event-driven integrations. Choose a serverless model when: - the workload can start and stop independently; - execution time and resource limits are acceptable; - local persistent disk is not required; - the function can use external data services; - and scale-to-zero economics matter. A VPS remains better when the process must stay alive, maintains local state, needs a stable long-running connection, requires custom system software, or regularly exceeds function execution limits. The key economic question is not simply the per-request price. It is whether the team needs to operate an always-on server for work that is rarely active. ## Kubernetes Is Better When Container Orchestration Is Already a Requirement Docker on one VPS is a practical model for a bounded application stack. Kubernetes becomes relevant when the team needs orchestration across multiple nodes rather than container packaging on one machine. A single VPS is probably the wrong long-term model when the system requires: - multi-node scheduling; - horizontal pod scaling; - service discovery across a cluster; - rolling deployments across many instances; - self-healing after node failure; - workload placement rules; - cluster-wide secrets and configuration; - standardized ingress and internal service networking; - or a platform shared by multiple application teams. Kubernetes introduces its own complexity. It should not be selected only because the application uses containers. A Docker Compose stack on a VPS can remain simpler and cheaper when one server is enough. Use Kubernetes when orchestration solves a real operational problem. Raff Kubernetes is the Raff path when standard cluster behavior, managed control-plane operations, and multiple worker nodes are justified. [VPS for Docker Containers](/learn/guides/vps-for-docker-containers) owns the Docker-versus-Kubernetes boundary in detail. ## Dedicated Hardware Is Better for Physical or Hardware-Specific Requirements A VPS cannot provide every hardware configuration. Dedicated or specialized infrastructure may be better when the workload needs: - physical single tenancy required by policy or contract; - a specific processor, accelerator, GPU, or attached device; - very large, stable memory capacity; - a large local-storage layout; - customer-controlled virtualization; - sustained use of most of a physical machine; - or hardware-level licensing requirements. Traffic growth alone is not a reason to leave VPS infrastructure. A larger VM, dedicated-vCPU VM, multiple VMs, load balancing, or service separation may solve the problem without introducing physical-server operations. The upgrade should follow a measured constraint. Use [VPS vs Dedicated Server](/learn/guides/vps-vs-dedicated-server) for the complete cost, performance, isolation, and migration comparison. ## Object Storage Is Better Than a VPS Disk for Scalable Files A VPS disk is appropriate for the operating system, application files, local caches, and data that software must access through a filesystem. It is not always the best home for growing uploads, backups, media libraries, exports, or objects shared by several application instances. Object storage is usually better when: - files should scale independently from the VM; - applications access data through an API; - multiple app instances need the same objects; - the VM should be replaceable without moving a large file library; - lifecycle and retention rules are useful; - or public media delivery should not depend on one server disk. Keeping all files on the VPS creates coupling. Resizing, replacing, or migrating the VM now includes the file library. A full disk can affect both application availability and data writes. Attached block storage may be better when the software requires a filesystem but capacity should be separate from the boot disk. Object Storage is better when the data model is object-based and independent scaling matters. Bandwidth and transfer economics remain owned by [VPS Bandwidth and Transfer Costs](/learn/guides/vps-bandwidth-transfer-costs). ## A Multi-VM Architecture Is Better When One Failure Domain Is Not Acceptable One VPS creates one obvious failure domain. If the application, database, uploads, and workers all run there, a single server event can affect the entire system. A single VPS may be acceptable when: - the workload is early-stage; - short downtime can be tolerated; - backups are tested; - recovery is documented; - and the simplicity is more valuable than redundancy. A multi-VM or managed-service design becomes more appropriate when: - application and database pressure interfere with each other; - maintenance should not stop every service; - independent scaling is required; - a database failure must not destroy the application host; - several app instances are needed; - or uptime requirements exceed a single-server recovery model. Adding servers is not automatically high availability. The application must handle shared state, uploads, sessions, database connections, health checks, and traffic routing correctly. Architecture should become more complex only when the reliability requirement justifies it. ## A VPS Is Wrong When Nobody Owns Server Operations The most common negative-fit signal is not CPU, RAM, or storage. It is missing ownership. A production VPS needs an owner for: - operating-system and package updates; - SSH or RDP access; - firewall rules; - application deployment; - logs and monitoring; - disk-capacity alerts; - certificates; - secrets; - backups; - restore testing; - and incident response. Installing software successfully does not prove the team can operate it safely for months or years. When nobody owns these tasks, the alternatives are: - use a managed hosting or app platform; - use a managed database for state; - purchase a clearly scoped managed VPS service; - hire or contract an operator; - or work with an MSP that accepts the operational responsibility. [Managed vs Unmanaged VPS](/learn/guides/managed-vs-unmanaged-vps) explains how to evaluate that responsibility boundary. The term managed should always be supported by a written scope. ## A VPS Is Wrong When Compliance Depends on Controls the Service Does Not Provide A VPS gives the customer technical control, but technical control alone does not establish compliance. A workload may require documented controls for access, logging, patching, encryption, retention, incident response, data location, evidence, vendor management, or physical isolation. Some controls can be implemented by the customer inside a VPS. Others depend on the provider, product, architecture, and contractual scope. Do not select a VPS and assume the operating model automatically satisfies a compliance requirement. Before deployment: - identify the required controls; - map each control to the provider or customer; - verify the evidence that must exist; - confirm whether physical or logical isolation is required; - define backup and retention responsibilities; - and reject the model when an essential control cannot be verified. A managed or specialized service may be the better fit when it provides the required operating evidence and responsibility scope. Dedicated infrastructure may be required when physical tenancy is explicit. ## A VPS Is Wrong When Idle Infrastructure Has No Business Value A continuously running VPS can be inexpensive and predictable, but it still consumes budget while idle. That is acceptable for a website, API, database, worker, or internal service that must remain available. It is less efficient for a task that runs briefly once per day, once per week, or only after rare events. Ask: - Must this process remain available continuously? - Does it need a stable IP or long-lived connection? - Does it require local persistent state? - Can it start from an event and stop afterward? - Would scale-to-zero reduce cost without creating platform constraints? If the workload is short and stateless, serverless or a managed job system may be better. If the workload is continuous, custom, or stateful, the VPS may still be the simpler model. ## Do Not Replace a VPS Only Because It Needs Resizing Outgrowing the first VM plan does not prove the VPS model is wrong. Before changing platforms, determine whether the real issue is: - insufficient RAM; - insufficient CPU; - shared-CPU variability; - disk capacity; - storage latency; - network throughput; - database configuration; - application inefficiency; - or a true architecture limitation. A larger VM, dedicated CPU, attached storage, managed database, or service separation may solve the problem while preserving the overall VM model. The VPS model is wrong only when the workload's operating requirements no longer fit a small number of virtual servers or when another service removes a more important burden. ## Choose the Alternative by the Problem You Need to Remove | Primary problem | Better first option | Why | |---|---|---| | Simple website with no custom stack | Shared or managed hosting | Lower operational responsibility | | Standard application deployment | App platform | Managed build, deploy, routing, and process lifecycle | | Database reliability and recovery | Managed database | Separates state and database operations from the VM | | Short event-driven tasks | Serverless functions or managed jobs | No need for an always-on server | | Multi-node container orchestration | Kubernetes | Cluster scheduling and application orchestration | | Physical isolation or specialized hardware | Dedicated infrastructure | Whole-machine or device-level control | | Large scalable file library | Object storage | Data scales independently from the VM | | Filesystem capacity beyond boot disk | Block storage | Separate persistent disk capacity | | Missing server-administration skill | Managed service, MSP, or operations partner | Gives production tasks an owner | | Moderate VM resource pressure | Larger or dedicated-CPU VPS | Fixes capacity without unnecessary migration | This table is not a maturity ladder. An app platform is not less serious than a VPS, and Kubernetes is not automatically better than one VM. Each model removes a different category of work. ## How Raff Products Fit the Negative-Fit Decision Raff provides more than one infrastructure model, so the correct Raff answer is not always Raff VM. Use **Raff VM** when the workload needs the operating system, custom software, direct process control, and a clear server model. Use **Raff Apps** when the team wants to deploy application services without administering the guest operating system. Use **Raff Managed Databases** when database operations, backups, recovery, or independent data scaling are the main concern. Use **Raff Kubernetes** when multi-node container orchestration is a real requirement. Use **Raff Object Storage** when files should scale and persist independently from the VM lifecycle. The product should follow the workload. Forcing every project onto a VPS would transfer responsibility even when another Raff service removes the right operational burden. ## Final VPS Negative-Fit Checklist A VPS is probably not the right hosting model when several of these statements are true: - The workload does not need root or administrator access. - Nobody can own patching, firewall rules, monitoring, backups, and incidents. - The app fits a managed deployment platform without meaningful constraints. - The database needs managed replicas, point-in-time recovery, or automatic failover. - The workload is short, intermittent, and event-driven. - The system already requires multi-node orchestration and automatic horizontal scaling. - Physical single tenancy or specialized hardware is mandatory. - Files should scale independently from the server. - One VM is an unacceptable failure domain. - The team is choosing VPS only because it sounds more professional. - The operational work would distract from the product without providing useful control. A VPS may still be correct when only one item applies. The decision should follow the most important requirement, not the longest list of features. ## Choose the Smallest Operating Model That Meets the Requirement A VPS is a strong tool for workloads that need server-level control and can be operated safely on one VM or a small number of VMs. It is the wrong choice when that control creates unnecessary administration, when the data needs a managed recovery model, when scaling already requires orchestration, or when hardware and compliance requirements exceed a standard virtual server. Choose shared or managed hosting for simple websites. Choose an app platform when code deployment matters more than operating-system access. Choose managed databases when data operations are the risk. Choose serverless for short event-driven work, Kubernetes for real multi-node orchestration, dedicated infrastructure for physical requirements, and object storage for independently scalable files. The best hosting model is not the one with the most control. It is the smallest model that meets the workload, reliability, security, recovery, and team-capability requirements without creating unnecessary operational burden. :::cta Explore Raff VM Use a full-control VM only when your workload benefits from server-level access and your team can own the operating responsibility. ::: ## Sources - [Raff VM](https://rafftechnologies.com/products/raff-vm) - [Raff Apps](https://rafftechnologies.com/products/app-platform) - [Raff Managed Databases](https://rafftechnologies.com/products/managed-databases) - [Raff Kubernetes](https://rafftechnologies.com/products/kubernetes) - [Raff Object Storage](https://rafftechnologies.com/products/object-storage) - [VPS Hosting Decision Guide](/learn/guides/virtual-private-server-hosting) - [What Is a VPS Used For?](/learn/guides/what-is-a-vps-used-for) - [Cloud VM vs App Platform](/learn/guides/cloud-vm-vs-app-platform-startups) - [VPS vs Dedicated Server](/learn/guides/vps-vs-dedicated-server) - [Managed vs Unmanaged VPS](/learn/guides/managed-vs-unmanaged-vps) - Date verified: 2026-08-03 --- ### VPS Free Trial vs Money-Back Guarantee: What Buyers Should Verify URL: https://rafftechnologies.com/learn/guides/vps-free-trial-vs-money-back-guarantee Description: Compare VPS free trials and money-back guarantees, including refund terms, trial credits, cancellation rules, and what buyers should verify before purchase. A VPS free trial and a money-back guarantee are not the same offer. A free trial lets you use a service before paying, usually with limits on time, credits, resources, or features. A money-back guarantee means you pay first and can request a refund under defined conditions. Before choosing a VPS provider, verify the exact terms behind the offer. A "free VPS trial" may be limited by promotional credits, account verification requirements, resource caps, or acceptable-use rules. A money-back guarantee may have a fixed period, first-purchase restriction, excluded products, or refund-method limitations. This guide explains how to compare VPS trial and refund policies before deployment. For total VPS pricing decisions, see [Cloud Server Pricing: What Actually Drives Monthly Cost](/learn/guides/cloud-server-cost-2026). For provider evaluation, see [How to Choose a VPS Provider](/learn/guides/how-to-choose-a-vps-provider). ## Free Trial and Money-Back Guarantee Solve Different Problems The terms sound similar because both reduce purchase risk, but they work differently. | Offer type | How it works | Main buyer question | |---|---|---| | Free trial | Use a service without normal payment during a defined period | What can I test before paying? | | Trial credits | Receive a limited balance for testing | What happens when credits expire? | | Money-back guarantee | Pay first, request refund within conditions | Can I recover my payment if the service is not suitable? | | Refund policy | General rules for cancellations and returns | Which purchases qualify? | A free trial focuses on experimentation. A money-back guarantee focuses on reversing a purchase decision. Neither automatically means the provider is easier or safer. The important details are hidden in the conditions. ## What to Verify Before Choosing a VPS Trial A VPS trial should answer practical deployment questions. Check: - Is a credit card required? - Is identity verification required? - How long does the trial last? - Which regions are available? - Which VM sizes can be created? - Are Windows licenses included? - Is bandwidth limited? - Are snapshots and backups available? - Can production traffic run during the trial? - What happens when the trial expires? - Are unused credits refundable? A trial that only allows a small test instance may not reveal how the provider performs for the actual workload. For example, a developer evaluating a VPS for an API should test deployment, networking, backups, monitoring, and migration—not only whether a small VM launches successfully. ## What to Verify in a Money-Back Guarantee A refund guarantee should be read like a contract, not a marketing headline. Verify: | Question | Why it matters | |---|---| | When does the refund period start? | Activation date and payment date may differ | | Does it apply to the first purchase only? | Renewals and upgrades may be excluded | | Is every product included? | Domains, licenses, storage, or add-ons may differ | | Is usage deducted? | Some providers calculate consumed resources separately | | Is the refund automatic? | Many require a support request | | How is the refund delivered? | Card refund and account credit are different | | How long does processing take? | Bank processing may add delay | A clear refund policy reduces uncertainty before production use. ## Raff VPS Refund Policy Example Raff does not offer a free VPS trial. Instead, Raff provides a 14-day money-back guarantee for the first purchase on an account. The current policy states: - The guarantee applies only to the first purchase per account. - A refund request can be made within 14 days of purchase. - No reason is required. - Refunds can be issued to the original payment method or Raff account balance. - Renewals, later purchases, and plan upgrades are not covered by the first-purchase guarantee. - After the 14-day period, unused subscription value is handled as Raff account credit rather than cash/card refund. - PAYG usage charges are based on actual consumption and are non-refundable. The controlling policy remains the live [Raff Cancellation and Refund Policy](/legal). This structure is designed around reducing initial purchase risk while keeping subscription billing predictable. ## Trial Credits Are Not the Same as Refundable Money Many cloud providers use promotional credits instead of traditional trials. Credits usually have different rules: - They may expire after a fixed period. - They may apply only to selected products. - They may not cover taxes, bandwidth, or marketplace items. - They may not be convertible to cash. - They may require payment verification. A buyer should calculate the real test environment cost: ```text Trial evaluation cost = VM resources + storage + backups + bandwidth + licenses + time required for testing ``` A free credit amount alone does not show whether a provider is economical for production. ## Questions to Ask Before Starting a VPS Use this checklist: ### Account and payment - Is payment verification required? - Is a credit card required? - Can the payment method be removed? - Are there verification charges? ### Refund conditions - Is the refund available once or repeatedly? - Are upgrades included? - Are renewals included? - Are add-ons refundable? - Is the refund sent to the card or account credit? ### Technical testing - Can I test the required region? - Can I create the required VM size? - Can I test networking? - Can I test backups and restore? - Can I export my data? ### Production transition - What happens when the trial ends? - What is the normal monthly cost afterward? - Are promotional prices temporary? - What are cancellation requirements? ## Common Buyer Mistakes ### Choosing a provider only because of a free offer A free period does not prove production suitability. Evaluate: - performance consistency; - support boundaries; - backup process; - network policy; - pricing after the promotion; - migration options. ### Confusing credits with discounts A $100 credit does not mean a $100 discount on every production workload. It may only delay the first invoice. ### Testing only deployment speed A VPS that launches quickly may still have unsuitable pricing, support, recovery, or performance characteristics. ### Ignoring post-trial pricing Always calculate the normal monthly cost after the promotion ends. ## Trial and Refund Policy Decision Framework | Situation | What to prioritize | |---|---| | Testing a new provider | Trial access or clear refund window | | Production migration | Refund terms, backups, export options | | Comparing multiple providers | Equivalent test environments | | Small business deployment | Support clarity and cancellation terms | | SaaS launch | Performance testing and long-term cost | | Temporary development server | Billing flexibility | The best offer is not necessarily the one with the longest trial. It is the one that lets you verify the workload assumptions with the lowest risk. ## Compare Provider Policies, Not Marketing Labels Different providers structure risk differently. Some providers offer promotional credits. Others offer refunds after payment. Others provide limited cancellation windows or account credits. When comparing providers, record: - trial type; - duration; - payment requirements; - refund window; - refund method; - excluded services; - normal pricing afterward; - cancellation process. A simple comparison table prevents surprises. ## Choose Based on Long-Term Fit A VPS trial or refund policy is only the first step in provider evaluation. The final decision should include: - workload fit; - performance evidence; - complete monthly cost; - support model; - backup and recovery options; - network policy; - migration path. A refund guarantee reduces initial risk. It does not replace technical evaluation. For teams evaluating Raff VM, review the current [Raff VM product page](/products/raff-vm) and pricing after confirming the workload requirements. :::cta Explore Raff VM Review Raff VM plans, resources, bandwidth policy, and pricing before deploying your workload. ::: ## Sources - [Raff Cancellation and Refund Policy](/legal) - [Raff Terms of Service](/legal) - [Raff VM](/products/raff-vm) - [Cloud Server Pricing](/learn/guides/cloud-server-cost-2026) - [How to Choose a VPS Provider](/learn/guides/how-to-choose-a-vps-provider) - Date verified: 2026-08-03 --- ### Application Observability for Small Teams: Metrics, Logs, and Traces URL: https://rafftechnologies.com/learn/guides/observability-small-teams-metrics-logs-traces Description: Build application observability for a small team with practical metrics, structured logs, distributed tracing, SLI, SLO, alerting, and telemetry cost decisions. Application observability helps a small team answer four production questions: **Is the service working for users, what changed, where is the failure, and who owns the next action?** Start with user-facing metrics and infrastructure health, add structured logs with shared context, and introduce distributed tracing when requests cross enough services that logs alone no longer explain the path. The goal is not maximum telemetry. It is faster detection, diagnosis, and recovery with a system the team can afford and maintain. ## Observability is a decision system, not a dashboard collection Monitoring checks conditions you already know to watch. Observability gives the team enough telemetry to investigate both expected and unfamiliar failures. For a small application, observability should support a practical operating loop: 1. Detect user impact. 2. Identify the affected service or workflow. 3. Correlate the issue with a deployment, dependency, or resource constraint. 4. Assign an owner and take action. 5. Confirm recovery. 6. Improve the signal that was missing. A dashboard that nobody checks, a log stream nobody can search, or an alert with no owner does not improve reliability. ## Metrics, logs, and traces answer different questions OpenTelemetry describes metrics, logs, and traces as separate telemetry signals. They become most useful when they share consistent service, environment, deployment, request, and trace context. | Signal | Best question | Small-team role | |---|---|---| | Metrics | Is user experience or capacity changing? | Detection, trends, alerting, SLI measurement | | Logs | What happened inside this component? | Error context, events, deployments, jobs, security evidence | | Traces | Where did one request spend time or fail? | Cross-service latency and dependency diagnosis | The signals are complementary. A latency metric shows that a checkout flow slowed down. Logs may show database timeouts. A trace can reveal that most of the request duration came from one external dependency. ## Monitoring and observability are related but not identical Monitoring is effective for known failure modes: - the service is unavailable, - error rate is above a threshold, - disk space is running out, - a queue is growing, - a scheduled job did not complete, - backup execution failed. Observability supports deeper questions: - Why did p95 latency rise only for one endpoint? - Which deployment changed error behavior? - Is the database slow, or is the application waiting on an external API? - Which customer workflow is affected? - Where did a request cross a slow service boundary? Small teams need both. Monitoring should create a clear signal that something matters. Observability should shorten the path from that signal to a defensible explanation. ## Start with user-visible service signals Infrastructure metrics matter, but users experience services rather than CPU graphs. Google’s Site Reliability Engineering guidance recommends four core service signals: latency, traffic, errors, and saturation. Use them as the first application observability layer: | Signal | What to measure | What it tells you | |---|---|---| | Latency | p50, p95, and p99 response or job duration | Whether normal and slow experiences are degrading | | Traffic | Requests, jobs, transactions, or active sessions | How much demand the system is serving | | Errors | Failed requests, failed jobs, rejected operations | Whether users are receiving correct outcomes | | Saturation | CPU, memory, queue depth, connections, disk capacity | How close the system is to a practical limit | Do not rely only on averages. A healthy average can hide slow tail latency, short periods of saturation, or failures isolated to one route. ## Add infrastructure metrics that explain capacity For each production VM, database, cache, queue, and worker, collect the metrics that reveal waiting and resource pressure. A useful baseline includes: - CPU utilization and load, - memory usage and swap activity, - free disk space and growth rate, - disk latency and I/O wait, - network throughput and errors, - process health and restart count, - database connections and query latency, - queue depth, retry count, and job age, - backup status where recovery depends on it. Infrastructure metrics explain capacity, but they should be interpreted beside application behavior. High CPU is not automatically an incident if latency and errors remain healthy. Low CPU does not prove that the service is healthy if the workload is waiting on storage, locks, or an external API. For bottleneck diagnosis, see [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). ## Structured logs should preserve searchable context Logs are valuable when the team can filter and correlate them during an incident. Prefer structured records over free-form sentences. Useful fields include: - timestamp, - severity, - service and component, - environment, - deployment version, - request ID and trace ID, - route, job, or workflow name, - result or status code, - duration, - dependency name, - retry count, - safe tenant or account identifier where appropriate. Standardize field names across services. OpenTelemetry semantic conventions provide a common vocabulary for telemetry attributes, reducing the need to remember that one service uses `service`, another uses `app_name`, and a third uses `component` for the same concept. Do not log passwords, private keys, session cookies, access tokens, payment data, or unnecessary personal data. Logs are copied, indexed, retained, and accessed by more systems than developers often expect. Application logs and audit logs also serve different purposes. Application logs explain software behavior; audit logs preserve accountable actions. See [Application Logs vs Audit Logs](/learn/guides/application-logs-vs-audit-logs-developers). ## Correlation IDs connect the signals A correlation ID is one of the highest-value observability improvements a small team can make. Generate or accept a request ID at the edge, then propagate it through the application, workers, internal APIs, and external-call metadata where possible. Include the same ID in logs and traces. This allows an operator to move from: - an error-rate alert, - to one failed request, - to the relevant application logs, - to the background job or downstream service involved. When distributed tracing is not yet justified, consistent request and job IDs can still provide much of the investigative value. ## Tracing becomes useful when request paths become distributed Distributed tracing follows one request across spans created by multiple components. It becomes valuable when a user action crosses several services, queues, workers, databases, or external APIs. Add tracing when: - logs show fragments but not the complete request path, - one action crosses several services or VMs, - p95 or p99 latency is difficult to attribute, - asynchronous work hides where a failure began, - retries and fallbacks obscure the original problem, - different teams own different parts of the request. A monolith on one VM may not need full distributed tracing. A multi-service application may need it early. Architecture complexity, not fashion, should determine the timing. Trace collection can create cost and storage pressure. OpenTelemetry recommends sampling when trace volume is high and complete collection is unnecessary. Preserve representative healthy traffic while prioritizing errors, slow requests, newly deployed services, and low-volume critical workflows. ## Define service level indicators before adding more alerts A service level indicator, or SLI, measures behavior users care about. Examples include successful request ratio, checkout completion, API latency, job completion time, or file-processing success. A service level objective, or SLO, sets the target for that indicator over a period. Small teams do not need a complex SRE program to benefit from this approach. Start with one or two critical workflows: | Workflow | Possible SLI | Example decision use | |---|---|---| | Public API | Successful requests under a latency threshold | Decide whether user impact warrants escalation | | Checkout | Completed transactions divided by valid attempts | Separate business failure from server uptime | | Background export | Jobs completed within an expected window | Detect growing queue delay before users complain | | Authentication | Successful valid logins | Detect identity or dependency failures | An SLO helps distinguish normal variation from reliability risk. It also prevents teams from paging on every CPU spike when users are unaffected. ## Alerts must be actionable and owned Prometheus guidance recommends keeping alerts simple, focusing paging on user-visible symptoms, and avoiding pages where no human action is required. Every urgent alert should include: - what user-facing condition is failing, - the affected service or workflow, - severity, - a responsible owner or rotation, - a dashboard or query link, - the first diagnostic steps, - a way to confirm recovery. Use different destinations for different urgency levels: | Signal | Destination | |---|---| | Immediate user impact requiring action | Page or urgent incident channel | | Capacity risk that needs planned intervention | Ticket or operations queue | | Diagnostic cause without current impact | Dashboard, report, or non-urgent notification | | Informational deployment or configuration event | Timeline and searchable logs | Avoid duplicate paging at every layer. If an application latency alert already captures the user impact, a separate page for every downstream CPU or database signal may create noise rather than clarity. ## Deployment markers shorten investigations Many incidents follow a change. Record deployment, configuration, migration, and infrastructure events on the same timeline as service metrics. At minimum, preserve: - deployment version, - start and completion time, - environment, - actor or automation identity, - result, - rollback event if used. This allows the team to answer, “What changed before the graph moved?” without reconstructing the timeline from several tools. ## Choose retention based on investigative value Observability cost grows through log volume, trace volume, metric cardinality, retention, and collector overhead. Use different retention policies for different data: - keep high-resolution operational telemetry long enough for normal incident discovery, - retain aggregated metrics longer for trends and capacity planning, - retain security and audit evidence according to business and legal requirements, - shorten retention for noisy debug data, - preserve incident-specific evidence when a serious event occurs. Watch metric cardinality. OpenTelemetry notes that high-cardinality attributes such as raw user IDs or unbounded URL values can create large numbers of unique series and increase memory and storage cost. Use controlled route names, service names, environments, status groups, and other bounded attributes for metrics. Keep request-specific detail in logs and traces. ## A practical maturity model for small teams ### Stage 1: Know whether the service is alive Implement external uptime checks, basic server metrics, application error reporting, and disk-capacity alerts. ### Stage 2: Understand user-facing behavior Add latency, traffic, error, and saturation dashboards. Record deployment markers and structured application logs. ### Stage 3: Make incidents searchable Standardize request IDs, service names, environments, deployment versions, and dependency fields. Write short runbooks for the most important alerts. ### Stage 4: Measure reliability Define SLIs for critical workflows and set initial SLOs. Review whether alerts represent real user impact. ### Stage 5: Trace distributed paths Instrument critical cross-service requests, propagate trace context, and introduce a deliberate sampling policy. ### Stage 6: Improve after incidents After each material incident, ask: - Did detection happen early enough? - Did the alert identify user impact? - Did the right person receive it? - Could logs and traces identify the failing boundary? - Was a deployment or configuration change visible? - Which missing signal prolonged recovery? Update instrumentation and runbooks based on the answer. ## The observability decision framework Use this table before adding another tool or signal. | Situation | Best next decision | |---|---| | One VM, one application, few incidents | Metrics, structured logs, external uptime | | Users report slowness but infrastructure looks normal | Add endpoint latency, dependency timing, and correlation IDs | | Background jobs fail silently | Add queue age, retries, failures, and job IDs | | Several services share one workflow | Add trace context and targeted distributed tracing | | Alert volume is high | Remove non-actionable alerts and page on symptoms | | Telemetry cost is growing | Reduce debug volume, control cardinality, adjust retention and sampling | | Incidents repeat | Add the missing signal and update the runbook after review | | Team cannot agree what “healthy” means | Define SLIs and initial SLOs for critical workflows | The correct observability stack is the smallest one that reliably supports detection, diagnosis, ownership, and recovery. ## How this applies on Raff A Raff VM can host the application, metrics collector, log forwarder, or an early single-node observability stack. As the architecture grows, application servers, workers, databases, and telemetry components can be separated according to measured resource and reliability needs. A practical Raff path is: - start with server and application metrics on the first VM, - add structured logs and external uptime monitoring, - use [Raff VPC](/products/vpc) for private communication between internal services, - separate telemetry storage when it competes with the production workload, - resize or split services when observability identifies a persistent bottleneck, - verify current VM capabilities on the live [Raff VM page](/products/raff-vm). Do not place the observability backend on the same failure boundary as every system it is supposed to monitor without considering the consequence. External checks and separated storage can still provide evidence when the application VM is unavailable. ## Application observability checklist Before calling the system observable, confirm: - Critical user workflows have latency and error signals. - Traffic and saturation are visible. - Alerts have owners and documented actions. - Deployments appear on the operational timeline. - Logs are structured and searchable. - Request or job IDs propagate across important workflows. - Sensitive data is excluded from telemetry. - Metric labels have controlled cardinality. - Retention and trace sampling are intentional. - External monitoring can detect failure of the main environment. - Incident reviews lead to instrumentation improvements. :::cluster ## Conclusion Application observability for a small team should begin with the user experience, not with a tool catalog. Measure latency, traffic, errors, and saturation. Add structured logs that preserve service and request context. Define an owner and action for every urgent alert. Introduce SLIs and SLOs when the team needs a shared definition of reliability. Add distributed tracing when requests cross enough boundaries that metrics and logs no longer explain the complete path. The strongest observability system is not the one that stores the most telemetry. It is the one that helps the team detect meaningful impact, find the failing boundary, restore service, and prevent the same incident from taking as long next time. :::cta Explore Raff VM Choose a cloud VM foundation for your application and observability workload. ::: ## Sources - [OpenTelemetry: Signals](https://opentelemetry.io/docs/concepts/signals/) - [OpenTelemetry: Observability Primer](https://opentelemetry.io/docs/concepts/observability-primer/) - [OpenTelemetry: Sampling](https://opentelemetry.io/docs/concepts/sampling/) - [OpenTelemetry: Semantic Conventions](https://opentelemetry.io/docs/concepts/semantic-conventions/) - [Google SRE: Monitoring Distributed Systems](https://sre.google/sre-book/monitoring-distributed-systems/) - [Prometheus: Alerting Practices](https://prometheus.io/docs/practices/alerting/) - [Raff VM](/products/raff-vm) - [Raff VPC](/products/vpc) - Date verified: 2026-08-03 --- ### Application Logs vs Audit Logs: What to Store and Why URL: https://rafftechnologies.com/learn/guides/application-logs-vs-audit-logs-developers Description: Compare application logs and audit logs, including event fields, integrity, retention, sensitive-data controls, storage, incident response, and customer-facing audit history. Application logs explain how software behaved; audit logs prove which actor performed an important action. **Use application logs for errors, requests, retries, jobs, latency, and dependency failures. Use audit logs for authentication, access changes, administrative actions, data exports, billing changes, security settings, and other events that require accountability.** Some actions should create both records, but the fields, access rules, retention, and integrity requirements should remain different. The decision is not whether to log more. It is which future question each record must answer. ## Application logs and audit logs serve different decisions Application logs support engineering and operations. Audit logs support accountability, security review, customer questions, and investigations. | Log type | Primary question | Main reader | Typical examples | |---|---|---|---| | Application log | What happened inside the software? | Developer or operator | Exception, timeout, retry, slow query, failed job | | Audit log | Who did what, to which resource, and with what result? | Security, admin, customer, reviewer | Login, role change, export, key creation, admin action | | Access log | Which client reached which endpoint? | Operator or security reviewer | Method, route, status, source, user agent | | Security event | Does this behavior indicate abuse or compromise? | Security or incident owner | Brute force, suspicious token use, privilege escalation | | Product event | How is the feature being used? | Product or analytics team | Feature activation, funnel step, conversion | One platform may store several of these event types. The important distinction is purpose. Mixing every event into one unstructured stream makes retention, access control, searching, and incident response harder. ## The application logs vs audit logs decision framework Ask these questions when designing an event: 1. Is the event needed to debug software behavior? 2. Does the event prove an accountable action by a user, administrator, service account, or system? 3. Does it affect identity, permissions, sensitive data, billing, recovery, or security settings? 4. Will the record need stronger protection or longer retention than normal debugging data? 5. Should a customer or compliance reviewer be able to understand it without reading source code? Use this rule: > If the event explains system behavior, create an application log. If it proves an important action, create an audit log. If it does both, create two purpose-built records linked by shared context. ## What belongs in application logs Application logs describe execution state and operational behavior. Common application events include: - request failures and exceptions, - database connection or query errors, - cache failures, - dependency timeouts, - queue processing and retries, - background-job results, - service startup and shutdown, - deployment and configuration events, - slow operations, - resource or rate-limit errors, - unexpected application states. A useful application log should help the team answer: - Which service failed? - Which request, job, or workflow was affected? - What error occurred? - Which dependency was involved? - How long did the operation take? - Which deployment or environment produced the event? ### Recommended application-log fields OpenTelemetry’s log data model defines common fields such as timestamps, trace and span identifiers, severity, body, resource, instrumentation scope, and attributes. A practical application record may include: | Field | Purpose | |---|---| | Event timestamp | When the event occurred | | Observed timestamp | When the collector received it | | Service and component | Where it originated | | Environment | Production, staging, or development | | Severity | Debug, information, warning, error, or critical | | Event name | Stable identifier for the event type | | Request, trace, or job ID | Correlation across components | | Deployment version | Connection to a code or configuration change | | Route or workflow | Affected operation | | Duration | Performance context | | Dependency | Database, queue, API, cache, or storage involved | | Result or error class | Outcome without relying only on free-form text | | Safe attributes | Additional controlled debugging context | Prefer structured fields over messages that require text parsing. A human-readable message can still be included, but the important dimensions should be searchable independently. Bad: ```text Something failed. ``` Better: ```json { "event_name": "payment_webhook_failed", "service": "billing-api", "environment": "production", "severity": "error", "request_id": "req_7f21", "provider": "payment-provider", "error_type": "signature_validation", "deployment_version": "2026.08.03.2" } ``` The example preserves diagnostic context without storing the webhook secret or payment details. ## What belongs in audit logs Audit logs record actions that require accountability. NIST describes an audit record as an individual entry in an audit log related to an audited event. Common audit events include: - successful and failed authentication, - password and MFA changes, - user invitations and removals, - role and permission changes, - API key creation, rotation, and deletion, - administrative impersonation, - security-setting changes, - billing and payment-setting changes, - customer-data exports, - account deletion, - backup restoration or deletion, - production access, - deployment approval, - high-impact configuration changes. An audit record should answer: - Who or what performed the action? - What action was attempted? - Which resource was affected? - When did it happen? - What was the result? - From which session, client, or source did it originate? - What changed? ### Recommended audit-log fields | Field | Purpose | |---|---| | Event ID | Unique record identity and duplicate detection | | Event timestamp | When the action occurred | | Actor ID and type | User, administrator, service account, API client, or system | | Actor display context | Human-readable identity where appropriate | | Action | Stable verb such as `role.changed` or `data.exported` | | Target type and ID | Account, workspace, user, server, key, or configuration | | Result | Success, failure, denied, or partial | | Source context | Session, IP, client, user agent, or automation identity | | Previous and new value | Controlled record of what changed when safe | | Reason or ticket | Business context for sensitive actions where available | | Request or trace ID | Link to related application activity | | Tenant or project | Boundary in a multi-tenant system | Do not depend only on names or email addresses as durable identifiers. Names can change. Use stable internal identifiers and add safe display context separately. ## Some actions require both log types One business action can have two valid representations. | Event | Application-log view | Audit-log view | |---|---|---| | User role changed | Endpoint completed, validation result, duration | Administrator changed user role from Member to Admin | | Data export generated | Export job duration, worker result, storage outcome | Actor exported a defined dataset | | API key created | Key service completed the request | Actor created a credential with a defined scope | | Production deployment | Pipeline steps, test and release result | Actor or automation deployed version to production | | MFA disabled | Account service updated configuration | Actor disabled a security control for an account | | Backup restored | Restore operation status and duration | Actor restored a recovery point to a target system | Do not copy the same record into two indexes and call them separate logs. Each record should use the fields and language appropriate to its purpose. Link them through request, trace, event, or change identifiers. ## Audit logs need stronger integrity controls Application logs are often high-volume operational data. Audit logs may become evidence. They therefore need stronger protection against unauthorized changes, deletion, and gaps. A practical integrity model includes: - restricting who can read, export, and delete audit data, - separating audit storage from the application process where practical, - using append-oriented writes, - recording unique event identifiers, - synchronizing system clocks, - monitoring ingestion failures and gaps, - preserving source and collector timestamps, - protecting archives with limited credentials, - logging changes to audit configuration itself, - reviewing privileged actions regularly. A system administrator who can perform a sensitive action and silently erase the only record creates a weak accountability boundary. Stronger integrity does not mean every audit event must be immutable forever. It means deletion, alteration, and retention must follow controlled rules rather than application convenience. ## Logging failures must be visible A logging design should account for the possibility that the destination is slow, unavailable, or rejecting events. Questions to answer: - Does application traffic block when the log backend is unavailable? - Are events buffered, dropped, retried, or written locally? - Can the team detect missing audit events? - Is queue growth monitored? - What happens when local disk fills? - How are duplicate events handled after retries? For normal debug logging, dropping low-value records may be safer than stopping the application. For critical audit events, silent loss may be unacceptable. The implementation should define durability, retry, backpressure, and failure behavior according to the event’s importance. Record a stable event ID so the receiving system can identify retries and duplicates. ## Sensitive data should not become logging context OWASP recommends excluding or masking data such as access tokens, authentication passwords, database connection strings, encryption keys, payment-card data, and sensitive personal information unless a justified and protected use requires it. Do not log: - passwords, - private keys, - full API tokens, - session cookies, - secret environment variables, - payment-card data, - raw authorization headers, - unredacted request bodies, - unnecessary personal data, - database dumps or full documents. Use allowlisted fields instead of logging complete objects. Redact values before they enter the logging pipeline, not only in the viewing interface. An audit event may need to prove that a data export occurred without copying the exported data into the log. Record the actor, target, data category, result, and export identifier instead. ## Retention should follow purpose and risk Application logs and audit logs should not automatically share one retention period. Use a retention decision based on: - operational troubleshooting window, - incident discovery time, - customer and contractual requirements, - legal and privacy obligations, - sensitivity of the data, - investigation value, - storage and search cost, - deletion and archive processes. | Data category | Retention posture | |---|---| | Verbose debug output | Short and tightly controlled | | Application errors and operational events | Long enough for normal incident discovery and regression analysis | | Performance and access data | Based on capacity, abuse, and troubleshooting needs | | Security events | Long enough to support investigation and access review | | Audit events | Based on accountability, customer, contractual, and legal needs | | Incident evidence | Preserved separately according to the incident process | Avoid retaining all data indefinitely. Excessive retention increases storage cost, access surface, privacy risk, and the amount of sensitive information exposed during an incident. A retention policy should define: - owner, - data category, - searchable period, - archive period, - deletion method, - exceptions for active incidents or legal holds, - review schedule. ## Storage should match the failure boundary Local VM logs can be appropriate for early development and short-term troubleshooting. They are not a complete solution when logs must survive server loss or compromise. | Storage pattern | Good fit | Main limitation | |---|---|---| | Local files or journal | Simple application and immediate troubleshooting | Lost or unavailable with the VM | | Central log platform | Search and correlation across services | Cost, access control, ingestion dependencies | | Dedicated audit database | Product-visible audit history | Requires deliberate schema and integrity controls | | Object-storage archive | Retained records and evidence | Search may require a separate indexing process | | Security platform | Detection and investigation | Operational complexity may exceed early-team needs | Important audit data should not depend solely on the same server and credentials involved in the action being audited. Object storage can be useful for compatible archives, but an archive still needs access controls, encryption decisions, lifecycle rules, validation, and an owner. Storage durability alone does not create a trustworthy audit system. ## Application logs should support incident response During an incident, application logs help establish the technical timeline: - first error, - affected service, - route or workflow, - dependency failure, - deployment version, - retry behavior, - recovery result. Audit logs help establish the action timeline: - administrator login, - permission change, - key creation, - configuration update, - deployment approval, - data export, - backup deletion or restoration. Together, they help distinguish a software failure from an authorized change, misuse, or compromise. Link important records with request, trace, change, or deployment identifiers. See [Incident Response Plan for Small Teams](/learn/guides/server-incident-response-small-teams-triage-containment-recovery) for evidence preservation and timeline decisions. ## Customer-facing audit logs are a product surface B2B SaaS customers may need to review user invitations, role changes, exports, administrative actions, and security settings. Customer-facing audit events should be: - understandable without internal code knowledge, - explicit about actor and target, - consistent in wording, - clear about success or failure, - accurate across time zones, - searchable and filterable, - protected from leaking secrets or hidden identifiers, - documented with an intentional retention promise. Bad: ```text update success user=293 role=admin ``` Better: ```text Workspace administrator changed user 293 from Member to Admin. ``` The internal record can preserve actor IDs, request IDs, source information, and old/new values. The product-facing presentation should remain concise and safe. Do not promise a retention period, export capability, or immutability property that the system cannot reliably deliver. ## Audit logging should support access reviews Audit data becomes an operational control when it is reviewed, not merely stored. Use it to review: - new administrator grants, - dormant privileged accounts, - unusual login behavior, - credential creation, - contractor activity, - sensitive exports, - backup deletion, - firewall and security-setting changes, - emergency-access use. For the broader ownership process, see [User Access Review for Cloud Servers](/learn/guides/cloud-access-reviews-small-teams-ssh-admin-permissions). High-impact events can generate alerts, but avoid paging on every audit record. Alert when the action is unexpected, unauthorized, high risk, or requires immediate validation. ## A practical logging architecture for small teams A small production application can use this progression: ### Stage 1: Structured application logs Use consistent timestamps, severity, service name, environment, request ID, event name, and safe attributes. ### Stage 2: Defined audit events Create an event catalog for identity, permissions, credentials, data, billing, security, and administrator actions. ### Stage 3: Central collection Forward logs away from individual application processes. Monitor collector health and ingestion gaps. ### Stage 4: Separate access and retention Give developers access to operational data needed for troubleshooting. Restrict sensitive audit records and administrative exports. ### Stage 5: Durable archive and review Archive records that require longer retention and schedule access, integrity, and event-coverage reviews. ### Stage 6: Correlation and incident use Link logs with trace IDs, deployment versions, change records, and incident timelines. The architecture should remain proportional to the product’s risk, customer expectations, and team capacity. ## How this applies on Raff A Raff VM can host an application, local logging agent, or an early centralized logging component. As the workload grows, logging and audit storage can be separated from the application’s failure boundary. A practical Raff design may use: - [Raff VM](/products/raff-vm) for the application and log forwarder, - [Object Storage](/products/object-storage) for compatible log and audit archives, - [Raff VPC](/products/vpc) for private communication between applications and internal logging components, - [Data Protection](/products/data-protection) for infrastructure recovery where appropriate. Do not rely on an application-server snapshot as the only audit record. Recovery copies, searchable application logs, and protected audit evidence solve different problems. Verify current product capabilities and storage behavior on the live product pages before designing retention or recovery around them. ## Application and audit logging checklist ### Event design - Every event has a defined reader and decision. - Application and audit events are distinguished by purpose. - Stable event names and identifiers are used. - Events that need both views create separate linked records. ### Application logs - Service, environment, severity, and timestamps are present. - Request, trace, or job identifiers support correlation. - Deployment versions and dependencies are recorded. - Error messages include actionable context. ### Audit logs - Actor, action, target, result, and source context are present. - Permission, credential, export, billing, and security changes are covered. - Audit configuration changes are themselves recorded. - Integrity and deletion permissions are controlled. ### Security and privacy - Secrets and unnecessary personal data are excluded. - Redaction happens before ingestion. - Read, export, and delete access is restricted. - Retention and archive rules are documented. ### Operations - Ingestion failures and gaps are monitored. - Backpressure, retry, duplicate, and disk-full behavior are defined. - Incident evidence can be preserved. - Audit events are reviewed according to risk. :::cluster ## Conclusion Application logs and audit logs are different records for different future questions. Use application logs to diagnose software behavior, performance, retries, dependencies, and failures. Use audit logs to prove important actions involving identity, access, credentials, customer data, billing, security settings, recovery, and administration. Keep both structured, exclude sensitive data, link related events through stable identifiers, and give audit records stronger integrity, access, retention, and review controls. A logging system is useful when it helps the right person make a reliable decision—not when it simply stores more events. :::cta Explore Object Storage Use compatible object storage for controlled log archives, exports, and retained audit records. ::: ## Sources - [OpenTelemetry Logs Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/) - [OpenTelemetry Logging](https://opentelemetry.io/docs/specs/otel/logs/) - [NIST Audit Record Glossary](https://csrc.nist.gov/glossary/term/audit_record) - [NIST SP 800-53 Rev. 5](https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final) - [OWASP Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html) - [Raff VM](/products/raff-vm) - [Raff Object Storage](/products/object-storage) --- ### Cloud Firewall Best Practices: Inbound, Outbound, and Private Traffic URL: https://rafftechnologies.com/learn/guides/firewall-best-practices-cloud-servers Description: Learn cloud firewall best practices for inbound, outbound, administrative, private, IPv4, and IPv6 traffic without overexposing services. A cloud firewall controls which network paths are allowed to reach or leave a server. **The strongest default is simple: expose only the public entry points the workload needs, restrict administrative access, keep databases and internal services on private paths, and review both inbound and outbound rules as the architecture changes.** A firewall reduces reachability. It does not replace secure authentication, patching, application security, encryption, monitoring, or backups. ## Cloud firewall best practices: quick answer For a typical cloud application: - allow public HTTP and HTTPS only when the workload serves public users - restrict SSH and RDP to approved administrative paths - keep databases, caches, queues, metrics, and internal APIs off the public internet - deny other inbound traffic by default - review outbound access where a compromised server could reach sensitive systems or exfiltrate data - apply equivalent policy to IPv4 and IPv6 - document temporary rules with an owner and expiry | Traffic path | Safer default | |---|---| | Public web traffic | Allow TCP 80/443 as required | | SSH or RDP | Restrict to trusted IPs, VPN, bastion, or private path | | Application runtime ports | Localhost or private network only | | Database, cache, and queue | Private network and approved sources only | | Monitoring and admin dashboards | Private or strongly authenticated access | | Outbound package and API access | Allow only what the workload requires where practical | | All other inbound traffic | Deny | A useful rule is: > If a rule has no clear service, source, owner, and review date, it should not remain in production. ## Begin with traffic flows, not port lists Before writing rules, document the expected communication paths. For example: ```text Users ↓ HTTPS Public load balancer or reverse proxy ↓ private application port Application VM ↓ private database port Database VM ``` Then add administrative and operational paths: ```text Approved administrators ↓ restricted SSH or RDP Application and database VMs Monitoring system ↓ protected metrics endpoints Application and database VMs ``` This approach is safer than copying a generic port list because it connects each rule to an actual dependency. For every flow, record: - source - destination - protocol and port - public or private path - purpose - owner - expected lifetime ## Use deny by default for inbound traffic A deny-by-default policy blocks inbound traffic unless a rule explicitly allows it. This reduces the attack surface because unused services are unreachable even if they are installed or accidentally listening. A public web VM might need: | Service | Port | Source | |---|---:|---| | HTTP | TCP 80 | Public internet, if used for redirect or certificate validation | | HTTPS | TCP 443 | Public internet | | SSH | TCP 22 | Approved admin source only | | Application runtime | TCP 3000 or similar | Localhost or approved private source | | Database | Engine-specific | No public access | Do not open development ports, database ports, or dashboards “temporarily” without an owner and removal plan. ## Treat administrative access separately SSH, RDP, control panels, hypervisor consoles, and database administration paths can change the system. They deserve stricter rules than user-facing traffic. Preferred options include: - a trusted source IP - VPN access - a bastion or controlled gateway - private-network administration - short-lived firewall access Network restriction should be combined with strong identity controls: - individual accounts - SSH keys for Linux where appropriate - strong Windows credentials and supported MFA or gateway controls - least privilege - rapid offboarding - logging Read [Private vs Public Admin Access](/learn/guides/private-vs-public-admin-access) for the architecture trade-off. ## Keep databases and internal services private Database authentication is necessary, but it should not be the only boundary. Services that usually should not accept broad public traffic include: - PostgreSQL and MySQL - Microsoft SQL Server - Redis and other caches - MongoDB and search services - message queues - metrics endpoints - internal APIs - container orchestration control planes Allow the smallest approved source set, such as an application subnet, a named VM role, or a controlled admin path. Private networking reduces public exposure, but private networks can still be too permissive. Apply least-privilege firewall policy inside the private network. Read [Private Networking in Cloud](/learn/guides/private-networking-public-vs-private-traffic) for public and private traffic design. ## Review outbound traffic as well Inbound filtering reduces who can reach a server. Outbound filtering limits where the server can connect. Outbound controls can reduce the impact of: - compromised applications - malicious dependencies - unexpected data transfer - lateral movement - misconfigured scripts Not every small workload needs a complex egress policy. Start with systems that handle sensitive data or have narrow, predictable dependencies. Examples include: - a database server that needs only DNS, updates, backups, and monitoring - a worker that should call one approved API - an internal service that should not reach the public internet - a production application that should reach specific storage, email, and payment endpoints Be careful with domain-based dependencies because IP addresses may change. Use documented provider ranges, proxies, service endpoints, or monitoring where appropriate rather than creating brittle rules. ## Apply policy to IPv4 and IPv6 A common dual-stack mistake is protecting IPv4 while IPv6 remains broadly reachable. Review both address families for: - public web ports - SSH and RDP - database and cache ports - monitoring endpoints - outbound rules Do not assume an operating-system or platform firewall automatically mirrors IPv4 rules to IPv6. Read [IPv4, IPv6, and Dual-Stack Networking](/learn/guides/ipv4-ipv6-dual-stack-networking-cloud-servers) for the broader deployment path. ## Understand stateful firewall behavior Many cloud firewalls are stateful: return traffic for an allowed connection is automatically permitted. This simplifies common client-server flows, but behavior varies by platform and rule type. Before designing complex policy, confirm: - whether rules are stateful - whether inbound and outbound policies are evaluated separately - how established connections behave after a rule change - whether network address translation is involved - whether health checks require separate rules Do not add broad return-path rules without understanding the firewall model. ## Separate rules by server role Different workloads should not inherit one universal rule set. | Role | Public ingress | Private ingress | |---|---|---| | Edge or reverse proxy | HTTP/HTTPS | Monitoring and approved backend paths | | Application VM | Usually none | Edge, admin, database, cache, queue | | Database VM | None | Application tier and controlled admin access | | Worker VM | None | Queue, database, storage, admin | | Bastion or gateway | Restricted admin protocol | Approved internal management paths | | Monitoring VM | Usually none | Metrics and log paths | Role-based policy is easier to review than one large collection of copied exceptions. ## Use platform and operating-system firewalls deliberately A platform firewall filters traffic before or around the VM. An operating-system firewall filters traffic inside the guest. Using both can provide defense in depth, but duplicated rules can also create troubleshooting confusion. A practical model is: - platform firewall for the broad network boundary - operating-system firewall for host-specific enforcement and local interfaces - application authentication for identity and authorization Document which layer owns each rule. When traffic fails, operators should know where to inspect first. ## Give temporary rules an expiry Temporary rules are a common source of long-term exposure. Every temporary rule should include: - reason - requester - owner - creation time - expiry or removal event - affected workload Examples include migration access, vendor support, debugging, or one-time data transfer. Review temporary rules immediately after the work ends rather than waiting for the next quarterly audit. ## Log and review meaningful changes Useful records include: - firewall rule creation, modification, and deletion - repeated attempts against administrative ports - blocked database or cache traffic - unusual outbound destinations - rules with no observed use Logging every packet may create too much noise. Prioritize high-impact paths and configuration changes. Review frequency should match environment change rate. Fast-moving production environments may need monthly or event-driven reviews; stable environments may use a quarterly review plus checks after major changes. ## Test firewall changes safely Firewall changes can expose services or lock administrators out. Use a simple change process: 1. Record the intended traffic flow. 2. Confirm an alternative access path or console is available. 3. Add the narrow rule. 4. Test from an allowed source. 5. Test from a disallowed source. 6. Verify application health and monitoring. 7. Remove the old or temporary rule. 8. Record the result. For production database and administrative changes, avoid editing several layers simultaneously unless the rollback plan is clear. ## How this applies on Raff Raff provides [Security](/products/security), [Private Cloud Networks](/products/private-cloud-networks), [Linux VMs](/products/linux-vm), and [Load Balancers](/products/load-balancers) as building blocks for controlled public and private traffic. A practical Raff pattern is: ```text Internet ↓ TCP 80/443 Raff Load Balancer or public application VM ↓ Raff Private Cloud Network Application and database services ``` Use the current dashboard and product documentation to confirm firewall scope, stateful behavior, supported protocols, IPv6 handling, and private-network integration before relying on a rule design. ## Common mistakes ### Opening SSH or RDP broadly Restrict management paths even when credentials are strong. ### Exposing a database because authentication exists Use both network restriction and database authentication. ### Protecting only IPv4 Apply equivalent policy to every enabled address family. ### Ignoring outbound access Sensitive and predictable workloads may benefit from egress restrictions and monitoring. ### Copying the same rules to every server Match policy to workload role and dependencies. ### Leaving temporary access indefinitely Assign an owner and expiry at creation time. ### Using a firewall instead of patching Reachability control and vulnerability remediation are separate responsibilities. ## Conclusion Cloud firewall policy should describe the traffic the system needs and deny the rest. Keep the public surface small, restrict administrative access, place databases and internal services on private paths, review outbound dependencies, protect both IPv4 and IPv6, and treat temporary rules as expiring changes. The best firewall configuration is not the largest rule set. It is the smallest understandable policy that supports the application safely. :::cta Explore Security Review Raff’s current security controls and design clearer public and private traffic boundaries. ::: ## Sources - [NIST SP 800-41 Rev. 1: Guidelines on Firewalls and Firewall Policy](https://csrc.nist.gov/pubs/sp/800/41/r1/final) - [Raff Security](/products/security) - [Raff Private Cloud Networks](/products/private-cloud-networks) --- ### Stateful vs Stateless Applications: Where Application State Should Live URL: https://rafftechnologies.com/learn/guides/stateful-vs-stateless-applications Description: Compare stateful and stateless applications, decide where application state should live, and prepare sessions, files, jobs, databases, scaling, deployment, and recovery. Stateful and stateless describe where an application keeps the context it needs to work correctly. **A stateful component depends on information retained between requests, jobs, or connections. A stateless application node can handle the next request without relying on memory or files stored on that specific server.** Almost every useful system has state somewhere. The architecture decision is whether that state is tied to one application node or placed in a shared, durable service designed to own it. For most cloud applications, the practical target is hybrid: stateless web and API nodes supported by intentionally stateful databases, queues, caches, and storage services. ## Stateful vs stateless applications at a glance | Decision factor | Stateful component | Stateless application node | |---|---|---| | Request handling | May depend on previous activity | Each request can reach any healthy node | | State location | Local memory, disk, or dedicated data service | Request or shared external service | | Server affinity | May require a particular node | Should avoid node affinity | | Horizontal scaling | Requires state coordination | Usually simpler | | Failure recovery | Restore, fail over, or reconcile state | Replace the node and resume traffic | | Common examples | Databases, queues, persistent caches, game sessions | Web servers, APIs, reverse proxies, many workers | | Main concern | Durability, consistency, ordering, recovery | Dependency availability and externalized state | A useful rule is: > Keep state in the component responsible for durability and continuity. Keep application nodes replaceable when scaling and recovery matter. ## Application state is information the system must remember Application state includes any information required after the current operation ends. Examples include: - user sessions and shopping carts - customer and transaction records - uploaded files - background-job progress - queue messages and delivery status - WebSocket connections - workflow checkpoints - cache entries - search indexes - locks, leases, and idempotency records The label “state” is too broad for one storage decision. Classify it by importance and lifetime. | State class | Meaning | Examples | |---|---|---| | Durable | Must survive process and server failure | Orders, accounts, documents | | Recoverable | Can be restored from another source | Search index, derived report | | Temporary | May expire or be recreated | Cache entry, temporary file | | Local | Exists only on one process or node | In-memory session, local upload | | Shared | Available to multiple nodes | Database, object store, queue | | Connection-bound | Exists for the life of a connection | WebSocket presence, stream position | The most important design question is usually not “Does the application use state?” It is “Which component owns each state class, and what happens when that component fails?” ## A stateful application depends on retained context A stateful component uses information created by earlier activity to process the next request, event, or connection. Common stateful workloads include: - relational and document databases - message brokers and durable queues - persistent caches - file servers - search indexes - multiplayer game servers - real-time collaboration systems - long-running workflows - applications that store sessions or uploads locally Statefulness is not a design flaw. Databases and storage systems exist because applications need reliable memory. The operational cost is that stateful components are harder to replace and scale. Teams must plan for: - data consistency - backup and restoration - replication or failover - storage capacity and latency - controlled network access - upgrades and schema compatibility - recovery point and recovery time objectives - reconciliation after partial failure A stateful service should not be treated like a disposable application VM. Its data path is part of the product. ## A stateless application node does not own durable context A stateless application node can process a request without relying on context stored only on that server. Required context is usually: - included in the request - represented by a validated token - retrieved from a shared database or cache - read from object storage - consumed from a shared queue Common stateless workloads include: - HTTP web servers - REST and GraphQL APIs - reverse proxies - frontend-rendering nodes - authentication gateways - workers that checkpoint externally - batch processors that use shared job state AWS Well-Architected guidance recommends offloading state from individual compute nodes so instances can be replaced without availability impact. Microsoft similarly recommends externalizing server-side session state when an application needs to scale across multiple instances. Stateless nodes are easier to: - scale horizontally - place behind a load balancer - replace after failure - deploy gradually - rebuild from automation - remove during maintenance Statelessness does not remove state. It moves state into services that must now be designed and protected deliberately. ## Most production systems are hybrid A typical cloud application combines stateless and stateful components. ```text Users ↓ Load balancer ↓ Stateless web or API nodes ↓ private network Database + cache + queue ↓ Object storage and recovery systems ``` In this model: - app nodes handle requests - the database owns durable business records - a shared cache or database owns session state - a queue owns pending background work - object storage owns uploaded files and generated assets - recovery systems protect state according to its value The application tier becomes replaceable while state remains in components designed to preserve it. ## Use a state ownership decision framework For every stateful item, record: 1. **Owner:** Which component is authoritative? 2. **Durability:** Must it survive node or region failure? 3. **Consistency:** Can stale or duplicate data be tolerated? 4. **Lifetime:** Request, session, job, customer, or indefinite? 5. **Access pattern:** One node, many nodes, ordered, concurrent, or append-only? 6. **Recovery:** Rebuild, restore, replay, or fail over? 7. **Security:** Which services and users may access it? 8. **Migration:** Can the state move without breaking old and new application versions? This prevents one VM from becoming the undocumented owner of sessions, files, jobs, and secrets. ## Sessions should not tie users to one application node A session stored only in process memory makes the application tier stateful. This often leads to sticky sessions, where a load balancer sends the user back to the same node. Sticky routing can work, but it creates limits: - node failure can end active sessions - traffic may become uneven - deployments require more care - scale-in can remove active user context - failover becomes less predictable A more replaceable design stores session state in a shared database or cache, or uses appropriately designed tokens. Tokens do not eliminate all session concerns. Revocation, expiration, rotation, sensitive claims, and authorization changes still require deliberate design. ## Uploaded files should not depend on one app VM Local uploads may be reasonable for a first single-server deployment, but they create problems when: - a second node cannot access the files - the original VM fails - deployment replaces the server - storage grows independently of compute - users are routed to different nodes Shared [Object Storage](/products/object-storage) is usually a better fit for files that multiple nodes must access. Temporary processing files can remain local when they are disposable and bounded. The completed output should be committed to its authoritative store before the node is removed. ## Background jobs need durable ownership and safe retries A worker that stores job progress only in memory is fragile. If it stops, the team may not know whether the job completed, partially completed, or should be retried. A safer design uses a queue or database to record: - job identity - ownership or lease - attempt count - progress or checkpoint - completion result - failure reason Workers should be idempotent where practical: repeating the same job should not create duplicate charges, emails, records, or destructive changes. Scaling workers horizontally is useful only when the database, queue, and external APIs can support the added concurrency. ## WebSocket and real-time services remain connection-stateful WebSocket services retain live connections, subscriptions, presence, and delivery position. They can scale horizontally, but not in the same way as ordinary request-response APIs. A multi-node design may require: - connection-aware routing - shared presence or subscription state - pub/sub between nodes - reconnect and resubscribe behavior - safe connection draining - message ordering and duplicate handling The node can still be replaceable, but active connection state needs a defined migration or recovery behavior. ## Databases are intentionally stateful The objective is not to make a database stateless. The objective is to give it the correct durability, consistency, access, and recovery boundaries. A database plan should consider: - storage latency and capacity - backup and point-in-time recovery needs - connection limits - private networking - replication and failover - schema migration compatibility - monitoring and slow-query analysis Adding stateless application nodes can increase database connections and query volume. Horizontal application scaling must include database headroom. ## Caches should not accidentally become the only source of truth A cache can be temporary, reconstructable state. It becomes a critical stateful system when the application cannot operate or recover without its contents. Decide whether cached data is: - safely disposable - reconstructable but expensive - session-critical - queue-like - the only copy of business data Design cache loss explicitly. A cache miss storm after restart can overload the database even when no durable data is lost. ## Statelessness improves horizontal scaling Stateless app nodes let a load balancer route requests to any healthy instance. Before scaling out, verify: - sessions are shared or self-contained safely - uploads are outside the app node - jobs can be retried or resumed - configuration and secrets are externalized - application nodes are built repeatably - database connections are controlled - one node can be removed without losing critical context Read [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) for the scale-up versus scale-out decision. The operational test is simple: > Can one application node be drained and deleted while users remain signed in, files remain available, jobs continue, and no durable data disappears? When the answer is no, identify which local state creates the dependency. ## State affects load balancing and deployment A load balancer does not make an application stateless. The state model must allow traffic to move between nodes. Stateless app tiers support: - round-robin or health-aware routing - rolling deployments - simpler node replacement - more even utilization Stateful backends may require: - sticky sessions - primary and replica roles - connection-aware routing - quorum and consistency rules - safe draining During rolling deployment, old and new versions may operate simultaneously. Shared state must remain compatible across: - database schemas - session formats - cache keys - queue messages - API contracts Use an expand-and-contract migration: 1. Add new state or schema without removing the old form. 2. Deploy code that understands both versions. 3. Migrate data where required. 4. Remove old application versions. 5. Remove obsolete fields or formats later. ## State determines the recovery path A failed stateless node can often be rebuilt from code and configuration. A failed stateful component may require: - restoring a backup - promoting a replica - replaying a queue - reattaching storage - reconciling incomplete writes - validating consistency Separate state by recovery need. | State | Typical recovery approach | |---|---| | Application node | Rebuild or replace | | Customer database | Restore, replay, or fail over | | Queue | Resume or replay safely | | Object uploads | Restore retained objects or versions | | Cache | Rebuild, warm gradually, or restore if intentionally durable | | Search index | Recreate from authoritative data | | Session state | Expire, restore, or preserve according to product needs | Having a snapshot is not the same as having a tested recovery process. Use [Data Protection](/products/data-protection) as one part of a broader recovery design. ## Keep the first architecture migration-friendly A single VM can be reasonable for a small application. The goal is not to distribute every component immediately. Keep the simple architecture ready for later change by: - avoiding local-only sessions - storing uploads outside the application directory - separating configuration and secrets from code - using repeatable deployment steps - backing up durable data - assigning clear owners to local files and databases - monitoring storage growth and dependency usage Introduce distributed components when they solve a measured scaling, recovery, security, or operational problem. ## How this applies on Raff A growing Raff architecture may use: - [Raff Cloud Servers](/products/raff-vm) for web, API, worker, database, and supporting workloads - [Load Balancers](/products/load-balancers) for health-aware routing across replaceable app nodes - [Private Cloud Networks](/products/private-cloud-networks) for backend communication - [Object Storage](/products/object-storage) for shared files and assets - [Volumes](/products/volumes) for persistent block storage where appropriate - [Data Protection](/products/data-protection) for recovery planning ```text Users ↓ Raff Load Balancer ↓ Stateless application VMs ↓ private network Database / cache / queue ↓ Object Storage + recovery systems ``` Verify current product capabilities, storage behavior, and recovery workflows on live product pages before implementation. ## Stateful vs stateless checklist ### State ownership - Every state item has an authoritative owner. - Durable, temporary, local, and shared state are distinguished. - Recovery and retention requirements are documented. ### Stateless app tier - Sessions do not depend on one node. - Uploads and durable files are externalized. - Jobs can be retried or resumed safely. - Configuration and secrets are externalized. - Nodes can be drained and replaced. ### Stateful services - Databases, queues, caches, and storage use controlled private access. - Backups and restores are tested. - Replication and failover behavior are understood. - Schema and message changes support version coexistence. ### Scaling and recovery - Database and dependency headroom is measured. - Load balancer health and draining are tested. - Cache loss and connection loss are planned. - Node removal does not destroy critical context. :::cluster ## Conclusion Stateful versus stateless is a decision about where context lives and which component is responsible for preserving it. Keep web and API nodes replaceable when horizontal scaling, rolling deployment, and fast recovery matter. Keep databases, queues, caches, and storage intentionally stateful when continuity and durability are their purpose. The strongest cloud design is usually hybrid: disposable application nodes connected to clearly owned stateful services through controlled private paths. :::cta Explore Raff VM Build a cloud architecture that can start simple and separate state as your application grows. ::: ## Sources - [AWS Well-Architected: Make Systems Stateless Where Possible](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_stateless.html) - [Microsoft Azure Well-Architected: Scaling and Partitioning](https://learn.microsoft.com/en-us/azure/well-architected/performance-efficiency/scale-partition) - [Raff Cloud Servers](/products/raff-vm) - [Raff Object Storage](/products/object-storage) --- ### Preview Environments vs Staging: What Startups Actually Need URL: https://rafftechnologies.com/learn/guides/preview-environments-vs-staging Description: Compare preview environments and staging by purpose, lifecycle, parity, secrets, data, cost, cleanup, and release confidence to choose preview only, staging only, or both. Preview environments and staging reduce different kinds of release risk. **A preview environment is a temporary deployment for reviewing one branch, pull request, or change. A staging environment is a stable pre-production environment used to validate a release as a complete system.** Use previews when parallel review is the bottleneck, staging when release confidence is the bottleneck, and both when branch-level feedback and final production-like validation are separate needs. Neither environment should use production secrets or unrestricted customer data. Each also needs a defined owner, purpose, lifecycle, and cleanup process. ## Preview environments vs staging at a glance | Decision factor | Preview environment | Staging environment | |---|---|---| | Main purpose | Validate one change | Validate one release | | Typical trigger | Branch, commit, or pull request | Release candidate or promotion step | | Lifetime | Short-lived | Persistent or regularly recreated | | Users | Developers, QA, design, product reviewers | Engineering, QA, operations, release owners | | Data | Synthetic or isolated test data | Production-like but protected data | | Configuration | Change-specific and restricted | Production-compatible configuration structure | | Main risk reduced | Review and merge risk | Release and integration risk | | Cleanup | Automatic expiry or deletion | Managed as a long-lived environment | A useful distinction is: > Preview answers “Is this change ready to merge?” Staging answers “Is this release ready to ship?” ## Start with the confidence your team is missing Do not begin by asking which environment is more modern. Ask which decision currently lacks evidence. Use a preview environment when: - several changes need review in parallel - product, design, or QA needs a shareable version of one branch - shared staging is constantly overwritten - pull-request feedback is slow because reviewers cannot run the change - short-lived isolated testing provides enough confidence Use staging when: - a release combines several merged changes - database migrations, workers, queues, and integrations must be tested together - deployment and rollback procedures need validation - a stable pre-production endpoint is required - the team needs one shared release-approval environment Use both when change-level review and release-level validation are separate gates. Use neither as a permanent rule only when the workload is still a disposable prototype and production impact is genuinely low. Once real users, business data, payments, or operational commitments exist, production should not be the first complete release test. ## Preview environments are change-level deployments A preview environment is usually created from a branch, pull request, or commit and given its own URL. Heroku Review Apps describe this model as a disposable application created for a pull request. Vercel similarly creates preview deployments from non-production branches or pull requests and gives each deployment a distinct URL. The model is useful because it separates review work: ```text Pull request A → Preview A Pull request B → Preview B Pull request C → Preview C ``` Reviewers can inspect one change without waiting for another team member to finish using a shared environment. ### Preview environments are strongest for - visual and product review - feature acceptance - branch-specific API testing - integration tests against isolated test services - reproducing a bug on a known commit - validating configuration before merge - sharing a change with internal stakeholders They are weaker when the question depends on the combined release, production-scale data, realistic traffic, or long-running operational behavior. ## Staging is a release-level environment A staging environment is a stable pre-production system used to validate the release that is expected to reach production. ```text Merged release candidate ↓ Staging deployment ↓ Migration, integration, smoke, and operational checks ↓ Approval ↓ Production ``` A useful staging environment should validate more than whether the web page loads. Depending on the application, it may test: - the production deployment mechanism - database migrations - background workers and scheduled jobs - HTTPS, DNS, proxy, and firewall behavior - environment-specific configuration - external services in approved test modes - logs, metrics, alerts, and health checks - rollback or recovery steps Staging provides value only when teams trust it. A persistent environment that has drifted away from production becomes an extra cost rather than a release control. ## Preview does not automatically replace staging Preview environments can absorb many tasks that teams previously forced through staging. They do not automatically answer every staging question. A preview may prove that one branch works while missing: - interactions with other merged changes - final release configuration - production deployment permissions - shared database migration behavior - long-running jobs - release ordering - production-like network paths - operational monitoring Conversely, staging is often inefficient for branch review. One shared environment becomes unstable when several people deploy unrelated changes to it throughout the day. The choice is therefore not preview **or** staging by default. The environments should own different decisions. ## Choose preview only, staging only, or both | Team situation | Better model | Why | |---|---|---| | One or two developers, infrequent releases | Staging only | One stable checkpoint may be enough | | Many pull requests and frequent visual review | Preview only at first | Parallel feedback is the main constraint | | Fast development plus meaningful production risk | Preview + staging | Separate merge confidence from release confidence | | Complex integrations or migrations | Staging required | Combined-system validation matters | | Highly disposable prototype | Local/development only | Extra infrastructure may not yet earn its cost | | Shared staging constantly overwritten | Add previews | Remove branch-level work from staging | | Preview deployments exist but releases still surprise production | Add or improve staging | Change-level checks are not proving the full release | A startup can evolve between these models. Environment architecture should change when workflow risk changes—not merely when the team reaches a particular size. ## Environment parity should match the decision The Twelve-Factor App recommends keeping development, staging, and production as similar as practical. The same principle applies to preview environments, but not every environment needs identical capacity. A preview environment should reproduce the behavior needed to review the change. Staging should reproduce the production characteristics needed to approve the release. Keep these compatible when they affect correctness: - runtime and dependency versions - database engine and major version - build and deployment artifact - environment-variable names - queue and worker behavior - storage APIs - reverse proxy and TLS behavior - schema migration process - health checks These may differ intentionally: - VM size - traffic volume - retention period - redundancy - test dataset size - number of application nodes Document material differences. An environment cannot prove behavior it does not reproduce. ## Promote a known artifact through staging Preview platforms often rebuild each branch deployment. That is acceptable for change review, but final release control should identify exactly what reaches production. A safer release path is: ```text Commit or merge ↓ Versioned build artifact ↓ Staging validation ↓ Production promotion or deployment ``` Record the commit, artifact version, migrations, validation result, and production deployment. Some platforms support promoting a preview deployment, while others perform a new production build using production configuration. Verify which model is in use. “Promote” does not always mean the same bytes and environment variables are reused unchanged. ## Secrets must be isolated by environment Preview environments are often created automatically, which makes secret scope especially important. Use separate credentials for: - preview - staging - production A preview environment should not inherit broad production access merely because it was created from the same repository. GitHub Environments can restrict deployments through approvals, branch rules, environment secrets, and environment variables. Whatever tooling is used, apply the same principles: - scope credentials to one environment and service - make preview credentials low privilege - restrict who can trigger production deployment - avoid exposing secrets to untrusted pull requests - rotate credentials when an environment or integration is retired Production secrets should never be stored in branch configuration or copied into temporary environments for convenience. ## Data must be separated from production A preview or staging application should not write to the production database. Use: - synthetic data - seeded fixtures - isolated test databases - masked or anonymized copies - service sandbox modes Preview environments usually need smaller, disposable datasets. Staging may need more representative schemas and edge cases, but that does not justify copying raw customer data without an approved transformation and access process. Each preview should also avoid interfering with other previews. Shared test databases can cause conflicting migrations, reused accounts, duplicate webhook events, and nondeterministic results. ## External integrations need environment-specific behavior Preview and staging deployments may interact with: - email providers - payment processors - OAuth applications - webhook consumers - object storage - queues - analytics - third-party APIs Define whether each integration is: - mocked - disabled - connected to a sandbox - connected to an isolated test account - allowed with strict limits A preview should not send real customer emails or trigger live payments. Staging should validate integration behavior through approved non-production endpoints where available. ## Preview environments need a complete lifecycle Creating previews is only half the system. Every temporary environment needs a reliable deletion path. Track: - owner - repository and pull request - commit or branch - creation time - expiration condition - URL and DNS records - credentials - database or dataset - storage objects - firewall rules - destruction result Heroku Review Apps can be configured to follow a pull request lifecycle, and automatically created apps can be destroyed when the pull request closes. The same lifecycle principle should apply to any VM-based or custom implementation. Deleting only the compute instance is not enough. Remove related databases, buckets, credentials, DNS, queues, and network rules. Use [Stale Infrastructure Cleanup](/learn/guides/stale-infrastructure-risk-old-servers-forgotten-keys-abandoned-services) for the wider cleanup process. ## Staging also needs ownership and reset rules A persistent staging environment can accumulate its own drift and test debris. Define: - who owns availability and configuration - how data is reset - when migrations are applied - who may deploy - how release candidates are identified - whether staging may be used for demos - how environment drift is detected - when the environment is rebuilt Do not allow staging to become an unofficial production service. If customers, internal operations, or permanent integrations depend on it, the environment’s actual role has changed. ## Measure whether each environment is earning its cost The full cost includes more than compute: - build minutes - database and storage resources - third-party test accounts - CI/CD maintenance - debugging environment-specific failures - cleanup failures - security review - developer waiting time Useful indicators include: - time from pull request to review - number of staging conflicts - abandoned previews - release defects that staging should have caught - environment drift incidents - monthly non-production infrastructure cost A preview system is justified when faster, parallel review outweighs its automation and cleanup cost. Staging is justified when it catches release-level failures or provides a trusted operational checkpoint. ## A practical environment progression ### Stage 1: local development plus production Appropriate only for a low-impact prototype. Keep production deployment and recovery documented. ### Stage 2: add staging Use one stable environment to validate complete releases before production. ### Stage 3: add previews Create short-lived branch environments when shared staging begins blocking parallel work. ### Stage 4: automate lifecycle and promotion Standardize provisioning, environment-specific secrets, datasets, tests, approval, and deletion. ### Stage 5: separate specialist environments only when justified Performance, security, demo, or migration environments should have a defined purpose and retirement rule. The progression is not mandatory. A frontend-heavy team may adopt previews before staging, while a migration-heavy backend may need staging first. ## How this applies on Raff A VM-based Raff setup can use separate [Raff Cloud Servers](/products/raff-vm) for persistent staging or temporary preview workloads, with [Private Cloud Networks](/products/private-cloud-networks) for controlled backend communication where appropriate. A practical model is: ```text Pull request ↓ automation Temporary preview VM or deployment ↓ merge Shared staging Raff VM ↓ release approval Production environment ``` Use separate credentials, databases, storage paths, and network rules for each environment. Do not embed fixed plan prices or temporary product assumptions in the environment architecture. Verify current capabilities and pricing on live product pages before implementation. For the full environment model, read [Dev, Staging, and Production Environments](/learn/guides/dev-staging-production-cloud-environments). For production rollout decisions, read [Blue-Green vs Rolling Deployments](/learn/guides/blue-green-vs-rolling-deployments). ## Preview and staging decision checklist ### Choose preview environments when - branch-level review is slow - several changes need parallel validation - reviewers need shareable change-specific URLs - environments can be provisioned and deleted reliably - test data and credentials can be isolated ### Choose staging when - complete releases need validation - migrations and integrations must be tested together - deployment and rollback need a stable checkpoint - the environment can remain production-compatible - access and data boundaries are controlled ### Use both when - previews validate changes before merge - staging validates the combined release - each environment has a distinct owner and purpose - artifacts, configuration, and promotion are traceable - cleanup and drift are measured :::cluster ## Conclusion Preview environments and staging are complementary controls. Use previews to isolate and accelerate change-level review. Use staging to validate the combined release, deployment path, integrations, and operational behavior before production. Use both when one shared environment can no longer provide fast feedback and dependable release evidence at the same time. The right environment model is the smallest one that produces the confidence your team actually needs—and reliably removes everything it creates. :::cta Explore Raff VM Build separate preview, staging, and production environments as your release process matures. ::: ## Sources - [The Twelve-Factor App: Dev/Prod Parity](https://12factor.net/dev-prod-parity) - [GitHub Docs: Deployments and Environments](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments) - [Heroku Dev Center: Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps) - [Vercel Docs: Environments](https://vercel.com/docs/deployments/environments) - [Raff Cloud Servers](/products/raff-vm) --- ### Single VM vs Multi-VM Architecture for SaaS Apps URL: https://rafftechnologies.com/learn/guides/single-vm-vs-multi-vm-saas-architecture Description: Decide when a SaaS app should stay on one VM or separate its application, database, workers, files, cache, and traffic routing across multiple systems. A single-VM architecture runs the application and most supporting roles on one server. A multi-VM architecture separates roles such as the app, database, background workers, cache, storage, and traffic routing across independent systems. **Start with one VM when simplicity is the main requirement. Split roles when measurement shows that one shared failure domain, resource pool, deployment process, or recovery path has become unacceptable.** Multi-VM does not mean microservices or Kubernetes. A monolithic SaaS application can remain one codebase while its infrastructure is separated gradually. ## Single VM vs multi-VM architecture at a glance | Decision factor | Single VM | Multi-VM | |---|---|---| | Initial setup | Simpler | More components and networking | | Cost structure | One shared resource pool | Capacity purchased by role | | Deployment | One server may affect every role | Roles can be deployed independently | | Failure boundary | One host can affect the whole system | Failures can be isolated by role | | Scaling | Increase the whole VM | Scale selected roles independently | | Data recovery | App and data recovery may be coupled | Each stateful role can have its own recovery plan | | Observability | Fewer systems, but shared signals | Clearer role-level metrics with more tooling | | Best fit | Prototypes, internal tools, early production | Growing production workloads with measured separation needs | A useful rule is: > Keep one VM while its shared boundaries remain acceptable. Add another role only when you can name the risk, bottleneck, or operating constraint that the split removes. ## Use a six-part topology decision Before moving from one VM to several, review six questions: 1. **Capacity:** Which role is exhausting CPU, memory, storage, connections, or throughput? 2. **Failure isolation:** Which services should continue if one role fails or is restarted? 3. **Recovery:** Which data needs its own backup, restore, and recovery objective? 4. **Deployment:** Which roles need separate release or maintenance windows? 5. **State:** Which sessions, files, jobs, and records prevent an app node from being replaced? 6. **Operations:** Can the team monitor, secure, deploy, and recover the additional system? A split is justified when the operational benefit exceeds the additional network, monitoring, security, and recovery work. ## A single VM is a valid production starting point One VM can run a reverse proxy, web application, API, database, worker, cache, scheduled jobs, and monitoring for an early product. This topology is often appropriate when: - traffic and job volume are modest - brief maintenance downtime is acceptable - one team owns the complete workload - the database and files are still small enough to recover predictably - deployments are infrequent - app, worker, and database resource usage do not interfere materially - the product is still validating demand The value is operational clarity. There is one host to deploy, inspect, secure, back up, and pay for. The architecture should still be production-aware. Use separate processes, explicit service ownership, resource monitoring, restrictive firewall rules, documented backups, and a tested restore path. “Single VM” should not mean “undocumented server.” Use [Production VPS Checklist for SaaS Apps](/learn/guides/production-vps-checklist-saas-app) to review the production baseline before deciding whether more servers are needed. ## One VM becomes risky when unrelated roles share every boundary A single host couples several concerns: - CPU and memory - storage capacity and latency - operating-system maintenance - application deployment - network exposure - monitoring and logs - backup and restore - incident blast radius The architecture may still work under normal traffic while becoming hard to operate during failure or maintenance. Common warning signs include: - background jobs delay user requests - database activity competes with the application for memory or disk I/O - uploads or logs threaten database free space - one deployment restarts the app, workers, and scheduler together - a backup job causes noticeable production latency - every capacity increase requires resizing unrelated roles - an app-server rebuild also requires moving customer data or files - a restore would recover several unrelated services together - incidents are difficult to isolate because every signal comes from one host One warning does not require a complete redesign. It identifies the role that should be measured first. ## Diagnose the constraint before adding servers Multi-VM architecture does not automatically solve performance. If the database query plan is the bottleneck, adding app servers can increase pressure. If an external API controls request latency, separating workers will not remove that dependency. If the application leaks memory, a new topology may only spread the problem. Correlate user impact with: - request and job latency - error rate - CPU and memory pressure - disk latency and capacity - database query, lock, and connection behavior - queue age and depth - upload and processing volume - backup duration - deployment and restart impact Use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) to find where work is waiting before changing the topology. ## Multi-VM architecture separates infrastructure roles Multi-VM means that roles run on separate VMs or suitable managed services. It does not require splitting the application code into microservices. ![Diagram comparing single VM SaaS architecture with multi-VM SaaS architecture](https://raff-images.s3.raffusercloud.com/single_vm_vs_multi_vm_comparison_diagram_webp_979f6a655a.png) A monolithic application might use: ```text Users ↓ Application VM ↓ private network Database ↓ Object storage and background workers ``` The app and workers may still run the same codebase with different commands. Infrastructure separation allows each role to have its own capacity, access, deployment, and recovery boundaries. ## Choose the first split from the evidence The database is a common first split because it owns durable business data, but it is not automatically first for every application. | Observed constraint | Likely first split | |---|---| | Database memory, storage, backup, or maintenance risk | Database | | CPU-heavy jobs delay web requests | Background workers | | Durable uploads block VM replacement or horizontal scaling | Object storage | | Cache or queue is critical and competes with the app | Cache or queue | | One app node cannot meet traffic or availability needs | Additional app nodes and load balancing | | Security policy requires separate access boundaries | Sensitive backend role | | App deployment must not affect scheduled jobs | Worker or scheduler | Select one change, migrate it safely, and confirm that the user-facing or operational result improves before continuing. ## Split the database when data needs an independent boundary Separate the database when its lifecycle no longer matches the application server. Useful triggers include: - database storage grows independently of application compute - backups or maintenance affect the application - the database needs stricter network and administrator access - the app VM should be replaceable without moving customer records - database memory and disk behavior require independent tuning - database recovery objectives differ from app-server recovery ```text Users ↓ Application VM ↓ private network Database VM or managed database ``` The split creates a clearer data boundary, but it also introduces network latency, credentials, connection management, and a second failure domain. Measure connection usage and query behavior after migration. Use [Separate App and Database Server](/learn/guides/separate-app-database-server) for the detailed decision. ## Move durable files away from replaceable compute Local application storage is simple on one VM, but it can block later scaling. When user uploads exist only on one app server: - another app node may not see the file - replacing the VM requires copying durable data - app-server backups grow with file volume - storage and compute cannot scale independently - failed uploads and partial processing are harder to reconcile A cleaner model is: ```text Application VM ↓ Database stores file metadata ↓ Object storage stores durable objects ``` Keep disposable temporary files local when bounded and safe to recreate. Move customer uploads, exports, media, and other durable objects to shared storage when they must survive app-node replacement. ## Separate workers when background work affects users Background jobs often have a different resource and failure profile from web traffic. Workers may process: - emails and notifications - reports and exports - imports - image or document processing - billing tasks - integration synchronization - scheduled cleanup A separate worker VM is justified when job execution consumes enough CPU, memory, database capacity, or deployment attention to affect the user-facing app. ```text Web or API VM ↓ Queue or job store ↓ Worker VM ``` The worker design must handle retries, duplicate execution, job ownership, and graceful shutdown. Adding workers without database and dependency headroom can create a new bottleneck. ## Separate cache or queue when it becomes critical state A small local cache may remain on one VM. A cache or queue deserves an independent boundary when its failure, memory usage, or restart behavior has meaningful product impact. Review: - whether the data is disposable or authoritative - whether several app and worker nodes need shared access - memory growth and eviction behavior - queue persistence and retry semantics - connection limits - recovery after restart Do not move a cache merely because a multi-server diagram includes one. Split it when the application needs independent scaling, shared access, or failure control. ## Add multiple app VMs only after externalizing state Horizontal app scaling requires requests to move safely between nodes. Before adding app servers, externalize or deliberately manage: - user sessions - uploaded files - background jobs - scheduled tasks - required cache state - configuration and secrets - application logs and metrics Microsoft’s scale-out guidance recommends avoiding instance stickiness and resolving backend bottlenecks before adding instances. AWS similarly recommends offloading state so servers can be replaced without availability impact. Use [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) before adding a load balancer. ## Load balancing adds routing, not complete availability A load balancer can distribute new traffic and remove unhealthy app nodes from rotation. It does not automatically make the database, storage, DNS, application deployment, or load-balancer layer resilient. A multi-node app tier needs: - meaningful readiness checks - externalized state - connection draining - compatible deployments - enough remaining capacity after one node fails - shared observability - database connection planning ```text Users ↓ Load balancer ↓ App VM 1 App VM 2 ↓ private network Database, cache, queue, and storage ``` Use [Load Balancing Explained](/learn/guides/load-balancing-explained) for L4, L7, health-check, timeout, and failover decisions. ## More VMs do not automatically create high availability Role separation and redundancy are different architectural choices. A separate database VM isolates resources but remains one database node. Two app VMs improve the app tier only if traffic routing, state, and remaining capacity are designed correctly. Several roles may still depend on one network, credential, deployment pipeline, or storage system. Review each failure domain: - app node - worker - database - queue or cache - object storage - load balancer - DNS - external dependencies - shared configuration and secrets Multi-VM architecture improves isolation when boundaries are intentional. It can also create more failure modes when ownership and recovery are unclear. ## Compare cost by role and risk A multi-VM design has a higher visible infrastructure cost, but it may avoid scaling every role together. On one VM, a worker CPU spike can force a larger plan for the app, database, and cache at the same time. After separation, worker capacity can change without resizing the database. The reverse can also be true: several lightly used VMs may cost more and create unnecessary operations. Evaluate: - infrastructure spend by role - expected downtime cost - recovery time - engineering and on-call time - deployment risk - unused capacity - monitoring and tooling overhead Use current product and pricing pages during implementation rather than embedding temporary plan prices in an evergreen architecture decision. ## A staged SaaS topology path The architecture should evolve one justified boundary at a time. ![Raff SaaS architecture path from one VM to managed database, object storage, workers, and load balancing](https://raff-images.s3.raffusercloud.com/raff_saas_architecture_scaling_path_webp_b9ede7d183.png) ### Stage 1: One VM ```text Application + database + worker + cache ``` Priorities: - production baseline - monitoring - backup and restore - clear service ownership - documented separation triggers ### Stage 2: Separate the most valuable boundary This may be the database, worker, files, or another role according to measured risk. ```text Application VM ↓ Separated role ``` ### Stage 3: Externalize durable and shared state Move sessions, files, jobs, and other state that would prevent application-node replacement. ### Stage 4: Add independent capacity Scale the database, workers, or other role according to its own workload. ### Stage 5: Add multiple app nodes Introduce load balancing when traffic, deployment safety, maintenance, or app-tier availability requires more than one node. The next stage should solve a current constraint. It should not exist only because the diagram looks more mature. ## Private networking becomes important after separation Once services are separated, internal traffic should use controlled private paths where available. Raff VPC can connect VMs and supported managed services through private networking. A common topology is: ```text Public internet ↓ Load balancer or application entry point ↓ private network Application, database, workers, cache, and internal services ``` Private networking reduces unnecessary public exposure, but it does not replace firewall rules, authentication, encryption, database permissions, or application security. ## Use a migration plan for every split A role split should have a defined sequence: 1. Measure the existing workload and define success. 2. Create the new role and restrict access. 3. Configure monitoring, backups, and ownership. 4. Synchronize or migrate state where required. 5. Test with production-like behavior. 6. Cut traffic or processing over deliberately. 7. Observe latency, errors, resource use, and recovery signals. 8. Keep a rollback path until the result is stable. 9. Remove obsolete data, credentials, rules, and services. Do not split several stateful roles in one change unless the migration requires it. Smaller changes make cause and rollback clearer. ## Single VM vs multi-VM decision matrix | Evidence | Better next move | |---|---| | No measured contention or recovery problem | Keep one VM | | One resource is constrained but roles remain compatible | Resize vertically | | Database needs independent recovery or tuning | Separate database | | Workers affect user-facing latency | Separate workers | | Durable files block replacement | Move files to object storage | | App node must be replaceable | Externalize state | | One app node is the capacity boundary | Add app nodes and load balancing | | One app node is the availability boundary | Add redundancy and failure capacity | | Team cannot operate several roles safely | Improve automation and observability first | Use [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) when the main decision is resize versus add instances. ## How this applies on Raff A Raff topology can combine: - [Raff Cloud Servers](/products/raff-vm) for application and worker roles - [Managed Databases](/products/managed-databases) when the database should have a separate managed boundary - [Object Storage](/products/object-storage) for durable shared files - [Load Balancers](/products/load-balancers) for multi-node app traffic - [Raff VPC](/products/vpc) for controlled private communication - [Data Protection](/products/data-protection) according to recovery needs Choose only the components the workload currently needs. Verify current capabilities and pricing on the live product pages before implementation. ## Pre-split checklist ### Evidence - The current bottleneck or risk is measured. - The role being separated has a clear owner and purpose. - Success criteria are defined. ### State and data - Durable data has an authoritative location. - Sessions, uploads, and jobs are mapped. - Backup and restore behavior is documented. ### Operations - Monitoring exists for the new role. - Access and private-network rules are defined. - Deployment and maintenance ownership are clear. - The team can diagnose cross-service failures. ### Migration - Data synchronization and cutover are planned. - Rollback is possible. - Obsolete services and credentials will be removed. - The architecture diagram and runbooks will be updated. :::cluster ## Conclusion Single-VM architecture is often the correct starting point for a SaaS application. Multi-VM architecture becomes valuable when one shared server creates unacceptable contention, failure exposure, deployment coupling, or recovery risk. Do not split every role at once. Identify the constraint, separate the role that removes it, validate the result, and keep the application model as simple as the product allows. A monolith can remain a monolith while its database, workers, files, and app tier gain clearer operational boundaries. The best topology is the smallest one that meets the workload’s current performance, reliability, security, and recovery requirements. :::cta Explore Raff VM Start with a clear cloud foundation, then separate roles as measured production needs emerge. ::: ## Sources - [Microsoft Azure Architecture Center: Design to Scale Out](https://learn.microsoft.com/en-us/azure/architecture/guide/design-principles/scale-out) - [Microsoft Azure Well-Architected Framework: Scaling and Partitioning](https://learn.microsoft.com/en-us/azure/well-architected/performance-efficiency/scale-partition) - [AWS Well-Architected: Make Systems Stateless Where Possible](https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_mitigate_interaction_failure_stateless.html) - [Raff Cloud Servers](/products/raff-vm) - [Raff VPC](/products/vpc) --- ### Object Storage vs Block Storage vs VM Disk: How to Choose URL: https://rafftechnologies.com/learn/guides/object-storage-vs-block-storage-vs-vm-disk Description: Compare object storage, block storage, and VM disk by access model, workload fit, scaling, and recovery needs to choose the right cloud storage layer. Object storage, block storage, and VM disk solve different storage problems. **VM disk** is the system or data disk attached to one virtual machine. **Block storage** presents raw disk capacity that an operating system can format and mount. **Object storage** keeps files as API-addressable objects inside buckets rather than exposing a normal filesystem. The important nuance is that VM disk and block storage are not always separate technologies. A VM disk is commonly presented to the operating system as a block device. In architecture decisions, however, “VM disk” describes data that is operationally coupled to one server, while an attached block volume and an object bucket create clearer storage boundaries. For teams using Raff Technologies, this guide answers the practical question: **what should live on the VM disk, what belongs on an attached volume, and what should move into object storage?** For the wider production model that also covers backups and restore testing, read [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps). ## The quick storage decision Use this framework before choosing a storage layer. | Workload or data | Better default | Why | |---|---|---| | Operating system and packages | VM disk | They belong to the server runtime | | Application code and deployment files | VM disk | They should be reproducible from source or build artifacts | | Temporary processing files | VM disk or block volume | The choice depends on size, lifetime, and disk pressure | | Self-hosted database data | Block volume or managed database | The workload expects disk and filesystem semantics | | Persistent container data | Block volume | State must survive container recreation | | User uploads and media | Object storage | Files should scale separately from the app server | | Reports, exports, and build artifacts | Object storage | They are durable file objects, not server runtime | | Backup exports and archives | Object storage | Retention should not depend on the source VM | | Short-term recovery point | Snapshot or backup product | Primary storage and recovery points solve different problems | A useful default is: > Use VM disk for runtime, block storage for disk-like persistent data, and object storage for durable files accessed through an API. This is a starting point, not an absolute rule. The correct choice depends on how the application reads the data, how independently the data must grow, and what the recovery plan requires. ## Object storage and block storage use different access models The defining difference is not capacity. It is how applications access and modify data. [Amazon Web Services describes block storage](https://aws.amazon.com/compare/the-difference-between-block-file-object-storage/) as data divided into addressable blocks, while object storage keeps data as objects with identifiers and metadata. [Google Cloud’s storage comparison](https://cloud.google.com/discover/object-vs-block-vs-file-storage) makes the same distinction and separates both models from shared file storage. ### Block storage behaves like a disk A block volume appears to the operating system as a disk device. You create a filesystem, mount it, and let software read or write through normal disk operations. That makes block storage a strong fit for: - PostgreSQL, MySQL, MongoDB, and other self-hosted databases - Docker or container data directories - Stateful applications that require a mounted path - Search indexes and application state - Large processing workspaces - Data that needs to grow separately from the VM system disk The application usually does not need to understand a storage API. It writes to a filesystem path, and the operating system handles the underlying blocks. ### Object storage behaves like an API service Object storage keeps data in buckets. Applications upload and retrieve objects by key through HTTP and an object-storage API such as S3. That makes object storage a strong fit for: - User uploads - Images, audio, video, and documents - Static assets - Generated reports and exports - Backup archives - Logs and artifacts kept for longer retention - Files that several app servers or workers need to access Object storage is not a drop-in replacement for a database data directory or an application that expects a normal mounted disk. The application must use an object-storage client, SDK, command-line tool, or compatible integration. ## VM disk is a lifecycle decision A VM disk is the disk attached to the virtual machine for its operating system and local data. From inside Linux or Windows, it behaves like a normal disk. Operationally, the important question is whether the data should remain coupled to that server. VM disk is the simplest choice when the data belongs to the machine itself: - Operating system - Packages and dependencies - Application runtime - Service configuration - Controlled local logs - Caches - Temporary files - Rebuildable application assets For a prototype or a small single-server application, the VM disk can also hold a modest database or small set of files. That can be a reasonable starting point when the team understands the trade-off. The model becomes risky when the same disk turns into the permanent home for everything: ```text VM disk ├── operating system ├── application ├── database ├── user uploads ├── reports ├── logs └── backup archives ``` In that layout, one full disk can affect the whole application. Storage growth can force a compute resize. Rebuilding or replacing the VM also becomes a data-migration event. Backup and restore scope becomes harder to explain. The decision is therefore not “Is VM disk bad?” It is “Which data should remain tied to this VM?” ## Block storage is for persistent filesystem data Choose an attached block volume when software needs a disk but the data deserves a clearer boundary than the system disk provides. A common layout is: ```text VM system disk └── OS, packages, application runtime Attached block volume └── database files, container state, application data ``` This separation is valuable when: - Storage needs to grow without adding CPU or RAM - A database or service needs a dedicated mount path - Persistent container data should be separated from the host runtime - Disk usage, ownership, and recovery need clearer monitoring - The team may replace or rebuild the app VM independently Block storage does not remove operational responsibility. A self-hosted database still needs database-aware backups, restore tests, monitoring, capacity planning, and a safe upgrade process. A volume stores active data; it is not automatically a historical recovery copy. For the narrower volume decision, read [Block Storage Volumes for Databases, Containers, and App Data](/learn/guides/block-storage-volumes-databases-containers-app-data). ## Object storage is for durable file objects Choose object storage when files should exist independently from any single app server and the application can access them through an API. A common SaaS pattern is: ```text Application VM ├── validates the request └── stores object metadata in the database Object storage └── stores the uploaded file ``` The database might keep the owner, object key, filename, size, content type, access status, and creation date. The bucket stores the actual file. This model is valuable when: - User files are part of the product - Upload growth is unpredictable - Multiple app instances need the same files - Workers or functions process the same inputs and outputs - Files must remain available when the app VM is rebuilt - Reports, exports, or archives need their own retention policy - VM backups should not grow with every uploaded file Object storage can also act as the retained destination for database dumps and backup artifacts. The database itself still needs an appropriate primary storage layer and a tested restore procedure. For the upload-specific decision, read [App Uploads: VM Disk vs Object Storage for SaaS Teams](/learn/guides/app-uploads-vm-disk-vs-object-storage). ## VM disk is not the same as shared file storage Searches for object storage vs block storage often include **file storage** as the third model. File storage exposes a shared hierarchical filesystem through protocols such as NFS or SMB. Multiple clients can access folders and files through familiar paths and permissions. A VM disk also contains a filesystem, but it is not automatically shared file storage. It is normally attached to one VM. You could run a file server on that VM, but then your team owns the file-serving layer, availability model, permissions, backups, and scaling. Choose shared file storage when several systems need normal filesystem paths and existing applications cannot use object APIs. Choose object storage when applications can work with buckets and object keys. Choose block storage when one workload needs a disk device and filesystem it controls. Raff’s current public storage choices in this decision are [Raff Volumes](/products/volumes) for attached block storage and [Raff Object Storage](/products/object-storage) for S3-compatible object storage. ## Performance depends on the workload’s access pattern “Which storage is faster?” is too broad to guide architecture. Block storage is designed for workloads that perform frequent reads and writes through a filesystem or database engine. Databases, container state, and transactional applications depend on that behavior. Object storage is designed around complete objects and API operations. It fits files that are uploaded, downloaded, listed, retained, or shared as objects. It is not intended to provide low-level disk access to a database engine. VM disk performance depends on the underlying disk implementation and the VM plan. Its architectural advantage is simplicity. Its limitation is that runtime, persistent state, and capacity can become coupled unless the team separates them deliberately. Use these questions instead of asking which option is fastest: 1. Does the software expect a mounted filesystem or raw disk? 2. Does it frequently update small parts of existing data? 3. Is the data naturally handled as complete files or objects? 4. Must several servers access the same files? 5. Should storage capacity grow separately from compute? 6. What must be restored after the VM is rebuilt? The answers usually make the correct storage model clear. ## Recovery requirements should shape the choice Primary storage and backups are different layers. A VM disk, attached volume, or object bucket holds active data. Snapshots and backups create recovery points. Replication or infrastructure durability cannot recover the correct previous state after every accidental deletion, bad migration, or application-level corruption. For each data set, define: - Which system is the source of truth? - Can the data be recreated? - How much data loss is acceptable? - How quickly must the workload return? - Where are recovery copies stored? - Has the restore path been tested? Examples: | Data | Primary layer | Recovery consideration | |---|---|---| | OS and app runtime | VM disk | Rebuild from documented deployment process | | Self-hosted database | Block volume or VM disk | Use database-aware backups and restore tests | | User uploads | Object storage | Define access, retention, deletion, and recovery rules | | Temporary workspace | VM disk or volume | Recreate or clean up; backup may be unnecessary | | Backup archive | Object storage | Verify retention and test the restore workflow | Raff separates these responsibilities across [Raff VM](/products/raff-vm), [Raff Volumes](/products/volumes), [Raff Object Storage](/products/object-storage), and [Raff Data Protection](/products/data-protection). The architecture is strongest when each layer has one clear job. ## Most production applications use more than one layer The choice is rarely object storage **or** block storage **or** VM disk for the entire system. A production application commonly uses all three. ```text Raff VM disk └── OS, packages, app runtime, temporary files Raff Volume └── self-hosted database or persistent container data Raff Object Storage └── uploads, reports, media, exports, archives Raff Data Protection └── snapshots, backups, retention, recovery workflow ``` This separation reflects a decision Raff makes at the platform level: storage should follow data behavior instead of forcing every byte into the server’s lifecycle. Compute can then change for compute reasons, while file capacity and persistent disk capacity can change according to their own workloads. Start simpler when the workload is small. Add separation when it reduces a real risk: disk pressure, recovery scope, multi-server access, data growth, or operational ownership. ## Common storage mistakes ### Treating every file as block-storage data A mounted volume can store uploads, but that does not make it the best long-term home for them. Files shared across app servers or accessed as complete objects usually fit object storage better. ### Treating object storage like a normal disk Object storage requires API-aware application behavior. Do not place a database data directory or ordinary filesystem-dependent application directly in a bucket. ### Assuming a separate volume is a backup A volume creates a storage boundary. It does not provide historical recovery by itself. Protect active data with an appropriate backup and restore plan. ### Resizing compute only because storage is full When disk capacity grows faster than CPU and RAM needs, separate storage may be cleaner than moving the whole workload to a larger VM plan. ### Keeping retained backups on the source VM A backup copy that depends on the same server and disk as the source has a weak failure boundary. Retained copies should follow a recovery design that survives loss of the source workload. ## Choose the storage layer by data behavior Use **VM disk** for the operating system, application runtime, controlled logs, caches, and temporary or rebuildable data. Use **block storage** when a database, container, or stateful application needs persistent filesystem behavior. Use **object storage** for uploads, media, reports, exports, artifacts, and backup files that should scale separately from compute. Then design snapshots, backups, retention, and restore tests around those primary layers. The goal is not to use every product. It is to give each important data set a clear owner, access model, growth path, and recovery path. Continue with [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps) to place these storage choices inside a complete production recovery design. :::cta Explore Object Storage Store uploads, media, reports, exports, and retained backup objects outside the VM when they need to scale independently from compute. ::: --- ### Microservices vs Monolith: A Decision Framework for Small Teams URL: https://rafftechnologies.com/learn/guides/monolith-vs-microservices-small-teams Description: Compare microservices vs monolith for small teams, including modular monoliths, scaling, ownership, data boundaries, operational cost, and migration signals. Microservices vs monolith is the decision between deploying an application as one coordinated unit and splitting it into independently deployable services. **Most small teams should begin with a modular monolith, then extract services only when a measured scaling, ownership, release, or failure-isolation problem is worth the added distributed-systems cost.** A monolith is not automatically one server, one process, or badly structured code. A monolithic application can have clear internal modules, separate workers, multiple application instances, and independently managed database and storage infrastructure while remaining one primary deployment unit. Microservices create separate deployment and ownership boundaries. That can improve independent scaling and team autonomy, but it also adds network failure, service contracts, observability, data consistency, deployment coordination, and on-call responsibility. This guide owns the software-architecture decision. For infrastructure topology, read [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture). For state placement, read [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications). ## Microservices vs monolith at a glance | Decision factor | Monolith | Microservices | |---|---|---| | Deployment unit | One coordinated application release | Several independently deployable services | | Initial delivery speed | Usually faster | Usually slower | | Debugging | More activity remains in one process or codebase | Requests may cross several services | | Data transactions | Easier inside one database boundary | Often require events, sagas, or reconciliation | | Independent scaling | Coarser | Stronger by service | | Team ownership | Shared application ownership | Service-level ownership | | Failure modes | Fewer network boundaries, wider app-level blast radius | Better isolation when designed well, more partial failures | | Testing | Simpler end-to-end environment | More contract and integration testing | | Infrastructure overhead | Lower | Higher | | Best fit | Small teams, changing domains, shared release cadence | Stable domains, multiple teams, clearly different scale or reliability needs | A useful rule is: > Choose the architecture your team can deploy, observe, recover, and change safely every week—not the one that looks most mature on a diagram. ## The real choice includes three architecture models The decision is not limited to a messy monolith or dozens of microservices. Small teams should compare three practical models. ### A traditional monolith A traditional monolith keeps most application capabilities in one codebase and deployable unit. Modules may exist, but boundaries are often informal. This model is valuable when: - the product is early - one team owns the application - business rules change frequently - deployment and debugging simplicity matter most - traffic can be handled by resizing or duplicating the whole application The risk is uncontrolled coupling. If every module reads every table and calls internal code without boundaries, the application can become difficult to change even before it becomes large. ### A modular monolith A modular monolith remains one deployable application but enforces internal domain boundaries. Each module should have: - a clear business responsibility - controlled public interfaces - limited access to another module’s internals - explicit ownership of data and business rules - tests around module contracts A modular monolith preserves simple deployment while making future extraction possible. It is usually the strongest default for a small SaaS team because it avoids distributed-systems overhead without treating the codebase as one undifferentiated block. ### Microservices A microservices architecture splits business capabilities into independently deployable services. Services communicate through APIs, events, queues, or streams and normally own their runtime and data boundaries. Microservices become valuable when independence creates a measurable benefit: - one capability needs a different release cadence - one workload scales very differently - separate teams need clear ownership - one failure should not interrupt unrelated capabilities - a domain has stable boundaries and a distinct lifecycle - regulatory or security requirements justify stronger isolation The service boundary must solve a real problem. A service that cannot be changed, deployed, or recovered independently is often only a network boundary without the expected benefit. ## Architecture model is not infrastructure topology A monolith does not require one VM. Microservices do not require Kubernetes. Multi-VM does not automatically mean microservices. A monolithic application can use: ```text Load balancer ↓ App VM 1 App VM 2 ↓ private network Managed database ↓ Object storage + workers ``` The same application artifact can run on several nodes. The database, workers, files, cache, and application tier can be separated operationally without splitting the source code into services. Likewise, several small services can run on one VM during development or early production. They are still microservices if they have meaningful independent boundaries, although sharing one host limits failure isolation and scaling independence. Use [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) when the problem is resource placement or failure domains. Use this guide when the problem is code, deployment, ownership, and domain boundaries. ## Monoliths are usually faster for small teams The main advantage of a monolith is not raw application performance. It is lower coordination cost. A small team can often: - change a workflow in one codebase - run one primary test suite - deploy one application version - trace a request without distributed tracing - use normal database transactions - refactor domain boundaries before they become public service contracts - maintain one main local-development environment This matters while product scope is changing. Early domain assumptions are often wrong. A boundary that looks obvious in month one may disappear in month six. Keeping the boundary inside one codebase makes correction cheaper. The best monolith is not careless. It should still have modules, ownership, automated tests, repeatable deployments, controlled configuration, and a documented data model. ## Microservices charge an operational premium Microservices replace in-process calls with distributed communication. That creates new concerns even when every service is small. A production microservices platform usually needs deliberate answers for: - service discovery and routing - authentication between services - timeouts and retries - duplicate message handling - idempotency - API and event versioning - distributed tracing - centralized logs and metrics - deployment ordering - data consistency across services - secret distribution - ownership and escalation - partial failure and degraded operation A function call either returns or fails inside one process. A network call may time out after the remote service completed the action. Retrying may create duplicate work. One service may be healthy while a dependency is slow. An old producer may send an event that a new consumer interprets differently. This premium is justified only when service independence is valuable enough to pay for it continuously. ## Use a seven-part decision framework A small team should evaluate the decision across seven areas rather than asking which architecture scales better in theory. ### 1. Product and domain stability Choose a monolith or modular monolith when: - the product model is still changing - domain boundaries are uncertain - features frequently cross several business areas - the team expects significant refactoring Consider microservices when domain boundaries have remained stable and teams can explain each service in business terms without relying on technical layers such as “frontend service” or “database service.” ### 2. Team structure and ownership Microservices work best when each important service has an owner who can deploy, monitor, and recover it. A one-to-five-person team usually gains more from shared context than service autonomy. If everyone still works across the whole product, splitting the codebase may add coordination without creating real ownership. Consider extraction when: - several teams work independently - repository and release coordination blocks delivery - ownership is clear after incidents - the team can maintain service standards without a dedicated platform group becoming a bottleneck ### 3. Scaling differences Do not choose microservices because the application may become popular. Identify a component with a different measured scale profile. Useful signals include: - media processing consumes far more CPU than the API - search traffic grows independently from transactions - one integration creates large asynchronous bursts - a reporting workload needs separate memory or scheduling - one service requires geographically different placement Before extracting code, check whether separate workers, queues, databases, storage, or application nodes solve the problem with less complexity. ### 4. Release independence Microservices help when capabilities genuinely need independent releases. Ask: - Do unrelated changes wait for one release train? - Does deploying one capability create risk for the whole application? - Do teams need different maintenance windows? - Can the proposed service remain backward compatible while clients update? If every release still requires coordinated changes across several services, the architecture may become a distributed monolith. ### 5. Failure isolation Service boundaries can limit blast radius, but only when dependencies and fallbacks are designed deliberately. A separate service does not improve resilience when every request fails if that service is unavailable. Effective isolation may require: - timeouts - circuit breaking - queues - cached or degraded responses - bulkheads and capacity limits - independent data recovery - failure-aware user flows Use a service boundary when the product can define what continues to work during partial failure. ### 6. Data ownership and consistency A monolith can use one database transaction across several modules. Microservices should avoid shared-table coupling and normally need explicit data ownership. Before extracting a service, answer: - Which service is authoritative for each record? - How do other services receive changes? - What happens when an event is delayed or duplicated? - Can the workflow tolerate temporary inconsistency? - How are cross-service reports built? - How are migrations and rollbacks coordinated? If the team cannot define data ownership, the code boundary is not ready to become a service boundary. ### 7. Operational maturity Microservices require reliable platform practices. Minimum readiness usually includes: - automated deployments - centralized logs and metrics - trace or correlation IDs - health and readiness checks - secret management - service-level alerts - documented ownership - tested rollback and recovery - API or event contract testing - controlled dependency versions When these capabilities are weak, improve them on the monolith first. The same practices will make later extraction safer. ## Decision matrix for small teams | Current evidence | Better default | |---|---| | One team owns the product | Modular monolith | | Product boundaries change frequently | Modular monolith | | One deployment remains fast and safe | Monolith | | Scaling the whole app is still affordable and reliable | Monolith | | One worker is CPU-heavy | Separate worker process or VM first | | User uploads block horizontal scaling | Move files to object storage first | | Database operations are the bottleneck | Separate or manage the database first | | Multiple teams block each other in one release | Consider service extraction | | One domain has a sharply different scale profile | Consider service extraction | | One capability needs independent security or failure isolation | Consider service extraction | | Cross-service transactions dominate the design | Keep the boundary internal longer | | Observability and ownership are unclear | Improve operations before microservices | The smallest change that solves the measured problem is usually the best next step. ## Avoid the distributed monolith A distributed monolith has several services but keeps the coupling of one application. Warning signs include: - services must be deployed in a fixed order - one feature requires changes in many repositories - several services share the same database tables - one synchronous request passes through many internal services - service versions cannot coexist - one outage stops the complete product - local development requires starting the whole platform - ownership remains shared and unclear This architecture pays for network and operational complexity without gaining deployment independence or failure isolation. When a proposed service cannot own its data, contract, deployment, and recovery path, keep it as an internal module until the boundary becomes stronger. ## A modular monolith needs enforced boundaries Calling an application modular does not make it modular. Boundaries need technical enforcement. Useful practices include: - organize code by business capability rather than technical layer - expose a small interface from each module - prevent direct access to another module’s internal classes or tables - publish internal domain events when loose coupling helps - keep cross-module calls visible and testable - assign database ownership even when tables share one database server - test module contracts - document dependency direction A simple module map might look like: ```text Accounts Billing Catalog Orders Notifications Reporting ``` `Orders` may request payment through `Billing` without reading billing tables directly. `Notifications` may consume an internal event rather than being called from every workflow. The application still deploys as one unit, but the boundaries create a safer path for future extraction. ## Extract services from proven seams The first service should not be the most central capability. It should have a clear boundary and a recoverable failure model. Good early candidates often include: - asynchronous media processing - report generation - external integrations - email or notification delivery - search indexing - import and export processing - isolated billing workflows when ownership and consistency are mature These workloads often have distinct scaling or reliability needs and can communicate asynchronously. Riskier first extractions include: - authentication used by every request - a generic “user service” with unclear ownership - shared database access wrapped in an API - highly transactional workflows split across several services - tiny services created around technical utility classes Extract one boundary, validate the operating model, and leave the rest of the application monolithic until another boundary earns separation. ## Use a staged evolution path ### Stage 1: Build one deployable application Start with a production-ready monolith: - automated build and deployment - monitoring and logs - backups and restore planning - controlled configuration and secrets - clear internal modules ### Stage 2: Separate runtime roles Run web, worker, scheduler, database, cache, and file storage according to their operational needs without changing the main codebase into microservices. ```text Web process Worker process Scheduler Shared database Object storage ``` These roles may run on separate Raff Cloud Servers or suitable managed services while using the same repository and release version. ### Stage 3: Strengthen module and data boundaries Track ownership, remove direct cross-module data access, add internal contracts, and make modules testable independently. ### Stage 4: Extract one proven service Choose a capability with clear ownership and a measurable benefit. Define its API or events, data ownership, deployment, monitoring, and rollback before moving production traffic. ### Stage 5: Keep a hybrid architecture A healthy system may remain a modular monolith with a small number of extracted services for years. The target is not maximum service count. The target is the right boundary for each capability. ## Cost should include engineering and recovery work Microservices can use infrastructure more efficiently when individual services scale differently. They can also increase total cost through duplicated capacity and operational tooling. Include: - compute for each service and environment - database, cache, queue, and storage capacity - load balancing and networking - logs, metrics, and traces - CI/CD execution - development and test environments - engineering time for platform maintenance - on-call and incident coordination - recovery testing A modular monolith may use more compute than a perfectly optimized service architecture at high scale, but it can still be cheaper overall for a small team because development and operations remain simpler. Use current Raff product and pricing pages during implementation rather than embedding temporary plan prices in an evergreen architecture decision. ## Security boundaries become more numerous A monolith usually has fewer internal trust boundaries. Microservices create more identities, credentials, network paths, and authorization decisions. A microservices security model should address: - service identity - least-privilege credentials - private network exposure - transport encryption where required - API authorization - secret rotation - audit logging - dependency and image updates - compromised-service containment Private networking reduces unnecessary public exposure but does not replace service authentication or authorization. Do not split services only to improve security unless the new boundary has a clear access policy and an owner who can maintain it. ## How this applies on Raff Raff supports both simple and gradually separated application architectures. A modular-monolith path can use: - [Raff Cloud Servers](/products/raff-vm) for the application and worker roles - [Managed Databases](/products/managed-databases) when database operations need a separate managed boundary - [Object Storage](/products/object-storage) for uploads, reports, and durable files - [Load Balancers](/products/load-balancers) when several replaceable app nodes serve traffic - [Raff VPC](/products/vpc) for controlled private communication - [Data Protection](/products/data-protection) according to recovery needs A microservices architecture can use the same building blocks, but it should add services only when each boundary has independent ownership, deployment, observability, and recovery. A practical Raff evolution path is: ```text Modular monolith on one cloud server ↓ Separate database, files, or workers when measured needs emerge ↓ Add multiple app nodes when the application tier must scale or tolerate maintenance ↓ Extract one proven domain when software-level independence creates value ``` This keeps infrastructure and software architecture decisions separate. A team can gain better scaling and recovery boundaries before paying the full microservices premium. ## Architecture readiness checklist ### Stay with a modular monolith when - one team still owns most of the product - domain boundaries continue to change - one release process is efficient - whole-application scaling remains practical - shared transactions simplify important workflows - distributed observability is not mature ### Consider a service extraction when - the domain boundary is stable - one owner can operate it end to end - independent deployment solves a real bottleneck - scaling requirements are materially different - the service can own its data - partial failure behavior is defined - contract compatibility is testable - monitoring and recovery are ready ### Stop before extraction when - the service would share database tables - every release still requires coordinated changes - the boundary is based only on a framework or technical layer - the team cannot support another production runtime - the expected benefit is only “future scalability” without evidence :::cluster ## Conclusion Microservices vs monolith is a decision about operational and organizational boundaries, not architectural fashion. For most small teams, a modular monolith is the better starting point. It preserves fast delivery, simple debugging, normal transactions, and cheap refactoring while the product and domain are still changing. Move toward microservices when a proven boundary needs independent scaling, deployment, ownership, security, or failure isolation—and when the team can operate the resulting distributed system safely. Extract one service at a time, measure the result, and keep the rest monolithic until another boundary earns independence. :::cta Explore Raff VM Start with a clear cloud foundation and separate application roles or services only as measured production needs emerge. ::: ## Sources - [AWS: Monolithic vs Microservices Architecture](https://aws.amazon.com/compare/the-difference-between-monolithic-and-microservices-architecture/) - [Microsoft Azure Architecture Center: Microservices Architecture Style](https://learn.microsoft.com/en-us/azure/architecture/guide/architecture-styles/microservices) - [Martin Fowler: Monolith First](https://martinfowler.com/bliki/MonolithFirst.html) - [Raff Cloud Servers](/products/raff-vm) --- ### SaaS Infrastructure Cost: From MVP to Series A URL: https://rafftechnologies.com/learn/guides/saas-infrastructure-cost-breakdown Description: Build a stage-based SaaS infrastructure budget from MVP to Series A across compute, databases, storage, environments, recovery, and operating cost. SaaS infrastructure cost is the recurring cost of running, protecting, delivering, and operating a software product in the cloud. It includes more than the application server: databases, storage, backups, non-production environments, networking, observability, delivery tooling, security controls, and the engineering time required to keep the system reliable. The cost model should change as the company changes. **An MVP should pay for the smallest operationally safe architecture. Early production should add protection around customer data and releases. A growing SaaS should measure cost by workload and customer value before adding redundancy, platforms, or permanent capacity.** There is no universal monthly budget that fits every SaaS company. A file-heavy product, real-time API, internal business tool, and analytics platform can have completely different cost shapes at the same customer count. The useful question is not “What should a SaaS spend?” It is: > Which infrastructure costs are required by the product’s current workload, customer commitments, and recovery expectations—and which costs exist only because architecture has drifted? For the full breakdown of an individual server bill, read [Cloud Server Pricing: What Actually Drives Monthly Cost](/learn/guides/cloud-server-cost-2026). This guide owns the stage-based budgeting decision from MVP through Series A readiness. ## SaaS infrastructure cost at a glance | Company stage | Main infrastructure goal | Typical cost risk | Better budgeting focus | |---|---|---|---| | Prototype | Validate the technical idea | Paying for production controls before demand exists | Temporary resources and easy cleanup | | MVP | Ship and learn safely | Premature platforms and environment duplication | One clear production path, backup, and basic visibility | | Early production | Protect real customers and data | Staying on a fragile single setup for too long | Recovery, database ownership, staging, and monitoring | | Growth | Scale the constrained role | Scaling every component together | Workload-level measurement and selective separation | | Pre-Series A | Improve reliability and operating leverage | Permanent idle capacity and unmanaged service sprawl | Unit economics, ownership, standards, and forecasts | | Series A readiness | Make cost and reliability predictable | Enterprise-pattern adoption without measurable value | Cost allocation, capacity planning, and controlled commitments | The objective is not to keep the cloud bill flat. Healthy infrastructure cost can rise with customers, usage, data, and reliability. The objective is to ensure that cost grows for explainable reasons. ## SaaS infrastructure cost includes nine layers A founder may first see one VM or platform subscription on the invoice. Production cost expands across several layers. ### Compute Compute includes application servers, workers, scheduled jobs, build runners, container nodes, and any processing capacity used by the product. Compute cost usually depends on: - vCPU and memory - compute class - number of instances - minimum always-on capacity - development and staging copies - burst or peak requirements - commitment term Compute is visible, which makes it easy to optimize first. It is not always the largest or fastest-growing cost. ### Database and state Databases often become more important than application compute once customers depend on the product. Cost may include: - database compute and memory - primary storage - transaction logs - replicas - connection pooling - backups and point-in-time recovery - monitoring - maintenance and operator time A self-hosted database may have a lower visible service price while requiring more internal operations. A managed database may cost more directly while reducing some host-level responsibility. Use [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) when that responsibility boundary becomes the main decision. ### Block and object storage Storage cost grows through database files, uploaded files, reports, exports, container images, build artifacts, logs, backups, and snapshots. Separate data according to behavior: - VM disk for the operating system, runtime, and controlled local data - block storage for persistent disk-like workloads - object storage for uploads, media, exports, and retained files - backup and snapshot systems for recovery points Storage capacity can grow while CPU demand remains stable. Keeping all data on the application VM can force an unnecessary compute resize. ### Networking and delivery Network cost may include transfer allowances, per-gigabyte egress, load balancers, public IPs, private networking, gateways, and content delivery. A low-transfer admin product may barely notice network pricing. A file-download service, public API, backup pipeline, or media product may treat network policy as a major cost driver. Model both normal traffic and temporary events such as migrations, restores, launches, and data exports. ### Environments Production is only one copy of the architecture. Teams may also run: - development VMs - staging - preview environments - QA and performance testing - demos - migration environments - disaster-recovery capacity Environment duplication is one of the most common cost multipliers because each copy can bring compute, storage, databases, logs, backups, and public endpoints with it. ### Data protection and recovery Snapshots, automated backups, database-native backups, object retention, and restore testing are production costs—not optional extras after the product becomes important. The budget should follow: - how much data can be lost - how quickly service must return - which data is authoritative - how long recovery history is retained - where copies are stored - how often restoration is tested A backup feature and a working recovery process are not the same thing. ### Delivery and automation CI/CD, artifact storage, image registries, deployment systems, infrastructure-as-code workflows, and build runners create cost directly or through engineering ownership. Automation is valuable when it reduces repeat work and release risk. It becomes waste when every environment and deployment path receives a separate platform before the team needs it. ### Observability and security Metrics, logs, traces, uptime checks, vulnerability management, security agents, audit history, and alerting all consume storage, processing, and operator attention. Retention is often the hidden multiplier. Production may require longer history than staging. Preview environments rarely need the same logging depth as customer-facing systems. ### Operations The invoice does not include every infrastructure cost. The team also spends time on: - patching - incident response - backups and restoration - upgrades - security reviews - capacity planning - migrations - billing analysis - access management - vendor coordination A cheaper service that repeatedly interrupts product work may have a higher total operating cost than a more expensive service with a clearer responsibility boundary. ## Use a complete cost model A practical monthly model is: ```text Monthly infrastructure cost = production compute + databases and stateful services + block and object storage + backups and recovery storage + networking and delivery + non-production environments + monitoring and security tooling + delivery and automation services + idle or reserved capacity ``` Then add operational ownership: ```text Total operating cost = monthly infrastructure cost + engineering and operator time + incident and recovery work + migration and maintenance effort ``` Not every company needs to convert internal time into an exact dollar amount. It should still be visible in the decision. A platform that saves a small invoice amount but consumes several engineering days each month is not automatically economical. ## Separate fixed, variable, and step costs SaaS cost forecasting becomes clearer when costs are grouped by how they change. | Cost type | Behavior | Examples | |---|---|---| | Fixed baseline | Exists even with little customer activity | Production VM, minimum database plan, monitoring baseline | | Variable | Grows with usage or retained data | Object storage, requests, egress, logs, backup size | | Step cost | Jumps when architecture crosses a threshold | Second app node, load balancer, separate worker, database replica | | Temporary | Exists for a migration, launch, or test window | Parallel environments, data-copy server, load test capacity | | Operational | Grows with complexity and incidents | On-call time, manual patching, recovery work | This classification prevents two common mistakes. First, a team may expect every cost to grow smoothly with users even though infrastructure often grows in steps. Second, temporary capacity can quietly become a permanent baseline when nobody owns its removal. ## MVP infrastructure should optimize for learning An MVP should use the smallest architecture that is safe enough for its current data and users. A common shape is: ```text Users ↓ Application VM ↓ Database ↓ Backup and required file storage ``` The application and database may share one VM for a low-risk MVP, or the database may use a separate or managed service when customer data is already important. The correct starting point depends on recovery risk, not architectural fashion. An MVP budget should normally cover: - one clear production runtime - enough CPU and memory for normal use - secure access and patching - domain, DNS, and TLS - basic logs and uptime checks - backup for data that cannot be recreated - object storage when durable uploads should not live on the VM - a documented deployment and rollback path Delay components that do not solve a current requirement: - multiple production regions - several always-on app nodes without an availability need - full Kubernetes adoption for one simple workload - service-mesh or multi-cluster platforms - production-sized preview environments - separate tools for every operational concern The MVP architecture should be easy to understand, replace, and expand. It does not need to represent the final company architecture. ## Early production should protect state and releases Infrastructure priorities change when paying customers or business-critical data arrive. The main questions become: - Can customer data be restored? - Does one app deployment endanger the database? - Can the team detect errors before customers report them? - Is the application server carrying files, jobs, and database pressure together? - Does the team have a safe staging or release-validation path? - Who owns incidents and maintenance? Common investments at this stage include: - stronger database backup and restore procedures - a staging environment sized for its actual purpose - application and resource monitoring - more controlled deployment automation - moving durable files to object storage - separating workers when they affect user requests - separating the database when its recovery or resource needs differ from the app Do not add every layer together. Choose the boundary that removes the clearest risk. Use [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) when deciding which infrastructure role should be separated first. ## Growth should scale roles independently A growing SaaS often reaches a point where the whole application no longer has one resource profile. Examples: - web traffic needs more app instances - background processing needs more CPU - the database needs more memory or storage - uploads grow without increasing request volume - search or analytics needs a separate workload - staging and preview usage expands with the team At this stage, scaling the largest shared server can become inefficient because every role receives more capacity even when only one role is constrained. A staged topology may become: ```text Load balancer ↓ Application nodes ↓ private network Database + workers ↓ Object storage and recovery systems ``` This does not require microservices. A modular monolith can run across several application nodes while the database, workers, and storage have independent operating boundaries. The budget should move from “How much is the server?” to: - Which workload drives each cost? - Which workload needs the next capacity increase? - Which customer or product activity creates the usage? - Which components remain idle? - What failure or recovery requirement justifies redundancy? ## Pre-Series A cost becomes a unit-economics question As revenue and customer expectations grow, the total cloud bill becomes less useful on its own. Track infrastructure against a business unit such as: - cost per active customer - cost per tenant - cost per paid account - cost per one thousand requests - cost per processed job - cost per gigabyte stored - cost per workload or environment - infrastructure cost as part of service delivery cost A simple calculation is: ```text infrastructure cost per active customer = attributable monthly infrastructure cost ÷ active customers in the same period ``` Do not force every shared cost into false precision. Start with a repeatable method and document what is included. For example: - production compute may be shared across all customers - object storage can often be attributed by tenant - one enterprise customer may require dedicated capacity - staging and internal tools may remain shared overhead - support-heavy workloads may cost more operationally than their resource use suggests The purpose is not perfect accounting. It is detecting whether growth improves or weakens the operating model. ## Series A readiness requires predictability, not maximum complexity Series A readiness does not require Kubernetes, microservices, multi-region deployment, or a large platform team by default. It requires the company to understand: - the architecture serving customers - major cost drivers - current capacity and growth signals - recovery and availability commitments - ownership of production systems - the cost of adding customers or workloads - which infrastructure commitments are fixed - which resources can be resized or removed - what investment is required for the next growth stage Useful practices include: - monthly cost reviews by product and environment - named owners for major resources - documented capacity thresholds - consistent environment labels - forecast ranges rather than one exact number - deletion and retention policies - commitment discounts only for stable workloads - architecture standards that reduce duplicate tooling The objective is an explainable cost model that can support planning. It is not an architecture designed to impress an investor diagram. ## The largest cost multipliers are usually architectural ### Environment duplication One production stack becomes staging, preview, QA, demo, and migration copies. Each environment should have an owner, purpose, size, and end condition. Use [Idle Infrastructure Cost](/learn/guides/idle-infrastructure-cost-dev-staging-preview-test) for the keep, resize, shut down, archive, or delete decision. ### Data retention Databases, logs, objects, snapshots, and backups continue growing after compute stabilizes. Retention should follow recovery, audit, product, and customer requirements rather than an undefined “keep everything” policy. ### Redundancy without a failure model A second server does not automatically provide high availability. Redundancy creates value only when traffic routing, shared state, failure capacity, and recovery behavior are designed together. ### Managed-service sprawl Managed services can reduce operational responsibility, but each one introduces a new minimum cost, access model, monitoring surface, and vendor boundary. Use them where the covered responsibility is worth more than the premium. ### Premature orchestration and service decomposition Kubernetes and microservices can improve deployment, scheduling, and ownership at the right scale. They can also duplicate capacity, increase tooling, and require more observability before the team receives those benefits. ### Cross-region architecture A second region can add compute, storage, transfer, database replication, operational testing, and failover complexity. Use it when recovery or customer requirements justify the complete design. ### Permanent headroom Production needs capacity for normal peaks and failures. Excess capacity becomes waste when it is based on imagined demand and never reviewed. ## Use an infrastructure investment test Before adding a server, environment, managed service, cluster, or paid platform, require at least one clear reason. | Investment reason | Evidence to look for | |---|---| | Removes a measured bottleneck | CPU, memory, storage, latency, queue, or connection data | | Reduces material business risk | Recovery objective, customer commitment, or incident history | | Improves delivery speed | Repeated release delay or manual work with measurable cost | | Satisfies a customer requirement | Security, isolation, region, or availability obligation | | Improves unit economics | Lower cost per workload or customer after complete operating cost | | Creates required capacity | Forecast tied to real adoption or contracted demand | Avoid investments justified only by: - “we may need it eventually” - “larger companies use it” - “it looks more scalable” - “the provider makes it easy to turn on” - “we already paid for the minimum tier” The smallest change that solves the current constraint is usually easier to verify and reverse. ## Cost control starts with ownership and lifecycle Every major resource should answer four questions: 1. Who owns it? 2. Which product, customer, or environment does it support? 3. What signal would justify resizing it? 4. When will it be reviewed or removed? Use consistent labels for: - environment - product or service - owner - customer or tenant where appropriate - production criticality - expiration or review date Cost dashboards cannot repair missing ownership. They can only reveal that spend exists. ## A monthly SaaS infrastructure review A useful monthly review can remain short. ### Cost movement - What changed since the previous month? - Was the increase caused by customers, data, traffic, reliability, or waste? - Which three resources or services drove the change? ### Utilization - Are compute resources consistently underused or constrained? - Is storage growing as expected? - Are worker queues, database connections, or network use approaching a limit? ### Environments - Which preview, test, demo, and migration resources still have an active purpose? - Is staging correctly sized for current release activity? - Are temporary resources carrying permanent data? ### Recovery and retention - Did backups complete? - Has restoration been tested according to the workload’s importance? - Do snapshot, object, log, and backup retention periods still match requirements? ### Unit economics - How did cost per customer, tenant, or workload change? - Did a new customer require dedicated capacity? - Is one workload creating cost without matching value? ### Decisions - What should be resized? - What should be separated? - What should be shut down or deleted? - Which forecast or commitment should change? The output should be a short decision list with owners, not only a screenshot of the invoice. ## How this applies on Raff A SaaS architecture on Raff can grow in stages instead of beginning with every platform component. A practical path may use: - [Raff Cloud Servers](/products/raff-vm) for application and worker workloads - [Managed Databases](/products/managed-databases) when database operations need a separate managed boundary - [Object Storage](/products/object-storage) for durable uploads, media, reports, and archives - [Data Protection](/products/data-protection) according to backup, snapshot, retention, and recovery needs - [Raff pricing](/pricing) as the current source for plan and platform costs ```text MVP Application VM + required data protection Early production Application VM + database boundary + object storage where needed Growth Separate constrained roles + multiple app nodes only when justified Pre-Series A Cost ownership + unit economics + forecasted capacity ``` When we review small-team infrastructure, the recurring cost problem is rarely one unusually expensive server. It is several individually reasonable decisions—an extra environment, retained snapshot, oversized staging VM, duplicate database, permanent migration host—becoming part of the monthly baseline without another review. Use current product and pricing pages during implementation rather than copying temporary plan prices into a long-lived budget. ## SaaS infrastructure budget checklist ### Architecture - The smallest safe production topology is documented. - Every component solves a current workload, recovery, security, or customer requirement. - Software architecture and infrastructure topology are evaluated separately. ### Cost model - Compute, databases, storage, transfer, backups, environments, and tooling are included. - Fixed, variable, step, and temporary costs are distinguished. - Engineering and incident ownership are considered. ### Lifecycle - Every non-production environment has an owner and review date. - Temporary infrastructure has an end condition. - Storage and backup retention are deliberate. ### Measurement - Major workloads have utilization signals. - Cost can be reviewed by environment and product. - At least one useful unit-economics measure is tracked. ### Growth - Capacity thresholds are defined before resizing. - Managed services are chosen by responsibility value, not only convenience. - Redundancy follows a documented failure model. - Longer commitments apply only to stable workloads. :::cluster ## Conclusion SaaS infrastructure cost should evolve with the product. At MVP stage, pay for the smallest architecture that can deploy, protect important data, and reveal failures. In early production, strengthen database, recovery, release, and monitoring boundaries. During growth, measure workloads separately and scale only the constrained role. Before Series A, connect cloud spend to customers, environments, reliability commitments, and forecasted capacity. The right cloud strategy is not the lowest possible invoice or the most advanced platform. It is an explainable operating model in which each recurring cost has an owner, a purpose, and a trigger for change. :::cta View Raff Pricing Compare current Raff Cloud Server and platform pricing, then model the complete monthly cost of your SaaS architecture. ::: ## Sources - [AWS Well-Architected: Cost Optimization Pillar](https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/welcome.html) - [Microsoft Azure Well-Architected: Cost Optimization](https://learn.microsoft.com/en-us/azure/well-architected/cost-optimization/) - [Google Cloud Architecture Framework: Cost Optimization](https://cloud.google.com/architecture/framework/cost-optimization) - [Raff Pricing](/pricing) - [Raff Cloud Servers](/products/raff-vm) --- ### Cloud Cost Management in Power BI: Build a VM Spend Dashboard URL: https://rafftechnologies.com/learn/guides/cloud-cost-management-power-bi-vm-spend-guide Description: Build a cloud cost dashboard in Power BI that explains VM spend by resource, workload, environment, owner, client, and period change. Cloud cost management in Power BI means turning billing and infrastructure records into an owned, explainable model of where money is being spent and what decision should follow. **Use Power BI when a spreadsheet no longer answers who owns the spend, which environment caused the change, or whether growth is useful, idle, or unallocated. Start with a normalized cost ledger and a small star schema. Do not begin with dozens of visuals, and do not assume a provider-specific connector can model Raff or multi-cloud costs without a common data layer.** A useful cloud cost dashboard does not merely reproduce an invoice. It connects cost to resources, workloads, environments, owners, clients, and time so engineering and finance can act on the same numbers. ## A cloud cost dashboard must lead to a decision The dashboard should answer a short set of operational questions: 1. How much did we spend in the selected period? 2. What changed from the previous comparable period? 3. Which workload, environment, owner, or client caused the change? 4. How much cost is unallocated or missing ownership data? 5. Which resources appear idle, oversized, duplicated, or temporary? 6. Which increases reflect customer or product growth rather than waste? 7. What action and owner should be recorded after the review? If the report can show total spend but cannot explain the change, it is a billing visualization rather than a management system. A practical dashboard should turn an observation into one of these outcomes: | Dashboard signal | Management decision | |---|---| | Production cost rose with active users | Validate unit economics and capacity | | Staging cost rose without release activity | Resize, schedule, or review ownership | | Unallocated cost increased | Repair resource metadata and ownership | | Storage grew faster than application data | Review volumes, snapshots, backups, and retention | | One client’s spend changed sharply | Validate usage, architecture, and commercial treatment | | A temporary environment survived its end date | Shut down, archive, or delete | | Cost stayed flat while customer usage grew | Confirm performance headroom and margin improvement | Power BI is valuable because it can preserve this context in a reusable semantic model rather than forcing every reviewer to reinterpret raw billing rows. ## Power BI becomes useful after spreadsheets lose control A spreadsheet can be the right starting point. Stay with a spreadsheet when: - only a few resources exist; - one person owns infrastructure; - costs are reviewed occasionally; - ownership and environment labels are already obvious; - the report does not need automated refresh or controlled sharing; - the data comfortably fits one clean table. Move to Power BI when: - multiple people can create infrastructure; - production, staging, development, preview, and client environments must be separated; - billing data must be joined with inventory or ownership records; - the same metrics are rebuilt every month; - users need different filtered views; - historical data is growing; - refresh, permissions, or auditability matter; - MSP or SaaS cost allocation requires consistent definitions. | Reporting model | Best fit | Strength | Main weakness | |---|---|---|---| | Billing portal | Immediate account review | Current provider view | Limited business context | | CSV or spreadsheet | Small resource footprint | Fast and flexible | Fragile definitions and manual refresh | | Power BI over files | Recurring small-team reporting | Reusable model and visuals | File pipeline needs discipline | | Power BI over database or warehouse | Multi-team, MSP, or long history | Governed refresh and scalable joins | More data-engineering ownership | | FinOps platform | Broad optimization program | Specialized allocation and recommendations | Additional cost and operating model | Power BI is not automatically better because it is more advanced. It is better when the organization needs a governed model that several people can understand and reuse. ## The data source decision comes before the report Power BI can analyze cost data only after the data is available in a stable, refreshable shape. There are three common source patterns. ### Provider connector Microsoft provides a Cost Management connector for supported Azure billing scopes. That connector is Azure-specific. It should not be treated as a universal connector for Raff, another provider, or a combined multi-cloud ledger. Use a provider connector when: - the supported billing agreement matches the connector; - the report is primarily about that provider; - the connector exposes the cost fields and history you need; - its authentication and refresh model fit the team. ### Billing export or operational file A regular CSV, spreadsheet, or structured export can be enough for a small environment. Use it when: - data arrives in a consistent format; - the export can be replaced or appended predictably; - files have a controlled location and naming convention; - the team can detect missing periods and duplicate loads; - manual or scheduled refresh is acceptable. A folder-based import should still have a schema contract. Power BI cannot repair a process where column names, currencies, date formats, or resource identifiers change every month. ### Database or warehouse A database or warehouse becomes useful when cost data must be combined with resource inventory, customers, contracts, deployment records, or long history. Use it when: - several sources feed the model; - allocation rules are shared across reports; - data volumes make full file reloads slow; - transformations need testing and ownership; - several semantic models depend on the same clean tables. Microsoft’s Power BI modeling guidance recommends considering a warehouse and ETL process when data volumes or transformation requirements outgrow Power Query alone. For Raff reporting, use the billing or account data source currently available to your team, then normalize it into a provider-neutral cost table before building visuals. Confirm current account export and API capabilities rather than designing around an assumed endpoint. ## A cost-data contract prevents reporting drift The source should produce a repeatable set of fields even when the infrastructure changes. A practical cost ledger includes: | Field | Purpose | |---|---| | `ChargeDate` | Date the usage or charge belongs to | | `BillingPeriod` | Invoice or reporting period | | `Provider` | Raff or another provider | | `AccountId` | Billing or platform account boundary | | `ProjectId` | Project or internal cost boundary | | `ResourceId` | Stable resource identifier | | `ResourceName` | Human-readable resource name | | `ResourceType` | VM, volume, snapshot, backup, object storage, database, or other service | | `Service` | Product or service family | | `Region` | Public region label where relevant | | `UsageQuantity` | Measured usage when available | | `UsageUnit` | Hours, GB-month, requests, or another unit | | `ListCost` | Cost before credits or negotiated adjustments when available | | `EffectiveCost` | Cost used for internal reporting | | `Currency` | Billing currency | | `CreditOrAdjustment` | Credits, refunds, discounts, or corrections | | `Environment` | Production, staging, development, preview, test, or demo | | `Workload` | Application or service supported by the resource | | `Owner` | Person or team accountable for the spend | | `Client` | Customer boundary for MSP or tenant reporting | | `LifecycleStatus` | Active, temporary, scheduled for deletion, archived, or deleted | Not every source provides every field. The important step is to define which values are authoritative, which are derived, and which are allowed to remain unknown. Use explicit values such as `Unallocated`, `Unknown`, or `Not Applicable` instead of silently leaving business dimensions blank. Unallocated cost is itself a metric and should remain visible. ## Grain is the most important modeling decision The grain defines what one row in the fact table represents. Possible grains include: - one billing line per resource per day; - one resource cost total per day; - one resource cost total per month; - one charge type per resource per billing period. Choose the finest reliable grain the source can maintain consistently. Daily resource-level grain is often a practical balance because it supports trend analysis without forcing the report to process every low-level usage event. Monthly totals may be sufficient for very small teams but make anomaly detection and partial-period comparisons weaker. Do not mix different grains casually in the same fact table. A monthly subscription row and a daily usage row can produce incorrect totals when relationships or measures assume they represent the same level of detail. When different charge types have different grains, either normalize them deliberately or store them in separate fact tables with shared dimensions. ## A star schema keeps cost definitions understandable Microsoft recommends star-schema principles for Power BI semantic models because dimensions support filtering and grouping while fact tables support summarization. A cloud cost model can use this shape: ```text DimDate DimResource DimWorkload DimEnvironment DimOwner DimClient DimService DimRegion ↓ FactCost ``` ### FactCost stores measurable charges Typical columns include: - charge date key; - resource key; - service key; - usage quantity; - list cost; - effective cost; - credit or adjustment; - currency key; - billing period key. ### Dimensions store business context `DimResource` can describe the resource ID, name, type, plan or class, lifecycle status, and creation date. `DimWorkload` can describe the application, product area, criticality, and revenue or internal classification. `DimEnvironment` can distinguish production, staging, development, preview, test, and demo. `DimOwner` can identify the accountable person, team, and cost center. `DimClient` can support MSP or dedicated-customer reporting. `DimDate` should support day, week, month, quarter, year, and comparable-period calculations. A single flat export may look easier initially, but it duplicates labels across every row and makes ownership changes difficult to manage. A star schema lets cost rows remain historical while dimensions control how the business groups and filters them. ## Ownership data is more valuable than another chart The hardest cloud cost question is often not “what did this VM cost?” It is “who can decide whether this VM should still exist?” Every active resource should map to: - a named owner or responsible team; - a workload; - an environment; - a purpose; - a lifecycle expectation; - a project or client where relevant. A useful allocation hierarchy is: ```text Resource ↓ Workload ↓ Environment ↓ Owner or team ↓ Product, client, or business unit ``` Do not force the billing source to contain every business field. Maintain a separate resource inventory or allocation table and join it through a stable resource identifier. The dashboard should expose data-quality gaps: - cost without an owner; - owner without a team; - resource without an environment; - deleted resource with continuing charges; - resource name reused across projects; - client resource assigned to an internal cost center. A lower unallocated-cost percentage is often a stronger sign of reporting maturity than adding more visuals. ## Cost definitions must remain consistent Teams can disagree about cost while looking at the same invoice because they are using different definitions. Before creating measures, define: ### Reporting cost Choose the field used as the primary cost measure. This may be billed cost, effective cost, amortized cost, or another internally approved value depending on the source. ### Credits and adjustments Decide whether credits and refunds reduce the cost of the original workload, appear as a separate category, or both. ### Taxes Decide whether tax belongs in infrastructure analysis or only in finance reconciliation. ### Currency Do not sum different currencies as though they were equivalent. Convert through an approved exchange-rate table or report each currency separately. ### Partial periods A month-to-date value should be compared with the same number of days in the previous period or with an explicit forecast, not automatically with a completed month. ### Shared services Monitoring, networking, backups, shared databases, and administration may support several workloads. Use a documented allocation rule or keep the cost visible as shared rather than hiding it through arbitrary distribution. ### Deleted resources Keep their historical cost. Mark lifecycle status in the resource dimension instead of removing the resource from the model. Write these definitions into the semantic model documentation. A measure is not governed merely because it exists in DAX. ## The first dashboard should have four pages Most teams do not need a large report at launch. ### Executive overview Answer: - total cost; - month-to-date cost; - comparable-period change; - forecast or run rate; - largest cost drivers; - unallocated cost; - active cost-control actions. The executive page should explain direction, not display every resource. ### Workload and environment Show: - cost by workload; - cost by production and non-production environment; - trend by environment; - top changes; - resource count and cost together; - temporary environments past their review date. This page connects spending to architecture and delivery activity. ### Resource and waste review Show: - highest-cost resources; - resources with no owner; - low-activity candidates supplied by monitoring data; - unattached or orphaned storage records when available; - old snapshots or backup retention exceptions; - resources scheduled for shutdown or deletion. Cost data alone cannot prove that a resource is idle. Combine cost with usage, monitoring, last-access, deployment, or lifecycle signals before recommending removal. ### Client or team allocation For MSPs and multi-team organizations, show: - cost by client or team; - shared and unallocated cost; - change by client; - service mix; - client-specific resource inventory; - allocation exceptions. Use row-level security only after the model and access requirements are understood. Security rules should not become a substitute for separating highly sensitive data into appropriate models or workspaces. ## A small measure set is enough to begin The first version should use explicit, documented measures. A practical set includes: - **Total Cost:** approved effective cost for the selected filter context; - **Previous Period Cost:** comparable prior period using the date dimension; - **Cost Change:** current minus previous period; - **Cost Change Percentage:** cost change divided by previous-period cost; - **Month-to-Date Cost:** cost from the beginning of the current month; - **Run Rate:** a clearly labeled projection based on elapsed days or another approved method; - **Unallocated Cost:** cost assigned to unknown owner, workload, environment, or client; - **Unallocated Cost Percentage:** unallocated cost divided by total cost; - **Cost per Active Resource:** total cost divided by resources defined as active; - **Non-Production Cost:** cost assigned to staging, development, preview, test, and demo; - **Shared Cost:** cost intentionally retained outside direct workload allocation. Avoid creating several measures with nearly identical names but different filters. Use a measure dictionary that records the definition, owner, and expected use. A forecast should never be presented as an invoice prediction without explaining the method. A straight-line run rate can be useful for early warning, but it may be misleading during launches, scheduled renewals, migrations, or seasonal usage. ## Change analysis is more useful than static totals A cloud cost dashboard should make change explainable. Break a material change into: ```text New resources + resized resources + longer runtime + higher usage + storage or retention growth + price or plan change + credits or adjustments - deleted or downsized resources = period change ``` Useful change views include: - current month versus previous month; - current month-to-date versus equivalent prior period; - last seven days versus previous seven days; - cost change by resource; - cost change by workload; - cost change by owner; - new and deleted resources; - cost per customer or active user where business data is reliable. Do not label every increase as waste. A cost increase can be healthy when it supports customers, revenue, reliability, or a deliberate migration. The dashboard should distinguish: - **growth spend** — additional infrastructure supporting measurable demand; - **resilience spend** — backups, redundancy, monitoring, or recovery capability; - **delivery spend** — development, testing, preview, and staging; - **waste** — resources with no current value or owner; - **unexplained spend** — cost not yet classified. This classification gives reviewers a better decision than a universal “reduce cost” target. ## Refresh design should match the decision cadence More frequent refresh is not automatically better. | Decision cadence | Suggested data cadence | |---|---| | Monthly founder or finance review | Daily or weekly data may be sufficient | | Weekly infrastructure review | Daily refresh is usually practical | | Client cost visibility | Daily or provider-available cadence | | Fast budget anomaly review | More frequent refresh if the source supports reliable incremental data | | Invoice reconciliation | Billing-period close and adjustment refresh | Power BI scheduled refresh depends on the data source, credentials, and connectivity. On-premises or privately hosted sources may require an on-premises data gateway. If the cost fact table grows continuously, incremental refresh can reduce the amount of historical data reloaded during each refresh. Monitor the reporting pipeline itself: - latest source period loaded; - expected versus actual row count; - duplicate billing rows; - missing resource identifiers; - refresh success; - data freshness timestamp; - currency and schema changes; - allocation table coverage. A dashboard with yesterday’s successful refresh icon can still be wrong if the source export omitted part of the account. ## Data quality belongs on the dashboard Create visible data-quality indicators rather than correcting every problem silently. Track: - percentage of cost with an owner; - percentage with an environment; - percentage with a workload; - percentage with a client where required; - duplicate resource IDs; - unknown resource types; - missing dates; - unsupported currencies; - costs arriving after period close; - cost rows with no matching resource inventory record. A small data-quality page or banner helps reviewers understand whether the allocation is complete enough for a decision. Do not distribute an apparently precise client chargeback report when a large part of the spend remains shared or unallocated. Show the uncertainty explicitly. ## MSP reporting needs client boundaries and shared-cost rules An MSP cost dashboard has two jobs: 1. help the MSP operate infrastructure efficiently; 2. explain client-specific cost without exposing another client’s data. The data model should separate: - client-owned resources; - shared platform resources; - MSP internal resources; - temporary migration or onboarding resources; - unallocated resources. Choose a shared-cost policy: | Shared-cost model | Best fit | Risk | |---|---|---| | Keep shared cost separate | Early reporting and transparent operations | Client totals exclude platform overhead | | Equal allocation | Similar clients using similar platform services | Can misrepresent heavy and light users | | Usage-based allocation | Reliable usage drivers exist | Requires stronger source data | | Revenue-based allocation | Financial margin analysis | Does not reflect technical consumption | | Contract-based allocation | Managed service packages define treatment | Must remain aligned with agreements | Do not let Power BI invent the commercial rule. The model should implement a policy approved by the business. For client-facing reports, define whether the dashboard shows provider cost, allocated internal cost, contracted price, or margin. These are different measures and should not share ambiguous labels such as `Client Cost`. ## Cost reporting does not replace cost controls Power BI can expose an oversized or forgotten resource, but it cannot decide safely whether that resource should be removed. Pair the dashboard with: - ownership rules; - environment expiration dates; - budget thresholds; - weekly idle-resource review; - monthly sizing review; - backup and snapshot retention policy; - recorded actions and owners; - follow-up validation. Use [Cloud Budget Guardrails for Startups](/learn/guides/cloud-budget-guardrails-startups-vm-spend-drift) for the operating controls and [Idle Infrastructure Cost](/learn/guides/idle-infrastructure-cost-dev-staging-preview-test) for shutdown, archive, and deletion decisions. A cost dashboard should create a review queue, not merely a collection of charts. ## How this applies on Raff Raff cost reporting should begin with a resource inventory that maps each billable item to a workload, environment, owner, and lifecycle status. Include the Raff services used by the workload, such as: - [Raff VMs](/products/raff-vm); - [Volumes](/products/volumes); - [Data Protection](/products/data-protection); - [Object Storage](/products/object-storage); - managed services where applicable. Use the live [pricing page](/pricing) for current prices and product terms. Do not copy plan prices into the semantic model as permanent constants unless the model also records the effective date and source. A practical Raff reporting flow is: ```text Current billing or account data ↓ Normalized cost ledger ↓ Resource inventory and ownership mapping ↓ Power BI semantic model ↓ Cost review and recorded action ``` For fixed monthly resources, allocate cost to the period and environment according to the approved accounting rule. For storage, backup, or usage-based services, retain the source quantity and unit where available so reviewers can distinguish price changes from usage growth. Raff’s simpler product and pricing structure can make the cost model easier to explain, but the dashboard still depends on disciplined ownership and lifecycle data. Predictable pricing does not identify an abandoned staging VM by itself. ## The implementation sequence should stay small Use this sequence without turning the guide into a long dashboard project. ### Phase 1: define the decision Choose the first review question, such as: - why did VM spend change this month; - which non-production environments still have an owner; - which client caused the largest change; - how much cost is unallocated. ### Phase 2: establish the cost ledger Load one complete billing period, preserve stable identifiers, and document cost and currency definitions. ### Phase 3: add business dimensions Map resources to workload, environment, owner, client, and lifecycle status. ### Phase 4: publish four core pages Create overview, workload/environment, resource review, and allocation pages. ### Phase 5: establish refresh and quality checks Record freshness, missing data, duplicate rows, and allocation coverage. ### Phase 6: connect the dashboard to a review process Every material finding should receive an owner, action, due date, and validation step. Add forecasting, unit economics, advanced allocation, and monitoring joins only after the first model produces useful decisions consistently. ## A Power BI cloud cost checklist ### Source - [ ] The billing source and extraction method are documented. - [ ] Complete periods can be reconciled with the source. - [ ] Stable resource identifiers are preserved. - [ ] Currency and credits are handled explicitly. ### Model - [ ] FactCost has one documented grain. - [ ] Date, resource, workload, environment, owner, client, and service dimensions are separated where needed. - [ ] Cost measures have written definitions. - [ ] Shared and unallocated cost remain visible. ### Operations - [ ] Refresh frequency matches the review cadence. - [ ] Refresh failure has an owner and alert. - [ ] Data freshness appears in the report. - [ ] Historical data is retained according to the analysis need. ### Governance - [ ] Report access matches client and team boundaries. - [ ] Allocation rules are approved outside the report. - [ ] Sensitive client or commercial measures are clearly separated. - [ ] Metric definitions have owners. ### Action - [ ] Material cost changes can be traced to resources. - [ ] Unallocated cost has a remediation queue. - [ ] Idle-resource candidates require validation before removal. - [ ] Reviews create recorded actions and follow-up dates. :::cluster ## Conclusion Cloud cost management in Power BI works when the report connects billing data to resource ownership and operational decisions. Start with a normalized cost ledger, choose one consistent fact-table grain, and use a star schema to separate cost from date, resource, workload, environment, owner, client, and service context. Keep the first dashboard limited to overview, workload, resource review, and allocation pages. Make data quality and unallocated cost visible. Power BI can explain where spend changed. Cost controls, owners, and lifecycle rules determine what the team does next. :::cta View Pricing Use current Raff pricing as the verified source for VM, storage, and protection costs in your reporting model. ::: ## Sources - [Microsoft: Understand Star Schema and Its Importance for Power BI](https://learn.microsoft.com/en-us/power-bi/guidance/star-schema) - [Microsoft: Azure Cost Management Connector for Power Query](https://learn.microsoft.com/en-us/power-query/connectors/azure-cost-management) - [Microsoft: Connect to Cost Management Data in Power BI Desktop](https://learn.microsoft.com/en-us/power-bi/connect-data/desktop-connect-azure-cost-management) - [Microsoft: Analyze Azure Costs with the Power BI App](https://learn.microsoft.com/en-us/azure/cost-management-billing/costs/analyze-cost-data-azure-cost-management-power-bi-template-app) - [Microsoft: Incremental Refresh for Power BI Semantic Models](https://learn.microsoft.com/en-us/power-bi/connect-data/incremental-refresh-overview) - [Microsoft: Configure Power BI Scheduled Refresh](https://learn.microsoft.com/en-us/power-bi/connect-data/refresh-scheduled-refresh) - [Raff Pricing](/pricing) - [Raff Cloud Budget Guardrails](/learn/guides/cloud-budget-guardrails-startups-vm-spend-drift) - [Raff Idle Infrastructure Cost Guide](/learn/guides/idle-infrastructure-cost-dev-staging-preview-test) --- ### Auto-Scaling VM Planning: Right-Size Before You Scale URL: https://rafftechnologies.com/learn/guides/auto-scaling-vm-planning Description: Plan VM autoscaling with demand signals, capacity limits, warm-up, stabilization, readiness, safe scale-in, dependency guardrails, testing, and cost controls. VM autoscaling is a capacity-control process that adds or removes compute resources according to measured workload demand. **Do not automate scaling until the current VM is correctly sized, the bottleneck is understood, and additional nodes can become healthy and replaceable without losing sessions, files, jobs, or durable data. Use scheduled capacity for predictable peaks. Use reactive horizontal scaling only when demand lasts longer than provisioning and warm-up time and when capacity can be removed safely.** This guide explains the policy and architecture decisions behind autoscaling. It does not assume that every cloud platform provides the same managed autoscaling feature. ## Autoscaling is a control loop A complete scaling loop has six stages: ```text Observe demand ↓ Evaluate policy and safety limits ↓ Change capacity ↓ Configure and register the node ↓ Wait for readiness and warm-up ↓ Verify service health ``` A useful policy defines: - the demand signal; - how long the condition must persist; - minimum, desired, and maximum capacity; - provisioning and warm-up time; - readiness and health checks; - stabilization after a capacity change; - dependency limits; - safe removal behavior; - manual override and rollback. Without these controls, the fleet can oscillate, add capacity too late, remove active work, or overload the database. ## Demand shape determines the scaling model Autoscaling is only one option. | Demand pattern | Better starting model | Reason | |---|---|---| | New or poorly understood workload | Manual scaling and measurement | The baseline is not reliable yet | | Gradual growth | Periodic right-sizing | One larger VM may remain simpler | | Known business or campaign peaks | Scheduled scaling | Capacity can arrive before demand | | Bursts shorter than node warm-up | Queue, cache, rate control, or fixed headroom | Reactive capacity arrives too late | | Sustained variable web traffic | Reactive horizontal scaling | Replaceable nodes can share demand | | Variable worker backlog | Queue-based worker scaling | Queue age represents unfinished work | | Stateful database pressure | Tuning or vertical scaling first | More app nodes may increase DB load | | Availability requirement | Fixed minimum redundant capacity | Failure protection should already exist | Use [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) for the scale-up versus scale-out decision. ## Autoscaling readiness has seven gates ### The bottleneck is known Identify whether the limiting factor is CPU, memory, disk, database, queue processing, network, an external service, or application behavior. Use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) before automating the wrong response. ### Work can be divided safely Requests or jobs must be distributable. A stateful or tightly coupled workload may still be better served by a larger VM. ### Nodes are replaceable A node should not own durable sessions, uploads, queue state, or business data that disappears when it is removed. Use [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) to decide where state should live. ### Provisioning is repeatable Every new node needs the same operating-system baseline, application version, configuration, monitoring, and network policy. ### Readiness is measurable A running process or open port is not always ready for production traffic. Readiness should prove that the application can serve its intended workload. ### Dependencies have headroom More application nodes may create more database connections, cache traffic, queue consumers, storage operations, or third-party API calls. ### Capacity can be removed safely The system must stop sending new work, allow active work to finish, and confirm that the remaining fleet can carry the load. A workload that can scale out but cannot scale in safely is not ready for full autoscaling. ## Build a capacity baseline before selecting thresholds Measure normal and peak behavior across: - request or transaction rate; - concurrent requests or connections; - p50, p95, and p99 latency; - error and timeout rate; - CPU and memory pressure; - queue depth and oldest-job age; - worker completion rate; - database latency, connections, and locks; - storage latency and throughput; - application startup and warm-up time; - node count and cost. Include ordinary traffic, deployments, backups, batch jobs, campaigns, and known seasonal peaks. A threshold selected from one busy hour can turn normal variation into constant scaling activity. The baseline should show the relationship between demand, user impact, and useful capacity. ## Scaling signals should respond to added capacity A strong metric changes predictably when capacity changes. | Workload | Stronger signals | Guardrails | |---|---|---| | Web or API tier | Requests per healthy node, concurrency, sustained p95 latency | Error rate, database latency, healthy-node count | | Queue workers | Oldest-job age, queue depth per worker, completion rate | Retry rate, database pressure, external limits | | Long connections | Active connections per node, connection delay | Memory, network, draining time | | Batch processing | Remaining work and completion deadline | CPU, storage, dependency capacity | | CPU-bound jobs | Work queue plus sustained CPU pressure | Error rate and job duration | ### CPU alone is rarely sufficient CPU is useful when the workload is genuinely compute-bound, work distributes across nodes, and added capacity reduces both CPU pressure and user or queue impact. It is weaker when the system waits on storage, database locks, network calls, or external rate limits. ### Memory is often a diagnostic guardrail Memory pressure can represent legitimate demand, a leak, duplicated cache state, or excessive concurrency. Diagnose the cause before using memory as the only scale-out trigger. ### Errors can indicate a broken system rather than insufficient capacity A bad deployment, expired credential, or unavailable dependency will not improve when more identical nodes are added. Use error and dependency signals to stop or escalate unsafe scaling decisions. ## Minimum, desired, and maximum capacity define safety ### Minimum capacity Minimum capacity should support normal demand, maintenance, expected node failure, and the time required to add replacement capacity. Two nodes are not automatically resilient if losing one leaves the other unable to handle peak traffic. ### Desired capacity Desired capacity is the current healthy fleet target. It may be changed manually, by schedule, or by policy. ### Maximum capacity Maximum capacity protects: - the approved cost boundary; - database connections and throughput; - cache and queue limits; - network and storage limits; - external API quotas; - the team’s operational ability to observe the fleet. Maximum capacity is not only a budget setting. It prevents the application tier from overwhelming a slower dependency. Keep a documented manual override for launches and incidents. ## Warm-up determines whether reactive scaling can help A new VM is not useful capacity immediately after creation. Warm-up may include: 1. VM boot; 2. host configuration; 3. application deployment or startup; 4. configuration retrieval; 5. database and cache connections; 6. readiness checks; 7. load-balancer registration; 8. gradual traffic or job intake. Measure **time to useful capacity**. When a traffic burst ends before this sequence completes, use scheduled headroom, buffering, caching, or a higher minimum instead of relying on reactive scale-out. New nodes should not be treated as full capacity before they are ready and stable. ## Stabilization prevents repeated scaling Metrics arrive with delay and normal workloads fluctuate. Use different behavior for adding and removing capacity. Scale-out can respond faster when sustained user impact is clear. Scale-in should wait longer and confirm that demand has remained low. Use: - separate scale-out and scale-in thresholds; - longer scale-in observation windows; - a stabilization period after changes; - limits on how much capacity can be removed at once; - minimum time between removals; - protection for newly added nodes. This creates hysteresis: the condition that adds capacity is intentionally different from the condition that removes it. ## Scale-out and scale-in policies should be asymmetric Example planning logic: ```text Scale out when: - p95 latency is above target for a sustained period - requests per healthy node exceed the tested range - database latency and error rate remain acceptable Scale in when: - p95 latency remains healthy for a longer period - demand per healthy node stays below the removal threshold - no deployment or incident is active - the remaining fleet has sufficient headroom - one node can drain successfully ``` The exact thresholds must come from testing and production evidence. A practical multi-metric rule is: - any approved demand signal may justify adding capacity; - all removal safety conditions should agree before reducing it. ## Scale-in is the riskier operation A safe removal sequence is: 1. Stop sending new traffic or jobs to the selected node. 2. Wait for routing changes to take effect. 3. Allow active requests or jobs to finish. 4. Release leases, locks, and queue ownership safely. 5. Confirm local temporary data is disposable. 6. Confirm the remaining fleet has enough capacity. 7. Remove the node from routing and monitoring. 8. Remove the compute resource. 9. Verify latency, errors, queues, and dependencies. Worker fleets require special care because a worker may appear quiet while holding a long-running job. Use [Load Balancing Explained](/learn/guides/load-balancing-explained) for readiness and draining decisions. ## Stateless nodes are easier to add and remove Externalize or coordinate: - user sessions; - uploaded files; - durable generated assets; - background jobs; - scheduled-task ownership; - application configuration and secrets; - logs and metrics; - database state. Sticky sessions can preserve compatibility temporarily but keep users tied to one node. Local uploads can prevent safe removal. A scheduled task running on every node may execute several times after scale-out. The operational test is: > Can one node be removed without losing files, duplicating jobs, or destroying important state? ## Load balancing controls the node lifecycle A horizontally scaled application tier normally needs health-aware routing. ```text Provision ↓ Configure and deploy ↓ Pass readiness ↓ Register ↓ Serve traffic ↓ Drain ↓ Remove ``` Plan: - readiness behavior; - registration delay; - connection draining; - long-lived requests and WebSockets; - health thresholds; - behavior when all backends are unhealthy; - spare capacity after one backend fails. Autoscaling cannot compensate for weak health checks or insufficient failure capacity. ## Dependencies define the real scale unit | Added capacity | Dependency that may become constrained | |---|---| | More app VMs | Database connections and query concurrency | | More workers | Queue throughput, writes, and external API quotas | | More upload processors | Object storage, network, and temporary disk | | More report workers | Database reads, memory, and output storage | | More WebSocket nodes | Shared presence, pub/sub, and routing | A scale unit is the group of resources and limits required to support additional work. Before allowing the application fleet to reach maximum capacity, estimate database connections per node, requests to external systems, storage and network demand, queue throughput, and observability volume. ## Scheduled scaling fits predictable events Use a schedule for: - campaign launches; - billing or payroll processing; - end-of-month reporting; - planned migrations; - recurring business hours; - known customer events; - batch-processing windows. Schedule capacity early enough to complete warm-up before demand begins. After the event, reduce capacity through the same safe removal process instead of removing it immediately at a fixed clock time. Review schedules periodically so yesterday’s peak plan does not become permanent idle cost. ## Cost planning includes headroom and lifecycle overlap Autoscaling cost includes: - minimum always-on capacity; - failure headroom; - overlapping nodes during warm-up and draining; - load balancing and networking; - databases, caches, queues, and shared storage; - monitoring and logging; - automation maintenance; - false or noisy scaling events. | Model | Cost posture | Main trade-off | |---|---|---| | One larger VM | Predictable | One-node capacity and failure boundary | | Fixed multi-node fleet | Constant headroom | Simpler availability and deployment behavior | | Autoscaled fleet | Capacity follows sustained demand | Highest policy and lifecycle complexity | For small teams, a modest fixed fleet can be operationally cheaper than unreliable automation. Use the live [Raff pricing page](/pricing) rather than embedding temporary plan prices. ## Test the complete control loop A production-readiness test should include: ### Scale-out Measure threshold detection, provisioning, application readiness, registration, time to useful capacity, and whether user or queue pressure improves. ### Failure Test a node that fails readiness, an unhealthy application release, dependency slowdown, maximum-capacity behavior, and automation failure. ### Scale-in Confirm draining, long-running request and worker behavior, session and file continuity, and remaining capacity. ### Override Confirm the team can freeze removal, raise the maximum temporarily, disable the policy, and return to the previous safe state. A successful test proves that capacity arrives before service targets are missed and can later be removed without disrupting work. ## A scaling contract makes the policy reviewable Maintain one short record for each workload: | Field | Required decision | |---|---| | Workload and owner | What is scaling and who owns it? | | Scaling goal | Which user or job outcome is protected? | | Primary signal | Which metric represents demand? | | Scale-out condition | How large and persistent is the breach? | | Scale-in condition | How long must the system remain healthy? | | Minimum and maximum | What protects availability, cost, and dependencies? | | Warm-up | How long until capacity is useful? | | Readiness and draining | How are nodes added and removed safely? | | Dependency guardrails | Which database, queue, storage, or API limits apply? | | Manual override | How is the policy frozen or disabled? | | Validation | Which metrics prove the change worked? | Review the contract after launches, incidents, architecture changes, and major traffic shifts. ## How this applies on Raff A Raff scaling architecture can use: - [Raff Cloud Servers](/products/raff-vm) for application and worker nodes; - [Load Balancers](/products/load-balancers) for health-aware traffic distribution; - [Private Cloud Networks](/products/private-cloud-networks) for backend communication; - [Object Storage](/products/object-storage) for shared uploads and assets; - [Volumes](/products/volumes) for persistent block storage where appropriate; - [Data Protection](/products/data-protection) for recovery planning. A practical growth path is: ```text Properly sized Raff VM ↓ sustained measured constraint Separated database or workers ↓ replaceable application nodes Load balancer + fixed multi-node fleet ↓ tested lifecycle and demand policy Team-operated scaling workflow ``` Raff documents programmatic infrastructure interfaces for supported operations. Those interfaces can support team-operated automation, but this guide does not assume a managed native autoscaling service or identical support across every interface. Verify current documentation for supported resources, provisioning behavior, load-balancer capabilities, limits, and safe removal workflows. Use [Infrastructure Automation on Raff](/learn/guides/automation-infrastructure-as-code-raff) for automation boundaries. ## VM autoscaling checklist ### Readiness - [ ] The bottleneck is measured. - [ ] Work divides safely. - [ ] State is externalized or coordinated. - [ ] New nodes are configured repeatably. ### Policy - [ ] Signals represent user or queue pressure. - [ ] Scale-out and scale-in use different conditions. - [ ] Minimum, desired, and maximum capacity are documented. - [ ] Dependency and cost ceilings are included. ### Lifecycle - [ ] Time to useful capacity is measured. - [ ] Readiness is meaningful. - [ ] Stabilization is defined. - [ ] Traffic and jobs drain safely. ### Validation - [ ] Scale-out, failure, scale-in, and override tests are complete. - [ ] Maximum-capacity behavior is known. - [ ] The policy has an owner and review date. :::cluster ## Conclusion Auto-scaling VM planning is the design of a safe capacity control loop. Right-size and diagnose the workload first. Use scheduled capacity for predictable demand and reactive scaling only when additional nodes can become useful within the workload’s tolerance. Define signals, capacity bounds, warm-up, readiness, stabilization, dependency limits, and conservative scale-in behavior before automating production changes. The best policy preserves user experience, avoids dependency overload, removes capacity safely, and stays within an explicit operating and cost boundary. :::cta Explore Raff VM Build the measurable VM foundation that your scaling policy will operate. ::: ## Sources - [AWS: Target Tracking Scaling Policies](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-scaling-target-tracking.html) - [AWS: Default Instance Warmup](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-default-instance-warmup.html) - [AWS: Scaling Cooldowns](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-scaling-cooldowns.html) - [Microsoft Azure: Autoscale Virtual Machine Scale Sets](https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-autoscale-overview) - [Google Cloud: Autoscaler Decisions](https://cloud.google.com/compute/docs/autoscaler/understanding-autoscaler-decisions) - [Raff Infrastructure Automation](/learn/guides/automation-infrastructure-as-code-raff) - [Raff Cloud Servers](/products/raff-vm) - [Raff Load Balancers](/products/load-balancers) --- ### Shared Cluster vs Per-Client Cluster: Which MSP Model Scales Better? URL: https://rafftechnologies.com/learn/guides/shared-cluster-vs-per-client-cluster-msp Description: Compare shared and per-client Kubernetes clusters for MSPs across isolation, admin access, upgrades, blast radius, cost allocation, operations, and service tiers. A shared Kubernetes cluster runs workloads for several MSP clients on one cluster, usually separated by namespaces, access policies, network rules, and resource controls. A per-client cluster gives each customer a separate control plane, worker environment, lifecycle, and failure boundary. **Use a shared cluster when clients can accept a common platform, the MSP retains administrative control, and standardized policies can provide the required isolation. Use a per-client cluster when a customer needs cluster-admin access, privileged workloads, an independent upgrade schedule, a contractual dedicated boundary, or a smaller blast radius than a shared control plane can provide.** Many MSPs scale best with a tiered model rather than one universal answer. ## Shared and per-client clusters optimize different boundaries The decision is not simply cheap versus expensive. | Model | Primary optimization | Main trade-off | |---|---|---| | Shared cluster | Density, standardization, and lower duplicated operations | Wider shared failure and policy boundary | | Shared cluster with dedicated node pools | Better compute placement inside one platform | Control plane and cluster lifecycle remain shared | | Per-client cluster | Isolation, lifecycle independence, and clearer accountability | More duplicated infrastructure and operating work | | Several shared clusters by tier or risk | Smaller blast radius without one cluster per customer | More clusters to operate than a single shared model | A shared cluster makes the **namespace, identity, policy, and workload placement model** responsible for tenant separation. A per-client cluster moves more of that separation to the cluster boundary itself. Neither option removes the need for security, observability, backups, resource planning, or incident ownership. ## Use seven questions to choose the tenancy model ### What level of tenant trust exists? Kubernetes documentation distinguishes between cooperative tenants and tenants that may need stronger protection from one another. A shared cluster is easier to justify when: - the MSP operates every workload; - clients do not receive cluster-admin access; - workloads follow a standard security baseline; - privileged containers and host-level access are prohibited; - clients accept a common cluster lifecycle. A per-client cluster is safer when one customer must be treated as untrusted by another or when the client controls workloads that the MSP cannot fully constrain. ### Who needs administrative control? Cluster-admin access reaches beyond one namespace. It can affect cluster-wide resources, admission controls, custom resource definitions, networking, storage, and other tenants. Use a separate cluster when a client needs: - cluster-admin privileges; - custom admission controllers; - cluster-wide operators or CRDs with uncertain impact; - privileged DaemonSets; - host networking or host filesystem access; - custom CNI, CSI, or policy components. Namespaces are not a substitute for a separate administrative boundary. ### Can clients share one upgrade and maintenance rhythm? A shared cluster has one Kubernetes version and one cluster-level maintenance lifecycle. Clients may run different application versions, but the underlying platform moves together. Choose a per-client cluster when a customer needs: - a delayed or accelerated Kubernetes upgrade; - a customer-specific maintenance window; - a different add-on version; - independent testing and approval; - a separate rollback or decommission timeline. Shared clusters reward standardization. Dedicated clusters support divergence. ### How large can the blast radius be? A cluster-level networking error, admission-policy mistake, failed upgrade, exhausted control-plane dependency, or broken shared add-on can affect every tenant in a shared cluster. Per-client clusters reduce cross-client impact, but they create more independent systems that can drift or fail separately. The correct question is: > Is the MSP more prepared to manage one larger shared failure domain or many smaller operational surfaces? ### How different are workload profiles? Similar workloads are easier to place together. Highly variable workloads create fairness and noisy-neighbor risks. Review: - CPU and memory bursts; - storage latency and throughput; - network behavior; - pod density; - database and queue dependencies; - scheduled jobs; - privileged or hardware-specific requirements. Dedicated node pools may solve compute-placement or performance concerns while keeping the control plane shared. They do not provide a fully independent cluster lifecycle. ### How should costs be allocated? Shared clusters improve utilization, but chargeback requires measurement. Per-client clusters provide clearer resource ownership, but duplicate minimum infrastructure and operations. ### What does the customer contract promise? The technical design must match the service language. “Dedicated environment,” “isolated cluster,” “customer-controlled maintenance,” and “separate administrative boundary” are stronger promises than “logically isolated workloads.” Do not sell a namespace boundary as a dedicated cluster. ## Hard-stop conditions usually require a per-client cluster A per-client cluster is normally the safer default when any of these conditions apply: - The contract explicitly requires a dedicated cluster. - The client requires cluster-admin access. - The client runs privileged or host-level workloads. - The client needs independent Kubernetes or add-on versions. - The client requires a separate maintenance and upgrade approval process. - A cluster-wide incident must not affect another customer. - The environment may later be transferred to the client. - The workload uses cluster-wide extensions that cannot be safely standardized. - The client’s security review does not accept soft multi-tenancy. These are architectural boundaries, not problems that should be hidden behind more namespace policy. ## Shared clusters need layered tenant isolation A shared cluster is not secure merely because every client has a namespace. ### Namespaces organize the tenancy model Use a predictable namespace structure for each client and environment. Avoid placing unrelated tenants in the same namespace. A naming pattern might distinguish: ```text client-a-production client-a-staging client-b-production ``` Namespaces improve organization and allow namespaced policies, but some Kubernetes resources remain cluster-scoped. ### RBAC must follow least privilege Kubernetes RBAC uses Roles, ClusterRoles, RoleBindings, and ClusterRoleBindings to control API access. For shared clusters: - grant namespaced permissions where possible; - avoid broad wildcard permissions; - restrict access to secrets; - separate human and workload identities; - review service-account permissions; - tightly limit ClusterRoleBindings; - keep cluster-admin access with a small, accountable operator group. A client user should not be able to enumerate or modify another client’s resources. ### NetworkPolicy should deny unintended traffic Kubernetes allows pod-to-pod communication unless the network implementation and policies restrict it. Use a deny-by-default model, then explicitly allow: - ingress from approved gateways; - service-to-service paths within the tenant; - required database, cache, queue, and DNS traffic; - controlled egress to approved external services. Confirm that the cluster networking implementation actually enforces NetworkPolicy. Creating policy objects is not enough when the network layer does not apply them. ### ResourceQuota and LimitRange protect fairness Resource quotas limit namespace consumption. Limit ranges can set or constrain resource requests and limits. Use them to control: - total CPU and memory requests; - total CPU and memory limits; - pod count; - storage claims; - object counts where appropriate; - default container requests and limits. Quotas protect the platform only when workloads declare resources realistically and the MSP monitors actual usage beside requested capacity. ### Admission and pod security controls protect the cluster Shared tenancy needs rules for: - privileged containers; - host namespaces; - hostPath volumes; - unsafe capabilities; - unsigned or unapproved images; - required labels and ownership; - approved registries; - resource requirements; - security contexts. One tenant’s deployment should not gain host-level access that weakens every other tenant’s boundary. ### Secrets and identities must stay tenant-specific Use separate service accounts, secrets, external credentials, and automation identities for each client. Do not reuse one database credential, object-storage key, deployment token, or registry credential across tenants merely because the workloads share a cluster. ### Storage needs an explicit tenant boundary Persistent volumes, snapshots, backups, storage classes, and restore workflows must preserve tenant ownership. Confirm: - which client owns each volume; - whether dynamic provisioning can cross namespaces incorrectly; - who can create or attach storage; - how snapshots and restores are authorized; - what happens to persistent data during offboarding. ### Observability must not leak client data Shared logging and monitoring can expose namespace names, request paths, labels, log content, or customer identifiers. Create tenant-aware access rules and retention policies. Client dashboards should not reveal another tenant’s workloads or operational events. ## Dedicated node pools are a middle boundary, not a dedicated cluster A dedicated node pool can help when one client needs: - reserved compute capacity; - different node sizes; - workload placement controls; - reduced compute noisy-neighbor risk; - taints, tolerations, and affinity rules; - specialized performance characteristics. The model still shares: - the control plane; - cluster-wide networking and policy components; - cluster version and upgrade process; - cluster-scoped extensions; - many observability and operational systems; - cluster-level incident risk. Use dedicated node pools when the problem is **compute placement or capacity ownership**. Use a per-client cluster when the problem is **administrative, lifecycle, trust, or failure isolation**. ## Several shared clusters can reduce risk without one cluster per client MSPs with many customers often need more than the two extreme choices. A practical grouping model may create separate shared clusters by: - production and non-production; - service tier; - client risk profile; - workload type; - region; - regulated and non-regulated workloads; - internal platform version. This limits blast radius and upgrade complexity without duplicating a full cluster for every small customer. Avoid arbitrary grouping. Each cluster should have a documented reason, owner, lifecycle, and client-assignment rule. ## Shared clusters scale better when the service is standardized A shared model is usually strongest when the MSP sells a repeatable platform rather than a custom cluster for every account. Good candidates have: - similar deployment patterns; - common ingress, monitoring, and security controls; - predictable resource profiles; - a shared Kubernetes version policy; - no client cluster-admin access; - standard backup and recovery expectations; - clear resource quotas and support limits. The commercial offer should explain what is shared, what is isolated, which actions the client can perform, and what happens during maintenance or a platform incident. ## Per-client clusters scale better when independence is part of the product A dedicated cluster becomes easier to justify when the customer is paying for: - a separate operational boundary; - independent upgrades and maintenance; - dedicated worker capacity; - customer-specific add-ons; - clearer billing and asset inventory; - simpler transfer or termination; - reduced cross-client blast radius; - stronger administrative isolation. The MSP must still standardize cluster creation, monitoring, upgrades, backup checks, access reviews, and retirement. Otherwise, dedicated clusters become a fleet of inconsistent snowflakes. ## Compare the operating workload, not only infrastructure cost Per-client clusters duplicate more than compute. A useful cost model includes: ```text Worker capacity + control-plane or HA choices + persistent storage + ingress and networking + backups and recovery + monitoring and logging + security tooling + upgrade and support labor + spare capacity ``` ### Shared-cluster chargeback Allocate cost using a combination of: - requested CPU and memory; - actual CPU and memory use; - persistent storage; - backup consumption; - external services; - dedicated node-pool capacity; - support tier; - exceptional operational work. Requested resources matter because they reserve scheduling capacity even when actual usage is low. ### Per-client chargeback A dedicated cluster makes direct infrastructure ownership clearer, but the MSP should still price: - minimum cluster footprint; - high-availability choices; - monitoring and backup coverage; - upgrade labor; - incident response; - unused reserved headroom. Do not use historical VM prices in an evergreen tenancy guide. Verify current Kubernetes and supporting-service prices on the live Raff pages. ## Onboarding and offboarding expose the real operational difference ### Shared-cluster onboarding A repeatable client onboarding workflow should create: 1. namespaces; 2. resource quotas and limit ranges; 3. RBAC bindings and service accounts; 4. deny-by-default network policy; 5. approved ingress and egress rules; 6. secrets and external credentials; 7. storage and backup ownership; 8. monitoring, logs, and alerts; 9. labels for cost and ownership; 10. validation that another tenant remains inaccessible. ### Per-client onboarding A dedicated workflow should create: 1. the cluster and network boundary; 2. node pools and scaling limits; 3. access and kubeconfig ownership; 4. baseline policies and add-ons; 5. ingress, DNS, and certificates; 6. storage and recovery configuration; 7. monitoring and alert routing; 8. upgrade and maintenance ownership; 9. asset and billing records; 10. a tested handover or recovery process. ### Offboarding Shared-cluster offboarding requires careful removal of namespace resources, persistent volumes, secrets, identities, backups, logs, DNS, and external integrations without affecting other tenants. Per-client clusters are easier to identify as one asset boundary, but the MSP must still export required data, revoke access, preserve agreed retention, and verify deletion before destroying the cluster. ## Upgrade strategy changes with the tenancy model A shared cluster forces clients onto a common platform schedule. Use: - supported-version policy; - pre-production validation; - maintenance communication; - add-on compatibility testing; - workload disruption budgets; - rollback and recovery planning. Per-client clusters allow different schedules but multiply the number of upgrade campaigns. Track version age, maintenance status, failed upgrades, and exceptions centrally. A customer-specific version exception should have an owner and expiry date. Permanent exceptions become operational debt. ## Incident response follows the boundary you choose ### Shared cluster An incident may affect several tenants. The MSP needs: - tenant-aware impact assessment; - cluster-level and namespace-level telemetry; - communication rules for multiple clients; - evidence that unaffected tenants remain isolated; - a controlled way to suspend one tenant’s workload if it threatens the platform. ### Per-client cluster Impact is easier to assign to one customer, but responders must search across more clusters and configurations. Central inventory, monitoring, access, and runbooks are essential. Isolation does not help when the team cannot quickly find the affected cluster or understand its differences. ## Backups and disaster recovery remain workload decisions A separate cluster does not automatically provide disaster recovery. A shared cluster does not automatically prevent tenant-specific restoration. Define recovery for: - databases; - persistent volumes; - object data; - secrets and configuration; - cluster manifests; - external DNS and integrations; - client-specific recovery order. Back up state according to the system that owns it. Test restore and client-level recovery independently of cluster recreation. ## A tiered MSP offer usually scales best A practical service catalog can use three levels. | Service tier | Boundary | Suitable clients | |---|---|---| | Standard | Shared cluster with namespace, RBAC, policy, and quota isolation | Cooperative workloads following one platform standard | | Isolated compute | Shared cluster with dedicated node pool plus tenant policies | Clients needing reserved capacity or stronger placement separation | | Dedicated | Separate cluster, network, lifecycle, and access boundary | Clients needing independent administration, upgrades, or contractual isolation | The tier names are commercial choices. The technical description must remain precise. From an MSP service-design perspective, the important step is to define the boundary before setting the price. Otherwise, the platform team may promise dedicated behavior from shared infrastructure or absorb dedicated-cluster operations inside a standard-tier margin. ## How this applies on Raff Raff’s current Kubernetes offering provides managed Kubernetes clusters with worker-node pricing, node pools, optional high availability, monitoring, private cluster networking, and worker-pool autoscaling. Verify current capabilities and prices on the live [Kubernetes product page](/products/kubernetes). A shared-cluster Raff model can use: - one Kubernetes cluster; - one namespace set per client and environment; - strict RBAC and service-account boundaries; - deny-by-default NetworkPolicy; - quotas and limit ranges; - dedicated node pools where compute separation is justified; - tenant-aware monitoring and backup ownership. A per-client Raff model can use: - one cluster per customer; - the cluster’s own network boundary; - customer-specific node pools and scaling limits; - separate access, maintenance, monitoring, and recovery records; - live pricing for the complete cluster footprint. Do not claim that a shared namespace has the same boundary as a separate cluster. Do not assume that separate clusters eliminate the need for policies, backups, least privilege, or operational standardization. :::cta Explore Kubernetes Review current Raff Kubernetes capabilities and plan the cluster boundary that matches your MSP service tier. ::: ## MSP cluster-model checklist ### Choose shared tenancy when - [ ] The MSP retains cluster administration. - [ ] Clients accept one platform and upgrade policy. - [ ] Workloads follow the same security baseline. - [ ] Privileged and host-level access are prohibited. - [ ] Namespace, network, resource, storage, and identity controls are tested. - [ ] Shared failure impact is contractually acceptable. ### Choose a per-client cluster when - [ ] The contract requires a dedicated cluster. - [ ] The customer needs cluster-admin access. - [ ] Workloads require privileged or cluster-wide extensions. - [ ] The customer needs independent upgrades or maintenance. - [ ] Cross-client cluster-level impact is unacceptable. - [ ] Transfer, termination, or asset ownership requires a separate boundary. ### Validate either model - [ ] Costs include operations and recovery, not only nodes. - [ ] Access is reviewed and attributable. - [ ] Backups and restores are tested. - [ ] Monitoring identifies client-level impact. - [ ] Onboarding and offboarding are repeatable. - [ ] The service description matches the technical boundary. :::cluster ## Conclusion Shared and per-client Kubernetes clusters scale in different ways. A shared cluster scales platform density and standardization. A per-client cluster scales independence, administrative separation, and blast-radius control. Dedicated node pools and several shared clusters provide useful middle boundaries, but they should not be described as fully dedicated clusters. For most MSPs, the strongest model is tiered: shared tenancy for standardized cooperative workloads, dedicated compute where placement is the concern, and per-client clusters where trust, lifecycle, or contractual requirements demand a separate boundary. ## Sources - [Kubernetes: Multi-tenancy](https://kubernetes.io/docs/concepts/security/multi-tenancy/) - [Kubernetes: Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) - [Kubernetes: Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) - [Kubernetes: Resource Quotas](https://kubernetes.io/docs/concepts/policy/resource-quotas/) - [Kubernetes: Limit Ranges](https://kubernetes.io/docs/concepts/policy/limit-range/) - [Kubernetes: Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) - [Raff Kubernetes](/products/kubernetes) - Date verified: 2026-08-04 --- ### DNS for Cloud Applications: Records, TTL, and Failover URL: https://rafftechnologies.com/learn/guides/dns-for-cloud-applications Description: Plan DNS for cloud applications across record types, TTL, caching, migrations, load balancing, failover, DNSSEC, CAA, and end-to-end monitoring. DNS for cloud applications maps public names such as `app.example.com` and `api.example.com` to the infrastructure that serves them. It also controls how long answers are cached, which systems can receive email, which certificate authorities may issue certificates, and how traffic moves during migrations or failures. **Use direct A or AAAA records for stable public IP addresses, CNAME records for subdomain aliases, and a load-balancer or health-checked DNS target when several application nodes must share traffic. Lower TTL before a planned cutover, but do not treat low TTL as instant failover.** DNS should match the workload’s availability and recovery requirements. ## DNS architecture should follow the public service boundary Start by deciding which components internet users must resolve. ```text Users ↓ DNS Public application endpoint or load balancer ↓ private network Application, database, cache, queue, and internal services ``` Public DNS normally belongs on: - websites and public APIs; - load-balancer or reverse-proxy endpoints; - public status and documentation services; - email and verification records; - intentionally public administration endpoints with strong access controls. Databases, caches, queues, internal workers, and private dashboards usually do not need public records. They should use private addressing, internal DNS where available, and explicit network policy. ![DNS traffic flow diagram showing a user request resolving through DNS to reach a cloud application server or load balancer.](https://raff-images.s3.raffusercloud.com/DNS_traffic_flow_diagram_showing_a_user_request_resolving_through_DNS_to_reach_a_cloud_application_server_or_load_balancer_02840857be.png) ## Use the record type that matches the destination | Record | Purpose | Common cloud use | |---|---|---| | A | Maps a name to an IPv4 address | Public VM or IPv4 load-balancer endpoint | | AAAA | Maps a name to an IPv6 address | Public IPv6 endpoint | | CNAME | Makes one name an alias of another name | `www`, `app`, or `api` subdomain pointing to a provider hostname | | MX | Identifies mail exchangers | Business or transactional email delivery | | TXT | Stores service-defined text | Domain verification, SPF, DKIM, and DMARC data | | NS | Delegates a DNS zone | Moving a zone or delegating a subdomain | | CAA | Authorizes certificate authorities | Reducing unintended certificate issuance | | SRV | Publishes service location data | Protocols that explicitly support SRV discovery | | PTR | Maps an IP address back to a name | Reverse DNS, commonly relevant to mail systems | The record is only one part of the decision. Also define the owner, TTL, expected destination, change process, and rollback path. ## A record vs CNAME depends on whether the target is an address or a name An **A record** points directly to an IPv4 address. An **AAAA record** points directly to an IPv6 address. A **CNAME record** points an alias to another DNS name, and the resolver then follows that name to its address records. Choose an A or AAAA record when: - the endpoint has a stable public IP; - the DNS name should resolve directly to that address; - the zone apex must retain other record types; - the application team controls IP replacement and record updates. Choose a CNAME when: - the target is a provider-managed hostname; - the provider may change the underlying addresses; - a subdomain should follow another canonical name; - the extra DNS lookup and provider dependency are acceptable. A standards-compliant CNAME alias cannot normally coexist with other record data at the same name. This is why a traditional CNAME is unsuitable at many zone apexes: the apex also needs records such as NS and SOA. Some DNS providers offer ALIAS, ANAME, or CNAME-flattening behavior, but that is provider-specific rather than a standard CNAME. Avoid long CNAME chains. They add dependencies, complicate troubleshooting, and can fail when any intermediate name is misconfigured. ## IPv4 and IPv6 records must represent the same service readiness Publishing an AAAA record tells IPv6-capable clients that the service is ready over IPv6. Do not add AAAA merely because an address exists. Confirm: - the application listens on IPv6; - the firewall protects IPv6 as well as IPv4; - the reverse proxy or load balancer accepts IPv6 traffic; - TLS and health monitoring work over IPv6; - logs distinguish both address families; - the IPv6 path reaches the same healthy application behavior. A broken IPv6 path can create intermittent failures for users whose clients prefer IPv6 even while IPv4 remains healthy. ## TTL controls cache lifetime, not global propagation speed TTL, or Time To Live, is the number of seconds a DNS resource record may remain cached before a resolver should request a fresh answer. RFC 1035 defines TTL as a cache lifetime in seconds. A lower TTL shortens the intended cache window. It does not guarantee that every resolver, operating system, browser, or application will refresh at exactly that moment. | Situation | Practical TTL direction | |---|---| | Stable production endpoint | Moderate or longer TTL | | Planned migration | Temporarily lower TTL before the change | | Health-checked DNS routing | Use the DNS provider’s supported range and failover model | | Frequently changing development name | Shorter TTL may be reasonable | | Mail, verification, and rarely changed records | Moderate or longer TTL is usually simpler | There is no universal best number. Choose TTL from: - acceptable cutover delay; - authoritative DNS provider limits; - expected change frequency; - resolver query volume; - failover design; - operational ability to keep old and new endpoints available together. ![DNS TTL migration timeline showing old server traffic, lowered TTL, DNS record change, cache expiry, and traffic moving to a new server.](https://raff-images.s3.raffusercloud.com/dns_ttl_migration_timeline_png_384189aba6.png) ### Lower TTL before the migration window If the current TTL is one hour, changing it to five minutes at the start of the cutover does not remove answers already cached for the previous one-hour period. Lower it early enough for the old TTL to expire. After the new endpoint is stable and old traffic has drained, increase it again if frequent changes are no longer expected. ### Negative answers can also be cached Resolvers may cache negative answers such as `NXDOMAIN`. Creating a record immediately after users have already queried a nonexistent name can therefore appear delayed. This matters for new hostnames, validation records, and emergency names created during an incident. Provision critical names before they are required and verify the zone’s negative-caching behavior. ## “DNS propagation” is several caches expiring at different times An authoritative change can be correct while some users still receive an older cached answer. The path can include: - the authoritative DNS provider; - recursive resolvers; - enterprise or ISP caches; - operating-system caches; - browser and application caches; - local proxies and service meshes. For planned changes: - verify the authoritative zone first; - query more than one public resolver; - keep the old endpoint available during overlap; - ensure TLS works on both endpoints; - monitor traffic reaching old and new destinations; - avoid deleting the previous resource too early. Do not promise a precise global propagation time. State the configured TTL and the planned overlap window instead. ## Use six questions to choose the DNS design ### What is the destination type? Use an address record for a stable IP and an alias record for a provider-managed name. Confirm apex limitations before selecting CNAME-like behavior. ### How much downtime can the workload tolerate? A personal site may accept a manual record change. A revenue-producing application may need a load balancer, redundant endpoints, health checks, and rehearsed failover. ### Is the application ready for more than one endpoint? Active-active routing requires compatible application versions, externalized sessions and uploads, consistent data, and sufficient capacity at every healthy destination. ### How quickly must traffic move? TTL affects resolver refresh behavior, while health-check intervals, failure thresholds, endpoint readiness, and client connection reuse also affect recovery time. ### Can old and new endpoints overlap? Overlap makes migrations safer. When both endpoints can serve valid traffic, cached answers become less dangerous. ### Who owns the change? Every production zone needs named ownership, access control, auditability, rollback instructions, and an emergency contact path. ## DNS failover is slower and less deterministic than load balancing DNS failover changes the answers returned for new DNS queries. It does not directly move existing connections, clear client caches, or guarantee that every resolver immediately stops returning an unhealthy target. Use a load balancer when the main requirement is: - distributing traffic among application nodes; - removing unhealthy backends quickly; - preserving one public endpoint; - connection draining; - application-aware health checks within one architecture. Use DNS routing or failover when the requirement is: - moving between distinct public endpoints; - active-passive disaster recovery; - weighted migration between environments; - geography-based endpoint selection; - a failure boundary above one load balancer or region. A resilient design may use both: ```text DNS routing or failover ↓ Regional load balancer ↓ Healthy application nodes ``` Google Cloud DNS documentation, for example, distinguishes weighted, geolocation, and failover routing policies and can remove unhealthy health-checked endpoints from eligible responses. Capabilities vary by DNS provider, so verify the exact health-check scope and failure behavior before relying on automation. ## Manual, active-passive, and active-active models solve different problems | Model | Suitable when | Main risk | |---|---|---| | Manual record change | Short interruption and operator involvement are acceptable | Detection and human response delay | | Active-passive DNS failover | A tested standby endpoint exists | Standby drift and cached primary answers | | Active-active DNS routing | Every endpoint can safely serve production | Data, release, and session inconsistency | | Weighted routing | Traffic must move gradually | Weight does not guarantee exact request distribution | | Geolocation routing | Regional service placement matters | DNS source location may differ from the end user | | Load balancer only | One public architecture contains several nodes | The load balancer or region remains a shared boundary | Choose the least complex model that meets the recovery objective. ## Active-passive requires a usable standby, not only a record A standby is useful only when it has: - compatible application and runtime versions; - current configuration and secrets; - valid certificates; - reachable dependencies; - sufficient capacity; - an understood data-recovery or replication path; - monitoring and a tested health endpoint; - a documented promotion and rollback process. A DNS change cannot repair stale data or an untested application environment. ## Active-active requires state and releases to work across endpoints Before returning more than one production endpoint, confirm: - sessions are externalized or portable; - uploads do not exist only on one local disk; - database consistency matches application expectations; - background jobs do not run duplicate side effects; - schema and API changes remain compatible during rollout; - certificates and secrets exist in every location; - health checks validate useful readiness; - each endpoint can carry traffic when another fails. Round-robin DNS alone is not a high-availability architecture. It can continue returning an unhealthy address unless the DNS service integrates health checks or operators remove the address. ## DNS migration should be designed as an overlap, not a single edit A safer migration has four phases. ### Prepare - inventory the existing zone; - identify records controlled by other services; - build and test the new endpoint; - issue and validate certificates; - verify firewall and application behavior; - lower the relevant TTL early enough. ### Change - update the smallest required record set; - confirm the authoritative answer; - test through several resolvers and networks; - watch application, TLS, error, and traffic metrics. ### Overlap - keep the previous endpoint healthy; - preserve compatibility between old and new application versions; - track residual traffic to the old address; - avoid destructive database or configuration changes during the cache window. ### Complete - confirm old traffic has drained; - restore the normal TTL where appropriate; - remove obsolete addresses and records; - update diagrams, inventories, and recovery instructions; - retain rollback evidence and review the change. This is a decision guide, not a promise that every DNS provider behaves identically. Test the real authoritative service and resolver path used by the application. ## Zone delegation changes need additional care Changing NS records moves authority for the zone, not only one application endpoint. Before changing nameservers: - reproduce every required record at the new provider; - preserve MX, TXT, CAA, verification, and delegated subdomains; - confirm DNSSEC requirements and DS records; - compare answers between old and new authoritative servers; - keep the old zone available during the transition; - verify the registrar configuration after the change. A missing record during nameserver migration can break email, certificates, integrations, and applications even when the main A record is correct. ## DNS security needs account protection, DNSSEC, and certificate controls ### Protect the registrar and DNS provider accounts Use: - multi-factor authentication; - individual administrator identities; - least privilege; - audit logs and change alerts; - controlled API tokens; - rapid offboarding; - protected recovery email accounts. A compromised DNS account can redirect users without changing the application server. ### DNSSEC authenticates DNS data DNSSEC adds cryptographic signatures so validating resolvers can check that DNS data is authentic and has not been modified in transit. It does not encrypt DNS queries or make an unhealthy application available. DNSSEC deployment requires coordination between the authoritative provider and the parent zone through DS records. Incorrect key or delegation changes can make a signed zone fail validation, so use the provider’s documented rollover and migration process. ICANN announced a DNSSEC root trust-anchor rollover planned for October 11, 2026. Application teams normally depend on their DNS and resolver providers to handle root trust anchors, but operators of validating resolvers should follow the official readiness guidance. ### CAA restricts certificate-authority authorization CAA records let a domain owner specify which certificate authorities are authorized to issue certificates for the domain. CAA is an additional control, not a replacement for DNS account security, certificate monitoring, or correct validation. ## Email and verification records need separate ownership A web migration should not accidentally modify mail or verification data. Protect: - MX records; - SPF data in TXT records; - DKIM selectors; - DMARC policy; - domain-verification tokens; - certificate-validation records; - service-specific subdomain delegations. Avoid creating multiple conflicting SPF records at the same name. Keep a record inventory showing which provider owns each value and what would break if it were removed. ## Monitor resolution and the application behind it A DNS check that returns the expected address does not prove the application is healthy. Monitor the complete path: 1. The expected authoritative nameservers answer. 2. The hostname returns the intended record set. 3. IPv4 and IPv6 behave as designed. 4. The TCP and TLS connection succeeds. 5. The certificate matches the hostname. 6. The application returns a meaningful healthy response. 7. Critical user workflows remain available. Also alert on: - unexpected record changes; - nameserver or DS changes; - certificate issuance and expiration; - stale or abandoned hostnames; - health-check state changes; - traffic continuing to retired endpoints. ## How this applies on Raff Raff infrastructure can sit behind standard public DNS records. A small application may point an A record to the public IPv4 address of a [Raff VM](/products/raff-vm). A multi-node application can place a [Load Balancer](/products/load-balancers) at the public edge while application and database traffic stays on [Private Cloud Networks](/products/private-cloud-networks). ```text Public DNS ↓ Raff VM or Raff Load Balancer ↓ private network Application and data services ``` Use the DNS provider for zone hosting, record management, DNSSEC, routing policies, and health-checked DNS behavior. Use Raff for the compute, load-balancing, networking, storage, and recovery layers required by the application architecture. Verify the current endpoint type, IP addressing, health-check behavior, and product availability on the live Raff product pages before changing production DNS. :::cta Explore Raff VM Deploy the public application endpoint first, validate it, and then point the appropriate DNS record to it. ::: ## DNS decision checklist ### Record design - [ ] Every public name has a documented purpose and owner. - [ ] A, AAAA, and CNAME choices match the destination type. - [ ] Apex records follow the DNS provider’s supported model. - [ ] Mail, verification, CAA, and delegated records are inventoried. - [ ] Private services are not exposed through unnecessary public records. ### Change readiness - [ ] Current and target answers are documented. - [ ] TTL was lowered before the migration window where required. - [ ] Old and new endpoints can overlap safely. - [ ] TLS, firewall, monitoring, and application readiness are verified. - [ ] Rollback is defined before the record changes. ### Availability and security - [ ] The failover model matches the workload RTO. - [ ] Standby or active endpoints are tested and sufficiently sized. - [ ] DNS provider and registrar accounts use MFA and individual access. - [ ] DNSSEC and DS records are handled through a documented process. - [ ] Resolution and end-to-end application health are monitored. :::cluster ## Conclusion DNS for cloud applications is a reliability and ownership decision, not only a domain setup task. Use address records for stable public IPs, aliases for provider-managed names, and a load balancer when several nodes must share one application endpoint. Treat TTL as a cache-lifetime control, plan migrations with overlap, and use DNS failover only when the standby, health checks, data, and recovery process are ready. Protect the registrar and authoritative DNS accounts, consider DNSSEC and CAA, inventory mail and verification records, and monitor the application behind every important hostname. ## Sources - [IETF RFC 1034: Domain Names — Concepts and Facilities](https://datatracker.ietf.org/doc/html/rfc1034) - [IETF RFC 1035: Domain Names — Implementation and Specification](https://datatracker.ietf.org/doc/html/rfc1035) - [IETF RFC 2181: Clarifications to the DNS Specification](https://datatracker.ietf.org/doc/html/rfc2181) - [IETF RFC 8659: DNS Certification Authority Authorization](https://datatracker.ietf.org/doc/html/rfc8659) - [ICANN: DNSSEC — What It Is and Why It Is Important](https://www.icann.org/resources/pages/dnssec-what-is-it-why-important-2019-03-05-en) - [Google Cloud DNS Routing Policies and Health Checks](https://cloud.google.com/dns/docs/routing-policies-overview) - [Raff Cloud Servers](/products/raff-vm) - [Raff Load Balancers](/products/load-balancers) - [Raff Private Cloud Networks](/products/private-cloud-networks) - Date verified: 2026-08-04 --- ### Podman vs Docker: Security, Compatibility, and When to Switch URL: https://rafftechnologies.com/learn/guides/docker-vs-podman-small-teams Description: Compare Podman vs Docker across rootless security, Compose compatibility, systemd integration, networking, storage, and migration risk. Podman and Docker can run many of the same OCI container images, but they create different operating models. **Docker is usually the safer default for small teams that depend on Docker Compose, broad third-party compatibility, and familiar tooling. Podman is the stronger choice when rootless operation, a daemonless architecture, and systemd-native service management are explicit requirements.** The decision should not be based on which runtime appears more modern. It should be based on which workflow your team can deploy, secure, debug, and maintain consistently. ## Podman vs Docker at a glance | Decision area | Docker | Podman | | --- | --- | --- | | Architecture | Client-server model with the `dockerd` daemon | Daemonless local engine; optional API service for remote workflows | | Rootless operation | Supported through Docker rootless mode | Core operating model; most commands can run as a regular user | | CLI compatibility | Native Docker CLI and API ecosystem | Docker-CLI-comparable commands, but not universal behavioral parity | | Compose workflows | Native Docker Compose ecosystem | Uses compose providers and may expose compatibility differences | | Linux service management | Commonly managed through Docker service and restart policies | Strong systemd integration through Quadlet | | Pods | Not a primary Docker abstraction | Built-in pod management | | Third-party tooling | Widest compatibility and documentation coverage | Strong Linux ecosystem, but some tools still assume Docker sockets and APIs | | Best default | Teams prioritizing compatibility and onboarding | Linux-first teams prioritizing rootless and systemd-native operations | Both runtimes can be production-ready. The more important question is which one fits the surrounding workflow. ## The architectural difference Docker Engine is a client-server application. The Docker CLI communicates with APIs exposed by the long-running `dockerd` daemon, which creates and manages images, containers, networks, and volumes. This architecture is one reason the Docker ecosystem is consistent. Tools can integrate with a known API and socket, and documentation commonly assumes Docker’s daemon, CLI, networking, and Compose behavior. Podman is designed as a daemonless container engine. The `podman` command creates and manages containers directly instead of requiring one central daemon for normal local operation. Podman also provides a Docker-CLI-comparable command structure and can expose an API service where remote or compatibility workflows require it. Daemonless does not mean “no background processes.” Containers still run as processes, and services such as systemd may manage their lifecycle. It means the runtime does not depend on one always-running central daemon for ordinary local container operations. ## Rootless containers and security Rootless operation reduces the privileges available to the container runtime and container processes. It is an important security boundary, but it does not make containers automatically safe. Podman treats rootless operation as a core use case. Most commands can run as a regular user, with user namespaces and subordinate UID/GID mappings separating container identities from host identities. Docker also supports rootless mode. In that configuration, both the Docker daemon and containers run inside a user namespace without root privileges, subject to documented prerequisites and limitations. The practical difference is emphasis: - Podman commonly starts from a rootless-first operating model. - Docker commonly starts from its standard daemon model, with rootless mode available when the team chooses it. Rootless containers can affect networking, privileged ports, storage drivers, cgroups, device access, and host integration. Test the actual workload instead of treating “rootless” as a checkbox. Security also depends on: - image provenance and update policy - Linux capabilities - seccomp and mandatory access controls - secrets handling - read-only filesystems - volume permissions - network exposure - host patching - access to runtime sockets A privileged or poorly configured container can remain dangerous under either runtime. ## Docker Compose and Podman compatibility Compose compatibility is usually the most important operational difference for small teams. Docker Compose is part of the standard Docker workflow. Application documentation, CI examples, control panels, self-hosted software, and deployment guides frequently assume `docker compose` behavior. Podman supports Compose-oriented workflows through compose providers. That can work well, but it should not be interpreted as guaranteed one-to-one compatibility with every Docker Compose project. Compatibility gaps may appear around: - networking behavior - container naming - dependency and health-check semantics - volume ownership under rootless execution - socket-dependent applications - build features - third-party Compose extensions - tools that expect `/var/run/docker.sock` A simple application with standard images, networks, environment variables, and named volumes may move with little work. A stack tightly coupled to Docker APIs, Docker socket mounting, specialized networking, or vendor-specific assumptions requires testing. For an existing Compose estate, Docker remains the lower-risk default unless Podman solves a clear operational or security requirement. ## Image and build compatibility Docker and Podman work with OCI-compatible images and registries, so the same image can often run on either runtime. That does not guarantee identical behavior. The runtime still controls networking, mounts, user namespaces, cgroups, security labels, and host integration. Review these areas before switching: - image architecture and platform support - entrypoint and signal handling - bind-mount ownership - SELinux labels where applicable - required Linux capabilities - privileged mode or device access - container-to-host networking - registry authentication - multi-stage build behavior - BuildKit-specific assumptions Podman uses the broader containers ecosystem, including Buildah for image building. Docker commonly uses BuildKit through Docker’s build workflow. Both can create standards-compatible images, but scripts and advanced build features may need adjustment. ## Networking differences Basic port publishing and user-defined container networks are available in both runtimes. Differences become more visible with rootless networking, DNS behavior, host access, and applications that rely on Docker-specific network conventions. Before migrating, test: - service-to-service name resolution - published host ports - IPv4 and IPv6 behavior - access from containers to host services - reverse proxy discovery - firewall interaction - rootless networking performance - database connections over private interfaces Do not expose databases or internal services publicly to avoid solving container networking correctly. Keep public ingress separate from private application traffic. ## Volumes and persistent data Container replacement should not destroy application data under either runtime, but persistent storage requires explicit ownership and backup decisions. Named volumes are convenient when the runtime should manage the storage location. Bind mounts are useful when operators need a visible host path or external tooling must access the same files. Rootless Podman can expose UID and GID mapping differences that were hidden in a rootful Docker deployment. A container may run correctly but lose write access to an existing bind mount because the effective user mapping changed. Before switching runtimes: 1. identify every persistent path 2. record ownership and permissions 3. stop application writes consistently 4. take an application-aware backup 5. test volume access under the new runtime 6. verify restore before removing the old environment Use [Docker Volumes vs Bind Mounts](/learn/guides/docker-volumes-vs-bind-mounts-production) for the storage decision itself. ## systemd and Quadlet Podman’s strongest Linux-specific advantage is Quadlet. Quadlet lets administrators define containers, pods, networks, volumes, images, and Kubernetes-style workloads through declarative files that generate systemd services. This gives container workloads standard Linux service behavior through `systemctl`, dependencies, startup ordering, restart policies, logging integration, and rootless or rootful unit paths. Quadlet is useful when: - containers are long-running server services - the team already operates systemd confidently - Kubernetes would be excessive - boot ordering and service dependencies matter - rootless per-user services are desired - the team wants declarative host-level service definitions Docker can also run reliable system services through restart policies, Compose, and systemd-managed Docker Engine. The difference is that Quadlet makes systemd a first-class deployment interface rather than an outer wrapper around a separate runtime workflow. ## Pods in Podman Podman includes pods as a native concept. Containers in a pod can share selected namespaces and be managed as a group. This can be useful for tightly coupled services, sidecars, or workloads adapted from Kubernetes-style pod definitions. It does not make Podman a replacement for a Kubernetes cluster. A Podman pod remains tied to the lifecycle and capacity of its host unless the team adds external orchestration. It does not automatically provide multi-node scheduling, cluster reconciliation, service discovery across hosts, or managed control-plane behavior. Use Podman pods when grouping containers on one Linux system simplifies operations. Use orchestration when the requirement is coordinating workloads across multiple nodes. ## Tooling and ecosystem compatibility Docker has the larger default ecosystem. Many tools expect: - the Docker CLI - the Docker API - the Docker socket - Docker Compose - Docker-specific event and metadata behavior Podman can provide compatibility for many of these cases, but compatibility should be verified tool by tool. Mounting a runtime socket into management software also creates a high-trust control path, regardless of which runtime provides it. Docker is usually the better fit when the environment depends heavily on: - vendor documentation written only for Docker - Docker Desktop workflows - Compose-based self-hosted applications - CI systems using Docker socket patterns - dashboards and automation built around the Docker API - developers who need the same commands across laptops and servers Podman is usually the better fit when the environment depends more on: - Linux servers rather than desktop development - systemd operations - rootless services - Red Hat and Fedora container tooling - pods or Kubernetes YAML on one host - minimal dependence on Docker-specific APIs ## Performance considerations Runtime performance is rarely the deciding factor for ordinary web applications. Application architecture, image design, storage latency, database behavior, network path, CPU contention, and host sizing usually matter more. Avoid universal claims that one runtime is faster. Rootless networking, storage drivers, build caching, security layers, and the exact workload can change results. Benchmark the operation that matters: - image build time - application startup - HTTP latency and throughput - persistent storage I/O - network throughput - memory overhead - recovery after reboot - deployment and rollback duration A benchmark from another provider, operating system, or storage driver may not predict the result on your host. ## When Docker is the better choice Choose Docker when most of these statements are true: - the team already uses Docker Compose - vendor documentation assumes Docker - developer onboarding and broad familiarity matter - CI/CD tooling relies on Docker APIs or sockets - applications are already tested on Docker - the team wants the widest troubleshooting ecosystem - there is no explicit requirement for Podman’s operating model For most small teams deploying common web applications, Docker remains the practical default. ## When Podman is the better choice Choose Podman when most of these statements are true: - rootless operation is a defined requirement - the team is Linux- and systemd-oriented - long-running services fit Quadlet well - a central daemon is undesirable - Docker-specific tooling is limited - pod management on one host is useful - the team can test Compose and networking compatibility Podman is not only a development alternative. It can be a strong production runtime when its Linux-native operating model matches the team. ## Migration checklist Do not begin by replacing the `docker` command with an alias in production. Begin with an inventory. 1. List containers, images, networks, volumes, secrets, and exposed ports. 2. Identify Compose features and Docker API dependencies. 3. Find applications mounting the Docker socket. 4. Record volume ownership and backup every persistent dataset. 5. Test the stack on a non-production host. 6. Validate rootless networking and filesystem permissions. 7. Replace runtime-specific health, logging, and restart assumptions. 8. Decide whether Compose or Quadlet owns production lifecycle. 9. Test host reboot, service restart, rollback, and restore. 10. Keep the old environment recoverable until acceptance checks pass. Migration is successful only when normal deployments and incident recovery both work. ## Decision framework Use this order: 1. **Compatibility:** Does the application or tool require Docker-specific APIs or Compose behavior? 2. **Security model:** Is rootless operation an explicit requirement, and have its limitations been tested? 3. **Operations:** Does the team prefer Compose and Docker tooling or systemd and Quadlet? 4. **Development parity:** Must laptops, CI, staging, and production use the same runtime? 5. **Migration cost:** Are storage, networking, and automation dependencies understood? 6. **Supportability:** Which runtime can the team diagnose confidently during an incident? When the answers are unclear, keep Docker. Switch to Podman when the expected operational benefit is specific enough to justify compatibility testing. ## How this applies on Raff Both runtimes can operate on a [Raff Linux VM](/products/linux-vm). Choose the VM size from actual application, build, database, and concurrency requirements rather than assuming the runtime determines capacity. Use [Private Cloud Networks](/products/private-cloud-networks) when containerized applications communicate with databases, caches, workers, or internal services across multiple VMs. Keep persistent data protected with application-aware backups and appropriate [Data Protection](/products/data-protection) controls. Docker is the simpler starting point for teams following common Compose-based tutorials. Podman is appropriate when the team deliberately wants rootless operation and Quadlet-managed Linux services. ## Conclusion Docker offers the broadest compatibility and the most familiar Compose-centered workflow. Podman offers a daemonless, rootless-friendly model with strong systemd integration through Quadlet. For most small teams, Docker remains the default. Move to Podman when rootless execution, Linux-native service management, or the daemonless architecture solves a documented requirement—not only because the commands look similar. :::cta Deploy Your Server Run Docker or Podman on a Raff Linux VM sized for your application and operational model. ::: ## Sources - [Docker Engine overview](https://docs.docker.com/engine/) - [Docker rootless mode](https://docs.docker.com/engine/security/rootless/) - [Podman documentation](https://docs.podman.io/en/latest/markdown/podman.1.html) - [Podman Quadlet documentation](https://docs.podman.io/en/latest/markdown/podman-quadlet.1.html) - [Podman systemd unit documentation](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html) - Date verified: 2026-07-29 --- ### VM Disk Storage for Production Apps: Capacity, Performance, and Failure Risks URL: https://rafftechnologies.com/learn/guides/vm-disk-storage-production-apps Description: Learn how to evaluate VM disk storage for production apps, including capacity planning, local storage benefits, failure risks, and when to use other storage layers. VM disk storage is the local storage attached to a virtual machine that holds the operating system, application runtime, and workload data. For production applications, the important decision is not only how much disk capacity exists, but which data should remain tied to one VM and which data should move to a separate storage layer. A small application often starts with one VM disk because it is simple: install the software, store files locally, and deploy. That model can work. The risk appears when the same disk becomes responsible for the operating system, databases, uploads, logs, backups, and generated files without clear ownership or recovery planning. Raff Technologies supports teams using VM-based workloads where storage decisions affect reliability, recovery, and scaling. This guide explains how to evaluate VM disk storage for production apps, when local storage is enough, when attached volumes or object storage are better, and which risks teams should consider before making storage architecture decisions. This guide belongs to the [VM & Local Storage](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) cluster. For the broader storage decision framework, read [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk). For moving persistent data away from the system disk, read [When to Add a Volume Instead of Resizing a VM Disk](/learn/guides/add-volume-vs-resize-vm-disk). ## VM disk works best when data belongs to the server lifecycle A VM disk is closely connected to one virtual machine. It normally contains the operating system, installed packages, application runtime, configuration files, temporary files, and local service data. A simple production layout often starts here: ```text VM disk ├── Operating system ├── Application runtime ├── Configuration ├── Logs └── Temporary files ``` This model works well when: - the workload runs on one VM; - the application can be rebuilt from code and configuration; - local files are small or temporary; - storage growth is predictable; - recovery requirements are simple; - the team understands what must be restored. The advantage of VM disk storage is operational simplicity. There is one server, one filesystem, and fewer moving parts. For prototypes, internal tools, and early applications, this simplicity can be valuable. The limitation is coupling. When important production data grows on the same disk as the runtime, replacing or recovering the VM becomes a larger operation. ## Production storage decisions depend on data ownership The main question is not whether VM disk storage is good or bad. The question is whether the data belongs to the VM lifecycle. | Data type | Better default | Reason | |---|---|---| | Operating system | VM disk | Part of server runtime | | Application binaries | VM disk | Usually rebuilt from deployment process | | Configuration files | VM disk or secret system | Required for service startup | | Temporary processing files | VM disk or volume | Depends on size and lifetime | | Database data directory | Block volume or managed database | Needs persistent storage boundary | | User uploads | Object storage | Should survive VM replacement | | Backup archives | Object storage | Should exist outside source VM | | Large media files | Object storage | Independent file lifecycle | | Container persistent state | Block volume | Needs filesystem persistence | A healthy architecture gives each data category a clear home. A risky architecture stores everything together: ```text One VM disk ├── OS ├── app ├── database ├── uploads ├── backups ├── logs └── generated files ``` The second model may work initially, but every failure scenario becomes harder to isolate. ## Disk capacity planning should include growth and recovery Disk sizing is not only about today's usage. Production planning should consider: - current data size; - monthly growth rate; - temporary workspace requirements; - application logs; - database growth; - package updates; - backup artifacts; - restore requirements; - emergency headroom. A disk that starts at 20% usage can still become a production problem if growth is not monitored. A practical planning model: | Factor | Question | |---|---| | Current usage | How much storage is used today? | | Growth | How quickly does data increase? | | Peaks | Are imports, builds, or reports temporary spikes? | | Cleanup | Which files can be removed automatically? | | Recovery | How much space is needed during restore? | | Alerts | Who knows when capacity becomes unsafe? | Production disks should have monitoring before they become full. A full filesystem can affect more than storage. It can prevent application writes, database operations, package updates, logging, and system maintenance. ## Local VM storage has clear performance advantages Local VM storage can be useful when applications need low-latency access close to compute. Examples: - application runtime files; - package caches; - temporary processing data; - build workspace; - local indexes that can be recreated; - short-lived files. Local NVMe-backed storage can provide fast access for workloads that do not require independent storage lifecycle management. The key consideration is not only speed. It is recoverability. A local disk may perform well, but if important data exists only there, the recovery design must account for that dependency. Choose local VM storage when: - latency matters; - data is rebuildable; - data is temporary; - the workload is tied to one server; - operational simplicity matters. Choose another storage layer when: - data must survive VM replacement; - multiple services need access; - retention matters; - recovery requires historical copies; - storage should scale independently from compute. ## VM disk failure affects the whole workload boundary A VM disk is part of the server it belongs to. That means disk issues can affect: - operating system availability; - application startup; - local configuration; - temporary processing; - local databases; - container data; - logs. The impact depends on what the disk contains. A VM disk holding only application runtime has a different recovery profile from a VM disk holding the production database. Consider these scenarios: | Scenario | VM disk impact | |---|---| | OS failure | Restore or rebuild server runtime | | Application package issue | Redeploy or restore runtime | | Full disk | Application and database writes may fail | | Corrupted local data | Requires recovery from valid copy | | VM replacement | Requires migration of important data | | Accidental deletion | Needs restore point or backup | This is why storage separation improves reliability. It reduces the number of things that fail together. ## Production apps often move data beyond the VM disk As applications mature, teams usually separate storage responsibilities. A common pattern: ```text VM disk └── OS, application runtime, temporary files Block volume └── Database files or persistent service state Object storage └── Uploads, reports, archives, generated files Backups └── Recovery copies and retention history ``` This does not mean every application needs every layer immediately. A small internal tool may remain on one VM disk for a long time. A customer-facing SaaS application may need separation earlier because customer data, recovery expectations, and uptime requirements are higher. The right time to separate storage is when it reduces operational risk. ## VM disk and backup strategy must be designed together A VM backup protects what exists on the VM. That makes storage placement important. If uploads, databases, and archives all live on one VM disk: - backups become larger; - restores become slower; - recovery scope becomes broader; - temporary files may be included unnecessarily. A clearer model separates active runtime from durable data. For example: ```text Application VM ↓ Runtime backup Database ↓ Database-aware backup Object storage ↓ File retention and archive policy ``` A backup strategy should answer: - What data is on the VM disk? - What data can be rebuilt? - What data needs historical recovery? - How long should recovery copies exist? - Has restore been tested? A backup job alone does not create a recovery plan. ## Raff storage choices follow workload behavior Raff supports different storage roles because production workloads do not all need the same storage model. A practical architecture can combine: ```text Raff VM ├── application runtime └── temporary local workload files Raff Volumes └── persistent disk-style data Raff Object Storage └── durable files and archives Data Protection └── recovery points ``` Use VM disk when the data belongs to the server runtime. Use [Raff Volumes](/products/volumes) when a workload needs persistent disk behavior separated from compute. Use [Raff Object Storage](/products/object-storage) when files should exist independently from a single VM. Use [Raff Data Protection](/products/data-protection) when recovery points and retention matter. The important design decision is assigning each data type the right storage boundary. ## VM disk readiness checklist Before using VM disk as a production data location, confirm: - [ ] The team knows what data lives on the disk. - [ ] Storage growth is monitored. - [ ] Disk usage alerts are configured. - [ ] Temporary files have cleanup rules. - [ ] Logs have retention rules. - [ ] The application can be redeployed. - [ ] Important data has a separate recovery plan. - [ ] Database data has database-aware protection if required. - [ ] Uploads have a defined storage strategy. - [ ] Restore procedures are documented. - [ ] Recovery tests are performed. - [ ] The VM owner is documented. A simple disk layout can be reliable when ownership and recovery are clear. ## Common VM disk mistakes ### Storing every data type on one disk A single disk can become responsible for unrelated workloads. Separate storage when data ownership becomes unclear. ### Scaling compute because storage grows If only storage grows, a larger VM may not be the right solution. An attached volume or object storage may fit better. ### Keeping uploads on the application server forever User files often need a longer lifecycle than the VM. Object storage usually provides a cleaner boundary. ### Treating snapshots as a complete backup plan Snapshots are useful recovery points, but they do not replace retention planning and restore testing. ### Ignoring disk monitoring Storage failures are often predictable. Alerts should exist before capacity becomes critical. ## VM disk is a foundation, not always the final storage layer VM disk remains an important part of cloud architecture. It provides the runtime environment where applications execute and where rebuildable files can live. The decision point is knowing when data has outgrown the VM lifecycle. Keep runtime close to compute. Move persistent data to storage designed for its behavior. Move durable files to object storage when they should survive server changes. Protect important recovery paths with tested backups. A production application does not need the most complex storage design. It needs a design where the team understands what is stored, where it is stored, and how it comes back after failure. :::cta Explore Volumes Use Raff Volumes when production data needs persistent storage separate from the VM system disk. ::: ## Sources - [AWS Storage Types Overview](https://aws.amazon.com/compare/the-difference-between-block-file-object-storage/) - [Google Cloud Storage Options Comparison](https://cloud.google.com/discover/object-vs-block-vs-file-storage) - [Raff Volumes](/products/volumes) - [Raff Object Storage](/products/object-storage) - Date verified: 2026-08-06 --- ### Backup Retention Policy Explained: Production VM Recovery Points URL: https://rafftechnologies.com/learn/guides/backup-retention-policy-production-vms Description: Learn how a backup retention policy sets daily, weekly, and monthly recovery points for production VMs while balancing restore needs, risk, and cost control. A **backup retention policy is a recovery-governance document that defines how long backup copies remain available for a workload.** It turns recovery needs into a controlled set of recent and historical recovery points rather than keeping every copy forever or deleting backups on an arbitrary schedule. For production virtual machines, retention should reflect how quickly failures are detected, how far the team may need to roll back, and how much recovery history the business can justify. A policy with **7 daily, 4 weekly, and 12 monthly recovery points creates 23 checkpoints** before any annual copies are considered. The number is easy to calculate; the harder decision is whether those checkpoints cover the failures the application can actually experience. Raff supports teams operating VM-based workloads where snapshots, backups, databases, attached storage, and application data may have different recovery requirements. In Raff infrastructure reviews, the recurring retention gap is usually an undefined owner who cannot explain why a recovery point is kept, when it expires, or how it would be restored. This guide provides a decision framework for production VM retention. Broader backup architecture belongs in [Cloud Server Backup Strategy](/learn/guides/cloud-server-backup-strategies), while the control-level difference between snapshots and backups belongs in [Cloud Snapshots vs Backups](/learn/guides/snapshots-vs-backups-cloud-server). ## A backup retention policy separates schedule from retention Backup frequency and backup retention answer different questions. - **Schedule:** How often is a recovery point created? - **Retention:** How long does that recovery point remain available? - **Recovery objective:** Which failure window must the retained set cover? - **Deletion rule:** When may a recovery point be removed? - **Ownership:** Who approves, monitors, restores, and changes the policy? A production VM may be backed up every day but retain only the latest 7 daily recovery points. Another workload may create one weekly recovery point and keep it for 12 weeks. The schedule controls potential data loss between copies; retention controls how far back recovery can reach. This distinction prevents a common mistake: increasing backup frequency without preserving enough history. Hourly backups retained for 24 hours may provide a narrow recovery point objective, but they cannot recover a configuration error discovered three weeks later. Conversely, monthly backups retained for a year provide long history but may lose too much recent data after an operational failure. A complete retention record should state: ```text Protected workload Backup method Creation schedule Daily retention Weekly retention Monthly retention Annual retention, if required Immutability or deletion protection Recovery owner Policy review date Restore-test evidence ``` Retention should be written at the workload level. A public website, an internal reporting VM, a transactional SaaS database, and an archive server should not inherit the same policy merely because they share an infrastructure account. ## Recovery windows should follow detection delay The most important retention input is often **incident-detection delay**: the time between a damaging change and the moment the team realizes recovery is needed. Some failures are discovered immediately: - a failed deployment; - an unbootable VM; - a filesystem error; - an accidental volume detach; - a service that stops responding. Others appear later: - silent data corruption; - an unauthorized configuration change; - an application bug that modifies records gradually; - a deleted customer file reported weeks later; - a compromised credential used intermittently; - an incomplete migration discovered after normal business cycles. A policy that keeps only recent copies may handle immediate failures while failing late-discovery incidents. A policy that keeps only long-term monthly points may miss the precise state needed for a recent recovery. Use the following questions: 1. How quickly would monitoring reveal a failed VM or backup? 2. How long could incorrect data remain unnoticed? 3. How far back do customer, financial, or operational investigations normally reach? 4. How long does the team need to approve a restore? 5. Which contractual, regulatory, or internal requirements override the technical preference? 6. Can the workload be rebuilt from code while only data needs historical recovery? 7. Does a database require point-in-time recovery in addition to VM-level copies? The [RPO and RTO guide](/learn/guides/cloud-server-backup-rpo-rto-snapshots) defines acceptable data loss and recovery time. Retention adds a third practical dimension: **the oldest usable point the team may need after a late discovery**. ## The retention decision framework balances risk, restore needs, and cost A useful policy starts with workload consequence rather than a universal number of days. | Workload pattern | Recent recovery points | Historical recovery points | Main decision | | --- | --- | --- | --- | | Rebuildable web VM with external data | Short daily window | Few or no monthly VM copies | Preserve configuration and deployment evidence | | Internal application with moderate change | Daily plus weekly | Limited monthly history | Cover delayed user reports and failed updates | | Customer-facing SaaS VM | Frequent recent points | Weekly and monthly checkpoints | Balance fast rollback with late-discovery risk | | Database VM | VM copies plus database-aware backups | Retention aligned to database recovery | Avoid treating crash-consistent VM copies as the only protection | | Compliance-sensitive workload | Policy-defined tiers | Required long-term or immutable copies | Business and legal requirements override the example baseline | | Temporary or preview environment | Minimal or no historical retention | None unless business data exists | Prevent idle backup cost from outliving the environment | Choose **shorter retention** when the workload is reproducible, changes are detected quickly, and durable data already lives in an independently protected system. Choose **longer retention** when incidents may be discovered late, customers can request historical recovery, the workload changes slowly, or investigations require older states. Choose **multiple protection methods** when one copy cannot cover every failure. VM-level snapshots can support rapid infrastructure rollback, while database-aware backups, object-storage copies, or application exports may provide the historical and logical recovery that a VM image cannot. The policy should also name unacceptable gaps. For example: - no production VM without a recent successful recovery point; - no weekly tier missing two consecutive scheduled points; - no monthly checkpoint deleted before its replacement is verified; - no policy change without an owner and review date; - no critical workload relying on a restore process that has never been tested. ## Daily, weekly, and monthly tiers create a practical baseline A tiered retention model keeps more recovery points near the present and fewer points as they age. An illustrative policy for a small production VM might be: | Tier | Example retention | Purpose | | --- | ---: | --- | | Daily | 7 recovery points | Recent deployment, configuration, and operational failures | | Weekly | 4 recovery points | Problems discovered after several days | | Monthly | 12 recovery points | Longer investigations, seasonal workflows, and historical reference | | Annual | Only when required | Contractual, audit, or long-term business needs | This is an example, not a universal standard or legal recommendation. A high-change database may need more frequent database-native recovery. A low-risk rebuildable VM may need less history. A regulated workload may require substantially longer retention and stronger deletion controls. The tiered model works because the value of precision usually decreases with age. Yesterday's state may need several possible recovery points. Eleven months ago, one validated monthly point may be sufficient. Avoid selecting the same calendar event accidentally. If a weekly and monthly rule both choose the last Sunday of the month, confirm whether the backup system stores one point with the longer retention or creates multiple billed copies. Provider behavior differs. A retention calendar should also define: - which day becomes the weekly point; - which daily or weekly point becomes the monthly point; - time zone and backup window; - behavior when a scheduled backup fails; - whether a replacement point extends or resets retention; - how leap years and month-end dates are handled; - what happens when the policy is shortened. Retention changes can affect existing recovery points differently across platforms. Review the product's lifecycle behavior before reducing a policy, because older copies may expire sooner than expected or keep their original deletion date. ## Snapshots and backups need different retention roles Snapshots and backups can both create recovery points, but they should not automatically share one retention period. | Protection layer | Better role | Typical retention tendency | | --- | --- | --- | | Pre-change snapshot | Rapid rollback before an upgrade or risky change | Short-lived after validation | | Scheduled infrastructure snapshot | Recent VM or volume recovery | Short to medium window | | Independent backup | Historical recovery outside the active workload boundary | Medium to long window | | Database-aware backup | Logical, physical, or point-in-time database recovery | Based on transaction and data requirements | | Object archive | Long-lived files, exports, or backup sets | Based on file and archive policy | A pre-change snapshot should have an explicit expiry condition: remove it after the change passes validation and the next normal backup succeeds. Keeping every maintenance snapshot indefinitely creates cost and makes the recovery list harder to interpret. Historical backups should use a separate decision. They may need stronger access separation, independent credentials, immutable retention where supported, and a restore workflow that does not depend on the failed VM. The main rule is: > Keep snapshots long enough to cover infrastructure rollback, and keep independent backups long enough to cover historical recovery and late discovery. For object-level expiration, use [S3 Lifecycle Policy](/learn/guides/s3-lifecycle-policy). For database copies and point-in-time recovery, use [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps). ## Retention cost should be forecast before the policy is locked Longer retention increases the number of recoverable states, but the billed storage does not always equal the number of recovery points multiplied by the current VM size. Full-copy, incremental, deduplicated, compressed, and archive implementations behave differently. Use a provider-specific forecast: ```text Monthly protection cost = billed retained backup storage + snapshot or archive storage + restore and egress charges + required replication copies + operational testing cost ``` Forecast at least three scenarios: | Scenario | Assumption | Decision use | | --- | --- | --- | | Stable | Normal data-change rate | Expected monthly cost | | Growth | Data and retained changes increase | Budget and capacity planning | | Incident | Several temporary recovery points are kept longer | Change-window and investigation cost | Track the cost by workload owner, environment, and retention tier. A monthly checkpoint for an active production VM may have clear value. The same checkpoint for a deleted staging environment is usually orphaned cost. Cost control should not be based only on age. Before deleting a recovery point, confirm: - the workload still exists; - the point is not under investigation or hold; - a newer validated point covers the intended tier; - database or application backup chains remain usable; - the deletion will not remove the only independent copy; - the owner has approved the rule. Retention optimization is successful when unnecessary copies are removed without weakening the recovery window the business approved. ## Ownership, deletion protection, and testing make the policy enforceable A retention table without operational controls is only documentation. Each policy needs: - a workload owner; - a backup-system owner; - a recovery approver; - alerting for failed or stale recovery points; - restricted deletion permissions; - a process for emergency holds; - evidence of successful restore tests; - a review cadence; - a retirement process for decommissioned workloads. Deletion protection or immutable retention can reduce the risk of an attacker or administrator removing recovery points prematurely. It also makes mistakes expensive and persistent. Configure minimum and maximum retention carefully before locking a policy, because immutable copies may remain billable until their lifecycle completes. Restore testing should sample different ages and tiers. A recent daily point proves one path; it does not prove that a monthly point, archived copy, encryption key, database chain, or application dependency can still be restored. A practical quarterly review asks: 1. Did every scheduled tier create the expected points? 2. Were any failures unresolved beyond the approved window? 3. Can the team restore a recent and an older point? 4. Are encryption keys, credentials, and documentation available? 5. Did workload size or change rate alter cost materially? 6. Do deleted environments still have retained copies? 7. Have business, customer, or compliance requirements changed? NIST contingency-planning guidance treats testing, exercises, and plan maintenance as part of the recovery lifecycle. The [Restore Testing Checklist](/learn/guides/restore-testing-checklist-production-vms) provides the operational evidence needed to support the retention policy. ## Raff Data Protection fits a documented recovery model Raff Data Protection can be part of a production VM recovery design alongside application-aware and database-aware protection. The retention policy should still be written before the team enables or changes recovery schedules. A practical Raff model is: ```text Raff VM and attached workload storage ↓ Recent infrastructure recovery points ↓ Weekly and monthly recovery checkpoints ↓ Independent database or application copies where required ↓ Restore testing and documented ownership ``` Use [Raff Data Protection](/products/data-protection) for the infrastructure recovery layer. Use [Raff Object Storage](/products/object-storage) when backup tools or applications need an S3-compatible destination for independent files or archives. Use database-native backup methods when the workload requires logical recovery or point-in-time recovery. From Raff infrastructure reviews, the clearest policy is one where every tier has a sentence explaining its purpose. “Keep 12 monthly points” is incomplete. “Keep 12 monthly points to cover delayed customer reports, annual operational review, and rollback beyond the weekly window” is an actionable decision. The retention model should remain portable. Record the schedule, expiry rules, recovery ownership, and validation evidence independently of the provider interface so the team can audit or migrate the protection design later. :::cluster ## Conclusion A backup retention policy should preserve enough recovery history to cover both immediate failures and incidents discovered later. Separate schedule from retention, use frequent recent points and fewer historical checkpoints, and give snapshots, independent backups, and database-aware copies distinct roles. Forecast the billed storage model before locking long retention, restrict deletion, and test more than the newest recovery point. The illustrative 7-daily, 4-weekly, and 12-monthly model is a starting framework, not a universal requirement. Continue with [Cloud Snapshots vs Backups](/learn/guides/snapshots-vs-backups-cloud-server) to choose the protection layer and [Restore Testing Checklist](/learn/guides/restore-testing-checklist-production-vms) to prove that retained copies can return the workload to service. :::cta Explore Data Protection Plan recent and historical recovery points for your Raff VM workloads. ::: ## Sources - [NIST SP 800-34 Rev. 1: Contingency Planning Guide for Federal Information Systems](https://csrc.nist.gov/pubs/sp/800/34/r1/final) - [AWS Backup: Backup Plans](https://docs.aws.amazon.com/aws-backup/latest/devguide/about-backup-plans.html) - [AWS Backup Vault Lock](https://docs.aws.amazon.com/aws-backup/latest/devguide/vault-lock.html) - [Microsoft Azure Backup Architecture](https://learn.microsoft.com/en-us/azure/backup/backup-architecture) - [Google Cloud: Perform Testing for Recovery from Data Loss](https://cloud.google.com/architecture/framework/reliability/perform-testing-for-recovery-from-data-loss) - [Google Cloud Backup and DR Overview](https://cloud.google.com/backup-disaster-recovery/docs/concepts/backup-dr) - [Raff Data Protection](/products/data-protection) - Date verified: 2026-08-06 --- ### Backup Monitoring: Failures, Age, Alerts, and Recovery Evidence URL: https://rafftechnologies.com/learn/guides/backup-monitoring-failures-age-alerts-recovery-evidence Description: Learn how backup monitoring detects failed and stale recovery points, broken chains, storage issues, and restore evidence that no longer meets production recovery objectives. **Backup monitoring is the process of checking whether recovery points are being created on time, remain usable, and still meet the workload's recovery objectives.** A completed job is only one signal. Production monitoring must also detect stale backups, missing schedules, broken chains, storage failures, expiring credentials, and restore evidence that is too old to trust. Raff infrastructure reviews show a recurring pattern: teams often notice a failed backup only when they need to restore. The backup system may have sent an email, but nobody owned the alert, the message was filtered, or the team monitored job completion without checking backup age. This guide defines a compact operating model for production virtual machines, databases, and application data. Use [Backup Retention Policy Explained](/learn/guides/backup-retention-policy-production-vms) to decide how long recovery points should remain available. Use [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms) to verify that retained copies can actually return a workload to service. ## Backup monitoring must prove current recovery coverage A useful backup dashboard should answer five questions: 1. Did the expected backup run? 2. Did it finish successfully? 3. Is the newest usable recovery point recent enough? 4. Is the retained recovery chain complete and accessible? 5. Has the restore path been tested recently enough to trust? These questions separate job status from recovery readiness. | Signal | What it proves | What it does not prove | | --- | --- | --- | | Job completed | The process reached a success state | The backup contains valid data | | Backup size recorded | Data was written | The data is complete or restorable | | Recovery point exists | A restore object is present | Credentials, keys, and dependencies are available | | Retention policy passed | Expected copies remain | The correct workload was protected | | Restore test passed | A selected copy restored successfully | Every recovery point or dependency will work | A production backup should not be considered healthy because the last job was green. Health is the combination of recency, completeness, accessibility, retention, and restore evidence. ## Backup age is the primary operational signal The simplest and most valuable monitoring metric is often **backup age**: the time since the newest successful and usable recovery point. ```text Backup age = current time - newest usable recovery-point time ``` Compare backup age with the approved backup interval and recovery point objective (RPO). For example, if a workload should create a backup every 6 hours and the newest usable point is 14 hours old, the team has missed at least one expected cycle. The job dashboard may show one recent failure, but backup age expresses the real recovery exposure. Track separate age values where needed: - newest VM or volume recovery point; - newest database-native backup; - newest transaction-log or binary-log archive; - newest object-storage copy; - newest off-account or off-system copy; - newest successfully tested recovery point. A backup-age alert should include: - protected workload; - environment; - expected interval; - current backup age; - last successful point; - last attempted job; - failure reason, if known; - owner and escalation path; - first safe diagnostic action. **Raff recommends monitoring backup age rather than relying only on failure emails because age captures missed schedules, silent failures, and disabled jobs with one measurable signal.** ## Monitoring should cover failures, warnings, and missing jobs Backup jobs can fail in more than one way. ### Hard failures require immediate investigation Examples include: - backup process exited with an error; - source disk or database was unavailable; - destination storage rejected the write; - credentials expired or permissions changed; - encryption keys were unavailable; - snapshot creation failed; - backup chain became inconsistent; - storage capacity was exhausted; - network interruption stopped transfer; - retention or lifecycle action deleted a required dependency. ### Warning states need policy-based handling A job may complete with warnings such as skipped files, partial databases, inaccessible paths, failed verification, or an unexpectedly small data set. Warnings should not be treated as success automatically. Define which warning classes: - page immediately; - create an urgent ticket; - enter scheduled review; - may be ignored with documented justification. ### Missing jobs must be detected independently A disabled schedule, deleted cron entry, broken agent, stopped service, or decommissioned automation may produce no failure event. This is why the monitoring system should expect a heartbeat or new recovery point by a deadline. ```text Expected backup deadline = previous successful point + allowed interval + grace period ``` Alert when the deadline passes without a new usable point, even if no job reported failure. ## Backup size and change rate reveal silent problems Backup size is not a quality metric by itself, but sudden changes can identify missing data or abnormal growth. Monitor: - current backup size; - comparison with the previous successful point; - rolling average or expected range; - protected source size; - compression or deduplication behavior; - changed-data volume; - destination storage growth; - estimated time to storage exhaustion. Examples that deserve investigation: - a database backup drops from 40 GB to 400 MB; - a VM backup remains exactly the same size despite significant workload growth; - daily changed-data volume increases tenfold after a deployment; - object count falls unexpectedly; - a backup completes unusually quickly; - retained storage grows after a policy change more than forecast. Thresholds should follow workload behavior. A percentage rule that works for a stable database may generate noise for an application with seasonal uploads or log-heavy activity. Use a baseline and rate-of-change model rather than one universal number. ## Backup chains and dependencies require continuity monitoring Incremental backups, transaction logs, binary logs, archive logs, and snapshot chains may depend on earlier recovery points. A successful latest job is not useful if the required chain is incomplete. Monitor: - base or full backup availability; - incremental dependency continuity; - transaction-log sequence gaps; - archive upload failures; - retention rules that may delete a parent copy; - encryption-key availability; - catalog or manifest integrity; - destination permissions; - cross-account or cross-system replication status. For databases, VM-level recovery points may not replace database-native protection. A database can require logical backups, physical backups, or point-in-time recovery logs in addition to infrastructure snapshots. Use [Database Backup Strategy for SaaS Apps](/learn/guides/database-backup-strategy-saas-apps) for the protection model. Monitoring should then verify each layer separately. ## The alert framework should match recovery risk Small teams should separate immediate pages from tickets, reviews, and evidence records. | Alert class | Trigger | Response expectation | | --- | --- | --- | | Page | RPO is breached or critical recovery chain is broken | Respond immediately | | Urgent ticket | Backup is approaching the recovery limit | Resolve within a defined window | | Scheduled review | Growth, warning, or restore evidence is becoming stale | Review during operations cycle | | Dashboard | Context for investigation | No standalone response | | Audit evidence | Policy, job, and restore records | Retain for review or customer assurance | A practical threshold model is: ```text Warning threshold = expected interval + normal processing delay Critical threshold = approved RPO or maximum backup age ``` If the schedule is every 6 hours, normal completion takes 45 minutes, and the approved RPO is 12 hours: - warning may begin after 7 hours; - critical alert begins at 12 hours; - the alert remains open until a new usable point exists. Do not clear an alert because a new job started. Clear it only when recovery coverage is restored. ## Every alert needs ownership and a recovery condition A backup alert without an owner becomes background noise. Record: - workload owner; - backup-system owner; - incident escalation contact; - business approver for policy changes; - destination-storage owner; - restore-test owner; - expected response time; - recovery confirmation criteria. The runbook should identify the first safe actions: 1. Confirm the newest usable recovery point. 2. Check whether the job ran, failed, or never started. 3. Inspect source availability and free space. 4. Verify destination access, credentials, and capacity. 5. Check encryption keys and required services. 6. Identify whether the failure affects one workload or the entire backup system. 7. Create a manual recovery point only when it will not damage the chain or overload production. 8. Confirm that the new point is visible and valid. 9. Preserve failure evidence for follow-up. Avoid deleting failed jobs, logs, or old recovery points during the initial investigation unless storage exhaustion creates a separate emergency. ## Restore-test age belongs on the backup dashboard The last successful restore-test date is a monitoring signal, not merely an audit note. ```text Restore-test age = current time - last verified restore date ``` Track at least: - date of the last test; - recovery point used; - environment restored into; - restore duration; - validation result; - data or application checks performed; - engineer or owner; - unresolved findings; - next test deadline. A backup can remain green for months while the restore process gradually breaks because credentials change, documentation becomes outdated, dependencies disappear, or the workload grows beyond the tested recovery window. Use age-based alerts for restore evidence: - warning when the next test window approaches; - critical governance alert when the approved test interval is exceeded; - incident alert when a restore attempt fails and no alternative validated path exists. **A successful backup job proves that data was written; a successful restore test proves that the team can use a recovery point.** ## Monitoring coverage should follow the workload boundary Different workloads need different signals. | Workload | Minimum monitoring coverage | | --- | --- | | Rebuildable web VM | Backup age, job status, configuration copy, restore-test date | | Stateful application VM | VM backup age, application-data backup, storage growth, restore evidence | | Database VM | Database-native backup, log continuity, VM recovery point, restore-test age | | Object storage backup target | Upload success, object count, lifecycle actions, access, retention, capacity | | Multi-VM application | Coverage by service, database, storage, and recovery order | | Temporary environment | Explicit policy showing whether backups are required | The monitoring inventory should detect unprotected workloads. Compare the infrastructure inventory with the backup-policy inventory and report: - production workloads without a policy; - policies without active jobs; - jobs without an owner; - workloads with no recent restore test; - decommissioned workloads still consuming retention storage; - destination accounts or buckets without access review. ## Dashboards should remain compact and decision-oriented A useful backup dashboard for a small team can contain: - protected workloads and policy status; - newest usable recovery-point time; - backup age versus RPO; - last job result; - consecutive failure count; - warning or partial-success count; - retained recovery-point count; - destination storage usage and growth; - chain or archive continuity; - last restore-test date and result; - open incidents and ownership. Group by environment and business importance. Put production and recovery-risk breaches first. Avoid combining unrelated warning states into one green or red number that hides the reason. The dashboard should support these decisions: - Is recovery coverage currently intact? - Which workload is closest to breaching its RPO? - Which failure needs immediate action? - Which backup chain is incomplete? - Which restore evidence is stale? - Which workload has no clear owner? ## Raff Data Protection should fit a wider monitoring model Raff Data Protection can provide the infrastructure recovery layer for Raff VM workloads. Teams should still document monitoring ownership, expected schedules, backup-age thresholds, and restore-test evidence. A practical model is: ```text Raff VM workload ↓ Infrastructure recovery points ↓ Backup-age and failure monitoring ↓ Independent application or database copies where required ↓ Restore testing and evidence review ``` Use [Raff Data Protection](/products/data-protection) for VM-level recovery planning. Use [Raff Object Storage](/products/object-storage) when backup tools or applications require an S3-compatible destination for independent files, exports, or archives. From Raff operations reviews, the most reliable monitoring rule is also the simplest: every production workload should have a named maximum backup age and a named owner who receives the alert before that age is exceeded. :::cluster ## Conclusion Backup monitoring should prove current recovery coverage, not merely display completed jobs. Track backup age, failed and missing jobs, warning states, unexpected size changes, destination capacity, chain continuity, credentials, retention, and restore-test age. Page when the approved RPO is breached or the recovery chain is broken. Use tickets and scheduled reviews for approaching limits, warning trends, and stale evidence. A compact monitoring model should tell the team which workload is unprotected, how long the gap has existed, who owns the response, and what confirms recovery. Continue with [Backup Retention Policy Explained](/learn/guides/backup-retention-policy-production-vms) to define recovery-point history and [Restore Testing Checklist](/learn/guides/restore-testing-checklist-production-vms) to validate that monitored backups can restore the workload. :::cta Explore Data Protection Monitor recovery coverage and protect Raff VM workloads with documented backup policies. ::: ## Sources - [AWS Backup monitoring](https://docs.aws.amazon.com/aws-backup/latest/devguide/monitoring.html) - [AWS Backup metrics with CloudWatch](https://docs.aws.amazon.com/aws-backup/latest/devguide/cloudwatch.html) - [Microsoft Azure Backup monitoring and alerts](https://learn.microsoft.com/en-us/azure/backup/monitoring-and-alerts-overview) - [Google Cloud Backup and DR monitoring](https://cloud.google.com/backup-disaster-recovery/docs/monitoring) - [NIST SP 800-34 Rev. 1](https://csrc.nist.gov/pubs/sp/800/34/r1/final) - [Raff Data Protection](/products/data-protection) - Date verified: 2026-08-06 --- ### What Is Self-Hosting? When It Makes Sense and How to Start URL: https://rafftechnologies.com/learn/guides/self-hosting-getting-started Description: Self-hosting means running applications on servers you control instead of a vendor's SaaS. Learn when it makes sense, what to operate, and what server you need. Self-hosting means running software on infrastructure you control instead of relying entirely on a third-party SaaS provider. **It makes sense when control, portability, customization, or predictable infrastructure cost is worth the responsibility of operating the service yourself.** The decision is not simply SaaS versus open source. A self-hosted application still needs compute, storage, backups, patching, monitoring, access control, and a named owner. When those responsibilities are unclear, SaaS or a managed service is usually the safer choice. This guide explains how to decide what to self-host, where to run it, and which operational controls must exist before the service becomes business-critical. ## What is self-hosting? Self-hosting is the practice of running applications on a server you control, either your own hardware or a rented cloud VM, instead of using the vendor's hosted SaaS version. You install the software, own the data, and manage updates, backups, and access yourself. The term covers more than home servers. In the self-hosting community, renting a VPS or cloud VM and running your own services on it counts as self-hosting: what matters is who controls the software and the data, not where the hardware sits. | Question | Hosted (SaaS) | Self-hosted | |---|---|---| | Who runs the software? | The vendor | You | | Where does the data live? | The vendor's cloud | Your server | | Who handles updates and backups? | The vendor | You | | Cost model | Per user or per seat | Server plus your time | | Customization | Limited to plan features | Full control | Common examples: Nextcloud instead of Dropbox, Jellyfin instead of streaming subscriptions, n8n instead of Zapier, Vaultwarden instead of a hosted password manager. ## Self-hosting is an ownership decision Self-hosting changes who is responsible for the service. With SaaS, the vendor typically operates the application platform, updates, and much of the availability model. With self-hosting, your team owns more of the stack: - operating system and runtime - application updates - authentication and administrator access - network exposure - persistent data - backups and restore testing - monitoring and incident response - migration and exit planning The benefit is control. The cost is operational responsibility. A useful first question is: > If this service fails at 2 a.m., who is expected to restore it? If nobody owns the answer, the application is not ready to become critical infrastructure. ## Why teams choose self-hosting ### Data control Self-hosting can provide direct control over where application data, logs, files, and configuration are stored. This is valuable when the data is strategic, difficult to export, or subject to internal location and retention requirements. Self-hosting does not make data secure automatically. The team must still patch the service, restrict access, encrypt sensitive paths where needed, and maintain recoverable backups. ### Portability and vendor independence Many self-hosted applications use standard Linux environments, containers, databases, and file formats. That can make the workload easier to move between providers than a proprietary SaaS workflow with limited export options. Real portability requires more than an open-source license. You need: - documented configuration - exportable data - known dependencies - tested backups - a repeatable deployment process - credentials and encryption keys under team control ### Customization and integration Self-hosting can be useful when the application must connect deeply to internal systems, use custom plugins, expose direct APIs, or follow a workflow that a standard SaaS plan does not support. Customization should remain intentional. Every modification can create upgrade and support work later. ### Cost structure Self-hosting may replace per-user pricing with infrastructure pricing. That can be attractive for predictable, lightweight services used by many internal users. The complete cost includes: ```text compute and storage + backups + monitoring + administrator time + updates + incident response + migration and recovery work ``` A lower subscription bill does not guarantee a lower total operating cost. ## The self-hosting decision framework ![Self-hosting decision framework showing SaaS, cloud VPS, home server, hybrid setup, and managed provider options with common self-hosted categories and infrastructure considerations.](https://raff-images.s3.raffusercloud.com/Self_hosting_infographic_guide_for_2026_81f90893aa.png) Use these five questions before moving a tool away from SaaS. ### 1. Is the workload strategically worth owning? Strong candidates often involve: - internal automation - monitoring - documentation - analytics - dashboards - developer tooling - lightweight workflow systems - controlled file or data services Poor first candidates often include email delivery, payroll, payment processing, legal systems, or compliance-heavy services where specialized providers remove substantial operational risk. ### 2. Can the team operate it? Confirm that someone can: - deploy and update the application - understand its database and storage model - secure public and administrative access - monitor failures - restore data - document the setup ### 3. Is the data recoverable? Know which files, databases, volumes, secrets, and configuration must be protected. A VM snapshot alone may not be enough for an application database or multi-service stack. ### 4. Is the workload portable? Confirm how the service would move to another server or provider. Test export and restore before the application becomes difficult to replace. ### 5. Is the benefit greater than the burden? Choose self-hosting only when control, integration, privacy, or cost structure clearly justifies the operating work. ## SaaS, self-hosted, managed, or hybrid? | Model | Best when | Main trade-off | |---|---|---| | SaaS | The workflow is standard and operations should stay with the vendor | Less control and possible per-user pricing | | Self-hosted VM | The team wants application and infrastructure control | Team owns operation and recovery | | Managed service | The team wants control over usage without operating the full service | Higher direct price for reduced responsibility | | Home or office server | Local access, learning, or hardware-connected workloads matter most | Power, internet, hardware, and remote-access risk | | Hybrid | Different workloads have clear reasons to stay local or in cloud | More networking and operational complexity | Most small teams should use a mixed model. Keep commodity, high-maintenance systems in SaaS or managed services. Self-host the applications where ownership creates a measurable advantage. ## Cloud VM vs home or office server ### Cloud VM A cloud VM is usually the practical default for internet-facing or remotely accessed services because it provides data-center networking, remote administration, public and private network options, and a predictable resource model without local hardware maintenance. It fits: - internal web applications - automation platforms - monitoring tools - dashboards - small APIs - documentation systems - containerized services ### Home or office server Local hardware can fit media storage, labs, local-only systems, and hardware-connected workflows. Operational risks include: - local power failure - internet outage - hardware replacement - router and firewall configuration - physical security - remote access - off-site backups Business-critical remote services should not depend on office infrastructure unless the team has deliberately designed for those risks. ### Hybrid model Hybrid infrastructure is useful when each workload has a clear placement reason. For example, public services may run in the cloud while large local archives remain on office storage. Avoid hybrid architecture when it only duplicates systems without clear ownership, backup, or network boundaries. ## What server do you need for self-hosting? Most self-hosted applications are light. One small VM behind a single reverse proxy comfortably runs several typical services. | Setup | Suggested server | Typical workloads | |---|---|---| | First experiments | 2 vCPU / 2 GB RAM | One or two light apps and a reverse proxy | | Small stack | 2 vCPU / 4 GB RAM | 3 to 6 containers and a small database | | Media or heavier stack | 4 vCPU / 8 GB RAM | Media server, multiple databases, monitoring | Three sizing rules: start smaller than you think and resize when monitoring shows real pressure; put large media or archive data on object storage or a volume rather than the root disk; and if you stream media, bandwidth policy matters as much as CPU. Raff Linux VM plans cover this whole range; check the [pricing page](/pricing) for current plans. ## Start with one low-risk service A safe adoption path is gradual. ### Stage 1: prove the operating model Begin with a service that can be unavailable without stopping the business. Use it to learn: - deployment - DNS and TLS - firewall rules - administrator access - backups - monitoring - update and rollback procedures ### Stage 2: run in parallel Before replacing a SaaS product, operate the self-hosted version beside it. Confirm that users can work with it and that the team can update, back up, and restore it. ### Stage 3: document the stack Maintain: - service inventory - owner - domain and network path - data location - backup schedule - restore steps - update policy - admin accounts - exposed ports - dependencies - migration plan Self-hosting becomes dangerous when the stack exists only in one person's memory. ## Security responsibilities A self-hosted application is secure only when its complete path is maintained. Minimum controls include: - supported operating system and application versions - restricted administrative access - least-privilege users - strong authentication and MFA where supported - minimal public ports - TLS for public traffic - secrets stored outside source code - regular updates - monitoring and alerting - backups isolated from the production failure path Keep databases, caches, and internal admin interfaces private where possible. Expose only the public application edge that users or external integrations require. ## Backups and recovery Protect the data layer, not only the server. A recoverable self-hosted stack may need: - database-aware backups - files and object data - container volumes - application configuration - secrets and encryption keys - infrastructure notes - DNS and certificate information Define Recovery Point Objective and Recovery Time Objective based on business impact. Then test a restore into a separate environment. A backup job that has never been restored is an assumption, not a recovery plan. ## Containers simplify deployment but do not remove operations Docker and Docker Compose can make application deployment repeatable. They do not remove the need to operate the host, storage, network, and backup layers. A small stack may use: ```text Cloud VM ↓ Docker Compose ├── application ├── worker ├── database or external database └── reverse proxy ``` For persistent services, document volumes, database backups, image versions, update order, and rollback steps. Read [Docker vs Virtual Machines](/learn/guides/docker-vs-virtual-machines-when-to-use) for the infrastructure boundary decision. ## When managed services are the better answer A managed database, application platform, or other managed service can be the better choice when the workload is valuable but the team does not want to own patching, failover, backups, or platform maintenance. Choose managed infrastructure when: - the service is production-critical - operations expertise is limited - recovery requirements are strict - maintenance distracts from the product - the managed feature set covers the required controls Self-hosting is not successful when it turns the technical team into permanent support for commodity infrastructure. ## Common failure patterns ### Replacing too many tools at once Each service adds updates, credentials, storage, logs, and failure modes. Prove one service before expanding. ### No named owner A shared responsibility with no owner often becomes no responsibility. ### No restore test Persistent data without a tested recovery path is not production-ready. ### Public exposure by default Do not expose databases, container ports, dashboards, SSH, or admin panels without a specific need and access policy. ### Excessive customization Deep modifications can make upstream updates difficult. Customize only where the business receives meaningful value. ### Depending on one maintainer Document the system, store credentials safely, and ensure another person can recover it. ## How this applies on Raff Raff Cloud Servers provide Linux VM infrastructure for self-hosted applications with root access, NVMe storage, unmetered server bandwidth, private networking, monitoring, and data-protection options. Current plans and included features should be verified on the live [pricing page](/pricing) and [Cloud Server page](/products/raff-vm). A practical Raff pattern is: - one Linux VM for the application or Docker Compose stack - private networking for internal service paths - firewall rules exposing only required ports - object storage or volumes where the data model requires them - snapshots before risky changes - scheduled backups and restore testing Do not choose a plan from a historical starting price or a fixed container count. Size the VM from the application's measured CPU, memory, storage, and network behavior. ## Self-hosting checklist Before launch, confirm: - The tool solves a real business or technical problem - A named person owns operation - The deployment process is documented - Public and administrative access are separated - Persistent data is identified - Backups cover databases, files, configuration, and secrets - Restore has been tested - Monitoring detects service and host failures - Updates and rollback have a schedule - The workload can be moved later - Total operating cost remains justified :::cluster ## Conclusion Self-hosting is valuable when ownership creates more benefit than operational burden. Use SaaS where it removes commodity work. Use managed services where a production workload matters but full operation does not. Self-host applications where data control, integration, portability, or cost structure clearly justifies responsibility. Start with one low-risk service, document the stack, protect the data, and test recovery before expanding. :::cta Explore Raff VM Deploy a controllable Linux VM foundation for your self-hosted application stack. ::: ## Sources - [Raff Cloud Servers](/products/raff-vm) - [Raff Pricing](/pricing) - [Raff Data Protection](/products/data-protection) - [Docker Documentation](https://docs.docker.com/) --- ### Block Storage vs Local Disk: How to Choose URL: https://rafftechnologies.com/learn/guides/block-storage-vs-local-disk Description: Learn how block storage vs local disk differs in lifecycle, performance, persistence, backups, database fit, and recovery planning for cloud workloads. Block storage and local disk both appear to applications as writable storage, but they have different lifecycles. **Local disk is coupled to the VM and is best for the operating system, caches, temporary files, and data that can be recreated. Block storage is a separate persistent volume and is usually better when data must grow independently, remain separate from the boot disk, or move through a controlled recovery and replacement process.** At Raff Technologies, our storage decision rule is simple: **if replacing the VM should not replace the data, separate that data from the boot disk.** This is a lifecycle decision, not a blanket performance claim. In this guide, “local disk” means storage operationally coupled to one VM; it does not describe Raff’s underlying physical storage implementation. The decision should begin with data lifecycle rather than headline performance. For the broader model that also covers object storage, backups, and restore testing, read [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps). ## Block storage vs local disk: quick answer Choose **local disk** when simplicity and VM-local performance matter and the data is disposable or easily rebuilt. Choose **block storage** when data is persistent, capacity may grow separately from compute, or the operating-system disk should remain replaceable. Choose **object storage** instead when applications need shared access to files through an API rather than a mounted filesystem. | Decision factor | Local disk | Block storage | |---|---|---| | Resource lifecycle | Coupled to the VM | Separate volume resource | | Best fit | OS, cache, scratch, build artifacts | Databases, application data, persistent filesystems | | Capacity growth | Often tied to VM or boot-disk options | Can usually be managed separately | | Replacement planning | Requires copying or restoring data | Data volume can be managed separately from compute | | Latency profile | Often lowest VM-local latency | Depends on the platform storage path | | Multi-server sharing | Usually not appropriate | Usually attached to one VM at a time unless documented otherwise | | Backup requirement | Required for important data | Still required for important data | A useful rule is: > If rebuilding the VM should not rebuild or destroy the data, separate that data from the boot disk. ## Start by classifying the data Before selecting storage, place each data set into one of four categories. ### Re-creatable data Examples include downloaded packages, generated thumbnails, temporary exports, build artifacts, and caches. Losing this data creates work, but not permanent business loss. Local disk is often appropriate. ### Durable application data Examples include database files, customer records, uploaded documents, and application state. This data needs a documented backup, recovery, and growth plan. A separate block volume may make that plan easier. ### Shared files Examples include user uploads served by several application nodes. A block device mounted to one VM does not automatically become shared storage. Object storage is often a better fit when multiple instances need access to the same files. ### Recovery data Backups and exports should not depend exclusively on the server they are intended to recover. Use a separate recovery destination and retention policy. ## What local disk is good at Local disk is the default storage associated with the VM. It is straightforward because the operating system, application, and filesystem use one familiar disk path. Good uses include: - operating-system files - application binaries - package and container caches - temporary processing space - build workspaces - transient logs - data that can be reconstructed from another source Its main advantage is operational simplicity. No additional volume must be attached, formatted, mounted, or monitored separately. Local disk is not inherently unsafe. It becomes risky when important data is stored there without a recovery plan or without understanding how VM deletion, replacement, resizing, or image changes affect it. ## What block storage is good at Block storage presents a separate disk-like device to the operating system. The team normally formats it, mounts it, chooses a filesystem, and decides where application data will live. Good uses include: - database data directories - persistent application state - large application filesystems - growing log or archive volumes - workloads whose storage grows faster than CPU or RAM needs - separating durable data from the operating-system disk The main architectural benefit is separation of concerns. Compute can be treated as replaceable while the persistent volume has its own lifecycle and protection policy. That separation does not make the volume automatically portable, replicated, or highly available. Confirm the platform’s attachment, detachment, region, snapshot, and recovery behavior before designing around it. ## Block storage is not shared storage by default A common mistake is assuming one block volume can be mounted read-write by several application servers safely. Most ordinary filesystems expect a single host to control the block device. Attaching the same volume to multiple writers without a cluster-aware filesystem and explicit platform support can corrupt data. For horizontally scaled applications: - keep application nodes stateless - place durable records in a database - use object storage for shared uploads and assets - use a documented shared-filesystem service only when the workload requires filesystem semantics Read [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) for the broader architecture. ## Performance depends on more than storage type “Local is faster” and “block is safer” are useful starting assumptions, not universal guarantees. Actual performance depends on: - IOPS and throughput limits - queue depth - request size and access pattern - filesystem and mount options - database synchronization behavior - VM and storage contention - latency between compute and storage - caching A database that performs many small synchronous writes has different needs from a media archive or backup target. Benchmark representative operations rather than copying a single sequential throughput number. Monitor latency percentiles, IOPS, throughput, and queueing under real workload conditions. ## Databases need a complete storage plan A database data directory may fit well on block storage when the platform provides suitable performance and recovery behavior. Before choosing the design, verify: - expected dataset and index growth - write and read patterns - required IOPS and latency - filesystem support - database consistency during snapshots - backup and point-in-time recovery method - replacement and restore steps - available disk space for maintenance operations A volume snapshot may be crash-consistent rather than application-consistent. For important databases, use database-aware backups and test recovery instead of relying only on storage snapshots. ## Block storage does not replace backups A persistent volume protects against some compute-lifecycle events. It does not protect against: - accidental file deletion - application corruption - destructive database migrations - ransomware - compromised administrator credentials - deletion of the volume itself - an invalid snapshot taken after corruption Use independent recovery points with retention and access controls. Read [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies) before treating persistence as recoverability. ## Mounting and filesystem operations add responsibility A separate volume requires operating-system work. The team must manage: - partitioning where required - filesystem creation - stable device identification - mount points and `/etc/fstab` - ownership and permissions - monitoring - filesystem checks - safe detachment - backup and restore procedures Use stable identifiers such as filesystem UUIDs where appropriate instead of assuming a device name will never change. Test a reboot before placing production data on the mount. A volume that is attached but not mounted correctly can cause an application to write into an empty directory on the boot disk, creating confusing split data. ## Capacity planning Do not size storage only for today’s dataset. Include: - database and index growth - temporary migration space - log retention - uploaded files - container images - backup staging - filesystem overhead - maintenance operations Set warning thresholds before the filesystem is nearly full. Databases and applications may fail unpredictably when free space disappears. A practical policy is to alert on both percentage used and expected time to exhaustion. ## Local, block, and object storage together Many production systems use all three. ```text VM local disk ├─ operating system ├─ application code └─ cache and temporary files Block volume └─ persistent database or application filesystem Object storage └─ shared uploads, media, exports, and backups ``` This model keeps each data type on a storage layer that matches its access and recovery requirements. Use [Object Storage](/products/object-storage) when applications need S3-compatible API access and shared file availability rather than raw block-device semantics. ## Decision framework ### Choose local disk when - the data is disposable or re-creatable - the workload is simple and single-server - low VM-local latency matters - capacity fits comfortably within the VM design - replacement from automation and backups is understood ### Choose block storage when - data should be separate from the boot disk - storage must grow independently from compute - a database or application requires a mounted filesystem - the team can manage mounts, monitoring, and backups - the platform’s volume lifecycle fits the recovery plan ### Choose object storage when - several application nodes need the same files - files are accessed through an API - application assets, uploads, exports, or backups need independent scale - filesystem-level block access is unnecessary ## How this applies on Raff Raff provides [Volumes](/products/volumes) for persistent block storage and [Raff VM](/products/raff-vm) for compute. As of August 7, 2026, Raff Volumes are available from **10 GiB to 1 TB** and the live product price is **$0.08/GiB-month**. The product page is the source of truth for current pricing and limits. A practical design is: 1. Keep the operating system and disposable runtime data on the VM disk. 2. Place selected persistent filesystem data on a Raff Volume when block semantics are required. 3. Use [Object Storage](/products/object-storage) for shared application files and backup objects where appropriate. 4. Protect critical data through [Data Protection](/products/data-protection) and workload-aware backups. 5. Use the live [pricing page](/pricing) for current volume and protection costs rather than relying on historical article prices. The operational decision stays the same even when product limits change: if data must survive a VM replacement, give it a storage and recovery lifecycle that does not depend on the boot disk. ## Common mistakes ### Mixing all data into the boot disk This makes replacement, migration, and recovery harder. ### Treating a block volume as a backup Persistence preserves good changes and bad changes. Keep independent recovery points. ### Assuming multi-attach means safe shared writes Use explicit platform and filesystem support before allowing several hosts to write to one block device. ### Forgetting the mount after reboot Test persistent mounting and application startup before production use. ### Ignoring storage growth Monitor capacity, latency, IOPS, and time to exhaustion. ### Choosing storage only by headline speed Match the storage layer to durability, sharing, recovery, and operational requirements as well as performance. :::cluster ## Conclusion Local disk and block storage solve different lifecycle problems. Use local disk for the operating system, caches, temporary files, and data that can be recreated. Use block storage when a mounted persistent filesystem should exist separately from the VM. Use object storage when files need shared API-based access across applications or servers. The strongest design classifies data first, separates durable state deliberately, and combines persistence with tested backups. Continue with [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps) for the full recovery model, or [Block Storage Volumes for Databases, Containers, and App Data](/learn/guides/block-storage-volumes-databases-containers-app-data) for the volume-specific decision. :::cta Explore Volumes Add persistent block storage when your application data needs a lifecycle separate from the VM. ::: ## Sources - [Raff Volumes](/products/volumes) - [Raff Object Storage](/products/object-storage) - [Raff Data Protection](/products/data-protection) - Product facts verified: 2026-08-07 --- ### How Small Teams Use Raff API Keys for Automation URL: https://rafftechnologies.com/learn/guides/raff-api-keys-automation-small-teams Description: Learn how small teams use Raff API keys safely for infrastructure automation, CI/CD workflows, inventory checks, backups, and repeatable cloud operations. Raff API keys let small teams automate cloud infrastructure tasks such as creating virtual machines, managing projects, attaching storage, configuring networking, creating snapshots, scheduling backups, and integrating Raff into scripts, CI/CD pipelines, CLI workflows, or Terraform. The practical answer is simple: **Use Raff API keys when a task is repeated often enough that dashboard clicks become slow, inconsistent, or risky. Start with low-risk automation, scope keys carefully, and treat every API key like production access.** That framing matters because API keys are powerful. A dashboard is manual. An API key is programmable. A script can repeat the same action hundreds of times. That is useful when the script is correct. It is dangerous when the script is careless. For small teams, the goal is not to automate everything on day one. The goal is to automate the work that creates the most operational value with the least unnecessary risk. Good first targets include: * creating test VMs * creating staging environments * managing SSH keys * scheduling backups * creating snapshots before deployments * cleaning up temporary resources * provisioning repeatable demo environments * managing firewall rules * listing infrastructure inventory * integrating Raff into internal tools Raff API keys turn infrastructure into a programmable system. Used well, they help small teams move faster without building a large DevOps department. Used poorly, they can create security and cost risk. This guide explains how Raff API keys work, when small teams should use them, common automation patterns, security best practices, and how to build a safer automation workflow on Raff. ## Quick answer: when should a small team use API keys? Use API keys when a cloud operation needs to be repeatable, scriptable, consistent, or connected to another tool. | Situation | Should you automate? | Why | | --------------------------------------- | ---------------------- | ---------------------------------------- | | Creating a one-off VM manually | Not required | Dashboard is fine | | Creating the same staging VM every week | Yes | Repetition creates drift and wasted time | | Taking snapshots before deployments | Yes | Reduces human forgetfulness | | Scheduling backups | Yes | Recovery should not depend on memory | | Creating preview environments | Yes | Good fit for repeatable scripts | | Deleting temporary test servers | Yes | Prevents unnecessary cost | | Managing production firewall rules | Carefully | High impact; needs review and logging | | Rotating credentials | Yes | Security workflows should be repeatable | | Scaling production automatically | Carefully | Needs monitoring, limits, and rollback | | Giving a third-party tool full access | Avoid unless necessary | Use least privilege and scoped access | A useful rule: > Automate repeated work first. Automate risky production work only after the workflow is tested, scoped, logged, and reversible. Small teams should not treat API automation as an all-or-nothing decision. Start with simple workflows. Build trust. Then expand. ## What Raff API keys are A Raff API key is a credential that allows scripts, tools, or applications to authenticate with the Raff API. Instead of clicking through the dashboard, a script can send API requests to perform infrastructure actions. ![Raff API keys dashboard showing API key names, key prefixes, account roles, project access, expiration dates, last used status, and management actions.](https://raff-images.s3.raffusercloud.com/raff_api_keys_dashboard_list_ce2ea10506.png) Depending on permissions and project scope, API-driven workflows can interact with platform areas such as: * virtual machines * projects * networking * VPCs * public IPs * firewalls * volumes * snapshots * backups * backup schedules * SSH keys * team members * roles * permissions * API keys In practical terms, an API key lets your automation act on behalf of your account or project. That means it should be protected carefully. A good mental model: ```text Dashboard access = human control API key access = programmable control ``` If a human can make a mistake with the dashboard, a script can make the same mistake faster. That is why API keys should be scoped, stored securely, rotated, and monitored. ## API keys are infrastructure credentials An API key is not just a random token. It is an infrastructure credential. Depending on the role and scope assigned to it, an API key may be able to create resources, delete resources, modify networking, trigger backups, update projects, or change infrastructure state. That makes API key security part of infrastructure security. Treat API keys like: * SSH private keys * production database passwords * cloud provider credentials * deployment secrets * admin tokens Do not paste API keys into chat tools, tickets, public docs, screenshots, repository files, or local scripts that will be shared. A leaked key can lead to: * unauthorized infrastructure changes * accidental or malicious VM creation * unexpected billing * deletion or modification of resources * exposure of project metadata * weakened firewall posture * broken backup workflows * disruption of production systems The safest API key is one that has only the access it needs, is stored in a secrets manager or secure CI/CD variable, and can be revoked quickly if compromised. ## How Raff API authentication works at a high level Most authenticated Raff API requests use an API key header. A typical request pattern looks like this: ```bash curl -X GET "https://api.rafftechnologies.com/api/v1/vms" \ -H "X-API-Key: $RAFF_API_KEY" ``` For project-scoped mutating operations, include a project identifier: ```bash curl -X POST "https://api.rafftechnologies.com/api/v1/vms" \ -H "X-API-Key: $RAFF_API_KEY" \ -H "X-Project-ID: $RAFF_PROJECT_ID" \ -H "Content-Type: application/json" \ -d '{ "name": "staging-api-01", "pricing_id": "replace_with_plan_id", "template_id": "replace_with_template_id", "region": "replace_with_region" }' ``` Keep examples like this as patterns, not permanent copy-paste commands. ![Raff API key automation flow showing a developer, script, or CI/CD system using a secure API key to access the Raff API and manage project-scoped cloud resources.](https://raff-images.s3.raffusercloud.com/raff_api_key_automation_flow_png_dcbfa7329f.png) Before implementing production automation, always check the current Raff API reference for the exact endpoint, required fields, response shape, and resource limits. The safest pattern is: ```text API key ↓ Project scope ↓ Role / permissions ↓ Specific automation task ``` Do not use one all-powerful key for every script. ## Why API automation matters for small teams Small teams usually have limited time. The same people may handle product development, deployments, support, bug fixes, security, customer onboarding, documentation, and infrastructure. Manual infrastructure work becomes a problem when it is: * repeated often * easy to forget * sensitive to small mistakes * required during deployments * needed outside working hours * dependent on one person * difficult to reproduce * undocumented * connected to production reliability Automation helps by turning repeated infrastructure actions into documented workflows. Instead of remembering every step, the team can run a script, CI/CD job, CLI command, or Terraform workflow. This reduces: * configuration drift * forgotten backup steps * inconsistent staging environments * manual cleanup work * repetitive VM provisioning * deployment mistakes * undocumented operational knowledge For small teams, automation is not about enterprise complexity. It is about making simple operations repeatable. ## What to automate first The best first automations are useful, low-risk, and easy to verify. Start with workflows where mistakes are easy to detect and recover from. ### 1. Infrastructure inventory A simple script that lists VMs, volumes, snapshots, backups, and public IPs can immediately help operations. Example use cases: * weekly infrastructure report * unused resource review * cost cleanup * stale VM detection * public IP inventory * backup coverage check This is a safe first step because it reads state without changing anything. ### 2. Temporary environment cleanup Small teams often create test servers and forget them. A cleanup script can list temporary VMs by tag, project, or naming convention and delete only resources that match a strict rule. Example: ```text Delete VMs tagged temporary=true Only if older than 48 hours Only in non-production project Require confirmation before deletion ``` This saves cost without touching production. ### 3. Snapshot before deployment Before a major deployment, an automation can create a snapshot of the relevant VM or volume. This gives the team a nearby rollback point. Example workflow: ```text CI/CD pipeline starts ↓ Create snapshot ↓ Wait for snapshot status ↓ Deploy application ↓ Run health check ↓ Notify team ``` This is one of the most valuable early automations because humans often forget pre-deployment safety steps. ### 4. Backup schedule checks Backups should not depend on memory. A small script can verify that production VMs have backup schedules and alert if a required schedule is missing. Example: ```text List production VMs ↓ Check backup schedule exists ↓ Report missing backup coverage ↓ Notify responsible owner ``` This is better than discovering missing backups during an incident. ### 5. Staging VM provisioning If staging environments are frequently recreated, automate them. A script can create a VM from a known template, attach SSH keys, configure networking, and run a bootstrap script. This helps every environment start from a known baseline. ## Common Raff API automation use cases ### VM provisioning API keys can help create repeatable VM provisioning workflows. A provisioning workflow may: * create a project * select a region * select a pricing plan * select an OS template * attach SSH keys * create a VM * add tags * attach firewall rules * connect the VM to a VPC * run a bootstrap script after SSH becomes available This is useful for: * staging environments * demo servers * test environments * preview apps * CI/CD runners * training environments * customer-specific deployments Manual VM creation is fine once. Automation is better when the same pattern repeats. ### Deployment automation API keys can support deployment workflows around your VM lifecycle. For example: ```text Developer merges to main ↓ CI/CD pipeline runs tests ↓ Snapshot is created ↓ App server is updated ↓ Service restarts ↓ Health check runs ↓ Team receives deployment result ``` The API key does not replace your deployment system. It connects Raff infrastructure actions into the deployment system. Good deployment automation should include: * pre-deployment snapshot * health checks * rollback plan * logs * notifications * production approval where needed Do not automate risky production deployments without visibility. ### Backup and snapshot workflows API automation is useful for backup and snapshot discipline. Examples: * create snapshot before OS update * create backup before migration * verify backup schedules exist * report failed or missing backups * list restore points for critical VMs * clean up old manual snapshots * trigger backup before high-risk changes A practical backup automation should not only create backups. It should also check that recovery points exist and can be found quickly. A better workflow: ```text Create backup ↓ Wait for completion ↓ Verify backup status ↓ Record backup ID ↓ Notify team ``` Creating a backup is not enough if nobody checks whether it completed. ### Networking and firewall automation Networking automation should be handled carefully because mistakes can lock teams out or expose services. Useful workflows include: * create firewall rules from templates * attach firewall to a VM network interface * keep database ports private * open temporary admin access * remove temporary admin access after a window * audit public-facing rules * create VPCs for internal services * attach VMs to private networks High-risk networking automation should include guardrails: * never modify production firewall rules without review * preserve known admin access * log every change * use dry-run mode where possible * validate rule sets before applying * avoid broad public exposure A firewall automation script should be more conservative than a human operator. ### Ephemeral testing environments Ephemeral environments are temporary environments created for a specific task and destroyed afterward. They are useful for: * pull request previews * QA testing * client demos * isolated bug reproduction * release validation * performance experiments * training sessions A typical flow: ```text Pull request opened ↓ Create temporary VM ↓ Deploy branch ↓ Run tests or allow review ↓ Destroy VM when done ``` The key detail is cleanup. Every ephemeral environment should have: * owner * expiration time * tag * project scope * cleanup workflow Otherwise, temporary infrastructure becomes permanent cost. ### Internal tools and dashboards Small teams can also use API keys to build internal infrastructure dashboards. Examples: * list all active VMs * show production backup status * display monthly resource inventory * show unattached volumes * report snapshots by age * show public IP usage * alert on untagged resources * show which project owns which resources This helps non-specialists understand infrastructure without needing full dashboard access. ## API key security best practices API key automation should be secure by design. ### Use project-scoped keys where possible Do not give one key broad account access if the automation only needs one project. A staging cleanup script should not have production access. ![Raff create API key modal showing the name field, account role selection, project access, expiration setting, and create key button.](https://raff-images.s3.raffusercloud.com/raff_create_api_key_modal_442e96ee6b.png) A backup verification script should not be able to delete VMs unless it genuinely needs that permission. Scope should follow purpose. ### Use least privilege Give each key only the permissions needed for the task. Examples: | Automation task | Safer key scope | | ----------------------------- | ----------------------------------------------- | | List infrastructure inventory | Read-only access where possible | | Create staging VMs | Staging project only | | Trigger backups | Backup-related permissions only | | Manage production firewall | Restricted role, approval workflow | | Cleanup temporary VMs | Non-production project only | | CI/CD deployment | Specific project and deployment-related actions | Avoid using owner-level keys in routine automation. ### Store keys in secure places Safe storage options include: * CI/CD secret variables * secrets manager * encrypted environment variables * secure deployment platform variables * password manager for manual use * local `.env` files excluded from Git for development Unsafe storage includes: * Git repositories * public issue trackers * chat messages * screenshots * shared documents * hardcoded scripts * plain text files on shared machines Always add `.env` to `.gitignore`: ```text .env .env.local *.secret ``` ### Rotate keys regularly API keys should be rotated on a planned schedule and immediately after suspected exposure. A rotation workflow: ```text Create or regenerate key ↓ Update CI/CD secret ↓ Run test workflow ↓ Disable old key ↓ Monitor for failed jobs ↓ Revoke old key ``` Do not rotate blindly without confirming the new key works. ### Use separate keys for separate workflows Avoid one key for everything. Better pattern: ```text raff-ci-deploy-prod raff-staging-cleanup raff-backup-checker raff-inventory-readonly raff-terraform-prod ``` This makes it easier to revoke one workflow without breaking everything else. It also makes audit trails easier to understand. ### Never log full API keys Scripts should avoid printing secrets. Bad: ```bash echo "Using key: $RAFF_API_KEY" ``` Better: ```bash echo "Using Raff API key from environment" ``` If you need to identify a key, use its name or prefix, not the full secret. ### Revoke unused keys Unused keys are security debt. Review API keys regularly and revoke keys that belong to: * old scripts * former team members * abandoned CI/CD jobs * temporary projects * one-off migrations * test automations * retired tools A good rule: > If nobody owns the key, revoke it. ## A simple automation maturity path Small teams should grow automation in stages. ### Stage 1: Manual dashboard operations This is fine early. Use the dashboard when tasks are rare, simple, and not production-critical. ### Stage 2: Read-only scripts Start with inventory and reporting. Examples: * list VMs * list backups * list snapshots * list public IPs * report resources by project This builds confidence without changing infrastructure. ### Stage 3: Safe write automation Move to controlled actions in non-production. Examples: * create staging VM * create snapshot * trigger backup * attach SSH key * create temporary environment ### Stage 4: CI/CD integration Connect Raff actions to deployment pipelines. Examples: * snapshot before deployment * deploy to staging * create preview environments * cleanup after tests * notify team ### Stage 5: Infrastructure as code Use Terraform or repeatable configuration workflows for more complex environments. This is useful when infrastructure state needs review, versioning, and reproducibility. ### Stage 6: Production automation with guardrails Automate production only when the workflow has: * least-privilege key * project scope * logs * monitoring * dry-run mode where possible * manual approval for risky actions * rollback path * clear owner Automation should improve reliability, not hide risk. ## Example: safe staging environment workflow A safer staging environment workflow might look like this: ```text Developer requests staging environment ↓ Automation checks project scope ↓ Automation creates VM from approved template ↓ SSH key is attached ↓ Firewall template is applied ↓ VM is tagged owner=team-name and expires_at=date ↓ Application bootstrap script runs ↓ Health check confirms readiness ↓ URL is shared with the team ↓ Cleanup job deletes environment after expiration ``` This workflow solves several problems: * staging is repeatable * access is controlled * firewall rules are consistent * cost is controlled through expiration * cleanup is automatic * ownership is visible The important detail is not just creation. It is lifecycle. Every automated resource should have an owner, purpose, and cleanup rule. ## Example: pre-deployment snapshot workflow For production deployments, the safest first automation is often a snapshot. A workflow: ```text CI/CD deployment starts ↓ Create VM or volume snapshot ↓ Wait for snapshot operation to complete ↓ Store snapshot ID in deployment logs ↓ Deploy application update ↓ Run health checks ↓ If healthy: mark deployment successful ↓ If unhealthy: alert team and use rollback plan ``` This gives your team a recovery point before risky changes. The script should not delete the snapshot immediately. Keep it long enough to validate the deployment. After the release is stable, old snapshots can be cleaned up according to a retention rule. ## Example: API key rotation workflow Key rotation should be predictable. A simple process: ```text Identify key owner and workflow ↓ Create or regenerate key ↓ Update secret in CI/CD or tool ↓ Run safe test action ↓ Confirm production workflow still works ↓ Disable or revoke old key ↓ Record rotation date ``` Do not wait for a leak to learn how key rotation works. Practice it as part of normal operations. ## Common mistakes to avoid ### Using one admin key for every script This is the most common mistake. If every automation shares one powerful key, one leak can affect everything. Use separate scoped keys. ### Committing keys to Git Never commit API keys to repositories. Even private repositories are not a safe place for secrets. ### Automating deletion too early Delete operations should be treated carefully. Start with list and report workflows. Then add deletion only with strict filters, confirmations, and project scope. ### Forgetting project scope A script intended for staging should not be able to affect production. Use projects and scoped keys to create boundaries. ### Skipping dry-run mode For cleanup, firewall, and deletion workflows, dry-run mode is valuable. A dry run shows what would happen without making changes. ### Not logging automation actions Automation should leave a trail. At minimum, log: * workflow name * key name or prefix * project * resource IDs * action taken * timestamp * result * error message if failed ### Ignoring rate limits and errors Automation should handle errors gracefully. Plan for: * `401` invalid key * `403` insufficient permission * `404` missing resource * `409` resource conflict * `429` rate limit * `5xx` temporary server-side error Do not assume every request succeeds. ### Treating API automation as a replacement for backups Automation can trigger backups or snapshots. It does not replace recovery planning. Backups still need retention, monitoring, and restore testing. ## Best practices for production automation Use these rules before allowing automation to touch production. ### Use named keys A key named `API key 1` is not helpful. Use names that explain purpose: ```text prod-deploy-ci prod-backup-checker staging-preview-cleanup terraform-production inventory-readonly ``` ### Require ownership Every key should have an owner. The owner is responsible for: * purpose * permissions * rotation * tool usage * removal when no longer needed ### Separate production and staging Use separate projects and separate keys. Do not reuse staging automation credentials in production. ### Use approvals for risky actions Actions such as deleting VMs, changing production firewall rules, or resizing production infrastructure should have manual review unless the workflow is mature and heavily guarded. ### Build rollback into the workflow Automation should not only move forward. It should know what to do if something fails. ### Monitor automation failures A failed automation job can silently create operational risk. Alert when: * backups fail * cleanup fails * deployment automation fails * key rotation breaks a workflow * permissions are denied unexpectedly * rate limits are hit repeatedly ### Review keys regularly Add API key review to your operations rhythm. For example: ```text Monthly: - List active API keys - Confirm owner - Confirm purpose - Check last rotation - Revoke unused keys - Review permissions ``` This keeps automation from becoming invisible risk. ## How this applies on Raff Raff is designed to support small teams that want cloud infrastructure without unnecessary operational complexity. The API fits that model because it allows teams to move from manual dashboard work to repeatable infrastructure workflows. Useful Raff automation paths include: * API scripts for simple tasks * Raff CLI for command-line workflows * Terraform provider for infrastructure as code * project-scoped automation * role-based access * backup and snapshot workflows * VM provisioning workflows * firewall and VPC automation * infrastructure inventory scripts A practical Raff automation architecture: ```text Developer or CI/CD system ↓ Secure API key ↓ Raff API ↓ Project-scoped infrastructure ↓ VMs, VPCs, firewalls, volumes, backups, snapshots ``` This gives a small team a controlled path from idea to repeatable infrastructure. A founder-led team might start with dashboard operations. A growing engineering team might add scripts. A production team might move critical infrastructure into Terraform and CI/CD. All three are valid stages. The goal is not to become more complex. The goal is to make the team’s most repeated infrastructure tasks safer and faster. ## Recommended Raff API key model for small teams A simple small-team model: | Key name | Scope | Purpose | | ---------------------- | ------------------------------ | ------------------------------------------ | | `inventory-readonly` | Account or project read access | Reporting and resource inventory | | `staging-ci-deploy` | Staging project | Create/update staging resources | | `preview-env-cleanup` | Non-production project | Delete expired temporary environments | | `prod-backup-checker` | Production project | Verify backups and snapshots | | `terraform-prod` | Production project | Infrastructure as code, tightly controlled | | `prod-deploy-snapshot` | Production project | Create pre-deployment snapshots | This is much safer than one key named: ```text main-admin-key ``` Small teams do not need enterprise bureaucracy. They need simple boundaries. ## Production API automation checklist Before using Raff API keys in production, review this checklist: * Does the key have a clear name? * Does the key have an owner? * Is the key scoped to the correct project? * Does the key use least privilege? * Is the key stored in a secure secret store? * Is the key excluded from Git? * Is the workflow logged? * Does the workflow handle API errors? * Is there a dry-run mode for risky changes? * Is there a rollback plan? * Are destructive actions reviewed? * Are backups or snapshots used before risky changes? * Is key rotation documented? * Are unused keys revoked? * Are production and staging keys separated? * Is the workflow monitored? * Does the team know how to revoke the key quickly? If an API key can affect production but nobody owns it, do not use it. ## Conclusion Raff API keys help small teams move from manual cloud operations to repeatable infrastructure workflows. That is valuable because small teams do not have time to repeat the same dashboard steps forever. VM provisioning, staging environments, snapshots, backups, cleanup jobs, SSH keys, firewall rules, and infrastructure inventory can all become safer and faster when automated carefully. The important word is carefully. An API key is powerful infrastructure access. It should be scoped, stored securely, rotated, monitored, and owned by someone on the team. The best automation uses least privilege, project boundaries, dry-run modes, logging, recovery points, and clear rollback steps. Start small. Automate read-only reporting first. Then automate staging. Then automate backups and snapshots. Move production workflows into API automation only when the process is tested and controlled. On Raff Technologies, API keys, projects, roles, the CLI, Terraform provider, and the REST API give small teams a practical way to build reliable automation without building a large DevOps department. The goal is not automation for its own sake. The goal is fewer mistakes, faster delivery, safer infrastructure, and more time spent building the product. --- ### Block Storage Volume Setup for Linux VMs URL: https://rafftechnologies.com/learn/guides/block-storage-volume-setup-linux-vms Description: Learn how to safely set up block storage volumes on Linux VMs with disk checks, mount paths, fstab, permissions, backups, and restore planning. Block storage volume setup on a Linux VM means preparing an attached disk so it can safely hold persistent app data, database files, container state, or processing workspace. This guide explains the storage decisions teams should make before attaching a volume, how Linux identifies Raff attached volumes, how persistent mounts should be designed, and how backups and recovery fit into the storage model. Raff Technologies provides [Raff Volumes](/products/volumes) for Linux VM workloads that need persistent storage separate from the VM system disk. Raff Volumes currently cost **$0.08/GiB-month** and are designed for data that should grow independently from compute resources. On Raff Linux VMs, the operating system disk is typically `/dev/vda`. Attached volumes appear as additional virtio disks such as `/dev/vdb` or `/dev/vdc`. The most important safety rule is simple: **never format a disk until you have confirmed that it is the new attached volume, not the system disk.** ## Separate storage starts with the right workload decision A volume is not just extra space. It creates a storage boundary. Use an attached volume when data should live separately from the operating system, such as: - database files - Docker persistent data - application state - processing workspace - large working directories Use the VM disk for the operating system, installed packages, and application runtime. Use object storage for durable file objects such as uploads, media, exports, and archives. ## Linux identifies attached volumes differently from system disks Before formatting or mounting any disk, confirm the device identity. A common Raff VM layout looks like: ```text /dev/vda → operating system disk /dev/vdb → attached Raff Volume /dev/vdc → additional attached volume ``` Check available disks first: ```bash lsblk ``` Verify: - disk size matches the new volume - mount points are understood - the system disk is not selected accidentally Formatting the wrong device can destroy the operating system or existing data. ## A persistent volume needs a filesystem and mount path After confirming the correct device, create a filesystem suitable for the workload. For many Linux VM workloads, ext4 is a practical default. A clean storage layout should have: | Component | Purpose | |---|---| | Volume | Persistent application data | | Mount path | Predictable location for services | | Owner | Person or team responsible for the data | | Backup policy | Recovery expectation | | Monitoring | Capacity awareness | Example mount paths: ```text /data /var/lib/postgresql /var/lib/docker ``` The correct path depends on the application. A database directory, container storage path, and media workspace should not automatically share the same location. ## UUID-based mounts prevent boot problems Production Linux systems should avoid relying only on device names in `/etc/fstab`. Device names can change when disks are added or removed. UUID-based entries are more predictable. Check the filesystem UUID: ```bash blkid ``` Then create the persistent mount entry using the UUID. After updating `fstab`, test before rebooting: ```bash mount -a ``` A failed mount configuration can prevent a clean boot, so always validate changes before restarting production systems. ## Volumes are useful for databases and containers Databases often benefit from separate storage because their data grows independently from application code. A practical layout: ```text VM system disk ↓ OS + application runtime Attached Raff Volume ↓ Database files ``` Docker workloads also commonly use volumes when container data must survive rebuilds or image updates. ```text Docker container ↓ Persistent mounted volume ↓ Application state ``` A volume improves separation, but it does not replace database backups, restore testing, or application-level recovery planning. ## Object storage solves a different storage problem Not every growing dataset needs a block volume. Use object storage for: - user uploads - images - videos - reports - exports - backup archives Use block storage when software expects filesystem behavior. Use object storage when files should exist independently from a VM lifecycle. For the broader storage decision, read [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk). ## Production volumes need ownership and recovery planning A production volume should always have: - a documented purpose - a known owner - backup coverage - snapshot strategy - restore procedure - storage monitoring Raff Volumes work best when combined with [Raff Data Protection](/products/data-protection) and tested recovery procedures. A volume that has no owner eventually becomes forgotten infrastructure. ## Decision framework for Linux VM storage | Need | Recommended choice | |---|---| | Operating system and packages | VM disk | | Database files | Block storage volume or managed database | | Docker persistent state | Block storage volume | | User uploads | Object storage | | Long-term archives | Object storage | | Temporary processing files | VM disk or block storage depending on size | The simplest rule is: > Use VM disk for the server. Use volumes for persistent disk-like data. Use object storage for durable files. ## Conclusion Setting up a Linux VM volume is not only a formatting task. The important decisions are where data belongs, how it should survive changes, who owns it, and how it can be recovered. Raff Volumes give teams a separate persistent storage layer for databases, containers, and application data without forcing compute and storage growth to happen together. When combined with backups, snapshots, and tested restore procedures, separate storage boundaries make production systems easier to operate. Before adding a volume, define the data it will hold. Before formatting a disk, confirm the device. Before trusting production storage, test recovery. --- ### Cloud Snapshots vs Backups: When to Use Each URL: https://rafftechnologies.com/learn/guides/snapshots-vs-backups-cloud-server Description: Compare cloud snapshots and backups by rollback speed, retention, consistency, failure coverage, RPO, RTO, and restore testing. Snapshots and backups protect cloud workloads in different ways. **Use snapshots for fast rollback around a known change, and use backups for retained recovery from deletion, corruption, compromise, or infrastructure loss. Production systems usually need both.** A snapshot is a point-in-time capture of a VM or disk state. A backup is a recovery copy kept on a schedule and across a retention window. The difference is operational rollback versus durable recovery. ![Snapshot vs backup comparison diagram showing snapshots as fast rollback points before risky changes and backups as scheduled recovery copies for long-term data protection.](https://raff-images.s3.raffusercloud.com/snapshots_vs_backups_cloud_server_comparison_png_d9965888a9.png) ## Snapshot vs backup at a glance | Question | Snapshot | Backup | |---|---|---| | Main purpose | Fast rollback | Retained recovery | | Best timing | Before a risky change | On a recurring schedule | | Typical scope | VM, disk, or volume state | VM, files, database, or application data | | Retention | Usually short | Usually longer and policy-driven | | Application consistency | May be crash-consistent | Can be application-aware | | Best for old data recovery | Limited | Stronger | | Best for deployment rollback | Strong | Supporting role | | Should it be the only control? | No | No | A useful rule is: > Snapshot = return to a recent infrastructure state. Backup = recover a usable copy from history. ## What a cloud snapshot does A snapshot captures the state of a VM, disk, or volume at a specific moment. It is most useful before a controlled change such as: - an operating-system upgrade - a major application release - a database migration - a package or runtime update - a firewall or network change - a storage reconfiguration - a risky troubleshooting action If the change fails, the snapshot can provide a faster rollback path than rebuilding the server manually. Snapshots are operational checkpoints. They are strongest when the team knows exactly which change may need to be reversed and the rollback window is short. The concept is the same on every platform. Whether the snapshot comes from VMware, Proxmox, or a cloud provider's control panel, it is still a point-in-time state capture with the same strengths and limits. What differs between platforms is where the snapshot is stored and whether it leaves the failure domain of the source system, not the role it plays. ## Snapshot limitations Snapshots should not be treated as the complete backup strategy. ### They may share the same failure path A snapshot often remains inside the same cloud account, platform, or administrative boundary as the source VM. If the account is compromised or the snapshot is deleted through the same control plane, both production and recovery may be affected. ### They preserve bad state too A snapshot captures the system as it exists. If data was already deleted, corrupted, encrypted, or misconfigured, the snapshot may preserve the same problem. ### They may not be application-consistent A storage-level snapshot may capture a database while writes are in progress. The result may be crash-consistent rather than transaction-aware. Important databases should keep an engine-aware recovery method as well. ### They encourage weak retention habits Snapshots are often created before changes and then forgotten. Long-lived snapshot collections can become difficult to understand and may not provide the historical recovery points the business expects. ## What a backup does A backup is a copy designed for recovery across time. Backups can protect against: - accidental deletion - long-undetected corruption - ransomware - failed deployments - destroyed or unavailable VMs - storage loss - application mistakes - compromised administrator accounts - the need to restore an older version A backup strategy defines: - what is protected - how often copies are created - where copies are stored - how long they are retained - who can delete or restore them - which recovery point should be selected - how the restored service is validated The schedule alone is not enough. The copy must be usable. ## Backup types solve different recovery needs | Backup type | Best use | Main limitation | |---|---|---| | VM backup | Rebuild the complete server state | May not provide granular application recovery | | File backup | Restore selected files or directories | Does not recreate the whole workload | | Logical database backup | Portable or selective database restore | Can be slower for large databases | | Physical database backup | Faster full database recovery | Engine- and version-specific | | Transaction-log or WAL archive | Point-in-time database recovery | Requires complete retention and testing | | Object storage copy | Independent files, exports, and archives | Restore process must be documented | The right design depends on the workload, not on the name of the tool. ## The decision framework Use a snapshot when: - a specific change is about to happen - rollback speed matters - the safe window is short - the workload can be restored from infrastructure state - an independent backup already exists for serious data loss Use a backup when: - data changes continuously - deletion may be discovered late - historical recovery points matter - the VM or storage may be unavailable - ransomware or account compromise is in scope - recovery needs to outlive a deployment window Use both when: - the workload is production - a database or customer data is involved - downtime affects revenue or operations - deployments and updates occur regularly - the team needs both fast rollback and historical recovery ## RPO and RTO change the answer Recovery Point Objective (RPO) defines how much recent data the business can lose. Recovery Time Objective (RTO) defines how quickly the service must return. Snapshots can help reduce RTO after a recent infrastructure change because they may restore quickly. Backups can support a safer RPO by preserving older and repeated recovery points. Neither result is automatic. A fast snapshot may not contain the correct historical state. A frequent backup may still take too long to restore. Use [RPO vs RTO for Cloud Backups](/learn/guides/cloud-server-backup-rpo-rto-snapshots) to define the targets before choosing the schedule. ## Databases need special attention A VM snapshot or backup may protect the disk without understanding database transactions. Important databases may also require: - logical dumps - physical base backups - transaction-log or WAL archiving - point-in-time recovery - replication for availability Replication does not replace backup because it normally copies unwanted changes too. For PostgreSQL-specific protection, read [PostgreSQL Replication vs Backups vs Snapshots](/learn/guides/postgresql-replication-vs-backups-vs-snapshots). ## Retention is the main backup advantage Snapshots are often useful for a short safety window. Backups become more valuable when a problem is discovered days or weeks later. A retention policy may combine: - frequent recent backups - daily short-term recovery points - weekly medium-term copies - monthly longer-term copies where justified Retention should follow: - business and legal requirements - how quickly problems are detected - data change rate - storage cost - the number of historical states the team may need Do not advertise or assume a fixed retention range unless it is verified in the current product configuration. ## Restore testing matters for both A snapshot or backup is only useful when the team can restore it. A full test should confirm: 1. The correct recovery point can be located. 2. Required credentials and encryption keys are available. 3. Replacement infrastructure can be created. 4. Data restores without integrity errors. 5. The application starts. 6. DNS, certificates, secrets, and networking are restored. 7. Critical user workflows succeed. 8. Measured data loss meets RPO. 9. Measured recovery time meets RTO. Testing only a file download does not prove full-service recovery. ## Use snapshots and backups together ![Cloud server data protection strategy timeline showing snapshots before risky changes, automated backups, retention planning, restore testing, disaster recovery, and regular strategy review.](https://raff-images.s3.raffusercloud.com/cloud_server_data_protection_strategy_timeline_png_5fa48f2529.png) A practical production pattern is: ```text Before risky changes: Create a snapshot. On a schedule: Run backups with defined retention. For databases: Add engine-aware backups or point-in-time recovery. Regularly: Test full restoration and update the runbook. ``` The snapshot protects the deployment window. The backup protects the business history. ## Common mistakes ### Using snapshots as the only backup This leaves the workload dependent on one platform, account, and recent state. ### Keeping only one recent backup A single recovery point may already contain the deletion or corruption being investigated. ### Ignoring the database layer Disk recovery and database recovery are not always the same process. ### Never testing restores A successful job does not prove a usable recovery. ### Forgetting configuration and secrets Data alone may not recreate the application. ### Allowing one identity to delete everything Important recovery points should be separated from routine production permissions where practical. ## How this applies on Raff Raff [Data Protection](/products/data-protection) provides the current platform path for snapshots and scheduled protection. [Volumes](/products/volumes) can support compatible persistent block storage, while [Object Storage](/products/object-storage) can hold compatible files, exports, and independently managed backup objects. A practical Raff model is: - use snapshots before risky infrastructure or application changes - configure scheduled protection for production workloads - add database-aware backups where required - keep an independent copy when the business impact justifies it - test restores in an isolated environment Verify current schedules, retention, restore behavior, exclusions, and pricing in the live dashboard and product pages. ## Decision checklist Choose **snapshot** when the question is: > Can we quickly reverse this planned change? Choose **backup** when the question is: > Can we recover important data or the service after a larger or older failure? Choose **both** when the workload matters enough that fast rollback and retained recovery are separate requirements. :::cluster ## Conclusion Snapshots and backups are complementary. Use snapshots as short-lived rollback points around known changes. Use scheduled backups for retained recovery across deletion, corruption, compromise, and infrastructure loss. Add database-aware protection where storage-level recovery is insufficient, protect copies from the same failure path as production, and test the complete restoration process. :::cta Explore Data Protection Combine fast rollback points with scheduled recovery for your Raff workloads. ::: ## Sources - [NIST SP 800-34 Rev. 1: Contingency Planning Guide](https://csrc.nist.gov/pubs/sp/800/34/r1/final) - [Raff Data Protection](/products/data-protection) - [Raff Object Storage](/products/object-storage) --- ### When to Add a Volume Instead of Resizing a VM Disk URL: https://rafftechnologies.com/learn/guides/add-volume-vs-resize-vm-disk Description: Learn when to add a block storage volume instead of resizing a VM disk, and how to choose between VM disk, volumes, and object storage. # When to Add a Volume Instead of Resizing a VM Disk Adding a volume is usually better when a workload needs more persistent storage but does not need more CPU, RAM, or a larger system disk. That distinction matters because storage growth and compute growth do not always happen together. A database can grow while the application still has enough CPU. A Docker workload can need persistent data while the VM size remains appropriate. A processing workload can need workspace without requiring a larger server. Raff Technologies gives teams two practical paths: resize the VM when the whole server needs more capacity, or attach [Raff Volumes](/products/volumes) when data needs a separate lifecycle from compute. Raff Volumes currently cost **$0.08/GiB-month**, making it easier to compare storage growth against a larger VM plan. This guide explains when to add a block storage volume, when resizing the VM disk is enough, when object storage is better, and how to choose a cleaner production storage layout. If you are new to the storage model, read [Block Storage Volumes for Databases, Containers, and App Data](/learn/guides/block-storage-volumes-databases-containers-app-data) first. ## VM disk resizing and attached volumes solve different problems A VM disk resize increases the size of the main disk attached to the server. An attached volume adds a separate disk-like storage resource. ```text VM disk resize ↓ Larger system disk Attached volume ↓ Separate persistent data disk ``` The VM disk usually contains: - Operating system - System packages - Application runtime - Configuration files - Local logs - Temporary files An attached volume usually contains: - Database files - Container state - Application data - Processing workspace - Large working directories - Persistent service data The important question is not only: > Do I need more storage? The better question is: > Should this data share the same lifecycle as the operating system? If the answer is no, a separate volume is usually the cleaner boundary. ## The storage decision framework separates capacity from lifecycle Use this framework before changing the VM size. | Situation | Better choice | Reason | |---|---|---| | Root disk is full because of OS files or logs | Resize VM disk or clean up | The system disk is the problem | | Database data is growing | Add a volume or managed database | Data needs its own lifecycle | | Docker persistent data is growing | Add a volume | Container state should survive rebuilds | | User uploads are growing | Object storage | Files should not depend on one VM | | VM lacks CPU or RAM | Resize VM | Compute is the bottleneck | | Only storage needs to grow | Add a volume | Storage scales independently | | Long-term files need storage | Object storage | File objects should outlive compute | A simple rule: > Resize the VM when the server is too small. Add a volume when the data needs its own boundary. ## Resize the VM disk when the system disk is the problem Resizing is appropriate when the operating system disk itself has become too small. Common examples: - OS updates need more space - Application packages grew - Docker images consume the root filesystem - Logs filled the system disk - Temporary files consumed available space - The original VM disk size was too small Before resizing, check whether cleanup solves the issue: - remove unused images - rotate old logs - clean package caches - remove abandoned build artifacts - investigate unexpectedly large files A larger disk should solve a real capacity requirement, not hide uncontrolled growth. ## Add a volume when storage grows faster than compute Volumes are useful when disk requirements increase while CPU and RAM remain sufficient. Example: ```text Current VM 2 vCPU 4 GB RAM 80 GB disk Problem Database needs 200 GB more storage CPU and RAM Still sufficient ``` A larger VM would add compute capacity that the workload does not need. A volume solves the storage requirement directly. Add a volume when: - data should be separated from the OS; - storage grows independently from compute; - databases need dedicated storage; - containers need persistent state; - recovery boundaries should be clearer; - data may move separately from the VM later. At Raff’s current rate, a **100 GiB volume costs $8/month** before other infrastructure costs. :::cta Explore Volumes Use Raff Volumes when your workload needs persistent storage that can grow separately from the VM. ::: ## Databases often benefit from separate storage Databases are one of the clearest cases for using a separate volume. A database contains durable state: tables, indexes, transaction logs, temporary files, and metadata. Keeping that data separate from the operating system makes capacity planning and recovery easier. A common layout: ```text Raff VM ↓ System disk OS + application runtime Raff Volume Database data directory ``` A volume helps when: - database data grows quickly; - the team needs storage monitoring separately; - the database may move independently later; - risky changes need storage recovery points. A volume does not replace: - database-aware backups; - restore testing; - access control; - monitoring; - recovery planning. For teams that do not want to operate database storage directly, [Raff Managed Databases](/products/managed-databases) may be a better responsibility model. ## Containers need persistent storage outside rebuilds Containers are replaceable. Important data should not depend on a container filesystem. Use a volume when: - containers store application state; - Docker volumes are growing; - self-hosted services need persistent files; - rebuilds should not remove important data. Example: ```text Container ↓ Persistent mounted volume ↓ Application data ``` For user uploads, media, reports, and exports, object storage is usually a better fit. ## Object storage solves file storage problems A common mistake is increasing VM storage because uploaded files are growing. Object storage is usually better for: - user uploads; - images; - videos; - reports; - exports; - archives; - shared files across servers. Use block storage when software expects filesystem behavior. Use object storage when files should exist independently from a VM lifecycle. Read [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) for the broader comparison. ## Volumes create clearer recovery boundaries Separating data from the system disk makes recovery planning easier. ```text System disk ↓ Recover OS and runtime Volume ↓ Recover persistent application data Object storage ↓ Recover durable file objects ``` A volume can help define: - what data is protected; - what gets snapshotted; - what requires database backup; - who owns recovery; - what can be rebuilt. Use [Raff Data Protection](/products/data-protection) when snapshots, backups, retention, and recovery workflows are required. :::cta Explore Data Protection Protect VM and volume data with snapshots, backups, and recovery workflows. ::: ## A production volume needs ownership Every production volume should have: - a clear purpose; - a documented mount path; - an owner; - monitoring; - backup coverage; - recovery instructions; - deletion rules. A volume named `extra-disk-1` without context becomes forgotten infrastructure. ## When resizing is still the better choice Do not add a volume automatically. Resize the VM when: - CPU and RAM are also insufficient; - the system disk is the real problem; - the workload is simple; - fewer moving parts are more valuable; - data separation does not provide meaningful benefit. A small application may correctly stay on one disk until growth or recovery requirements justify a change. ## Decision checklist Before resizing or adding storage, ask: - Is compute also under pressure? - Is only storage growing? - Is the data durable? - Should it survive VM replacement? - Does it need filesystem access? - Would object storage fit better? - Does it need separate backup and recovery rules? - Is there a clear owner? If data needs its own lifecycle, add a volume. If the server itself is undersized, resize the VM. If the data is file-based, consider object storage. ## Conclusion Resize the VM when the whole server needs more capacity. Add a volume when persistent data needs a separate storage boundary. Use object storage when files should exist independently from compute. The right storage design separates runtime, persistent data, durable files, and recovery points. That makes production systems easier to operate and easier to recover. :::cta Explore Volumes Add Raff Volumes when your VM needs persistent storage that can grow separately from compute. ::: --- ### Cron Jobs vs Queues vs Workflow Automation: Choosing the Right Model URL: https://rafftechnologies.com/learn/guides/cron-jobs-queues-workflow-automation-background-work Description: Understand cron jobs, task queues, and workflow automation with a decision framework for background jobs, retries, scheduling, and orchestration # Cron Jobs vs Queues vs Workflow Automation: Choosing the Right Model A background work model is an architecture pattern that decides when, where, and how non-request work runs in an application. For developers building cloud applications, the real decision is not whether background work is useful. It is whether the work belongs on a clock, in a queue, or inside a workflow system. Raff Technologies gives small teams full root access, Docker-ready Linux VMs, fast deployment, and predictable infrastructure, which makes it practical to start with a simple model and evolve as the workload becomes more important. Raff’s Linux VM page lists deployment in 60 seconds, 9 Linux distributions, full root access, unmetered bandwidth, 99.9% uptime SLA, and plans from $4.99/month. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s automation and application architecture cluster. Raff already has guides on n8n, infrastructure automation, MCP vs n8n vs direct API integration, single-server architecture, and auto-scaling. This article focuses on a narrower but important decision: when a background task should be a cron job, a queue worker, a workflow automation, or a hybrid of all three. ## Background Work Is Not One Category Most applications eventually need work that does not fit neatly inside a user request. An order confirmation email should not delay checkout. A report export may take minutes. A daily cleanup job needs a schedule. A webhook retry may need backoff. A customer onboarding workflow may need to touch a database, CRM, billing system, and support notification. These examples are all “background work,” but they do not need the same execution model. The mistake is choosing a tool because it is familiar. Cron is familiar, so everything becomes a cron job. Queues are powerful, so every delayed task becomes a worker. Workflow automation is visual and flexible, so business processes get moved into a tool before the team understands operational risk. A better approach is to classify the work first: | Question | Why it matters | |---|---| | Is the work time-based or event-based? | Determines whether scheduling or triggering is primary | | Does the work need retries? | Determines whether failure handling must be built in | | Can the work run more than once safely? | Determines idempotency requirements | | Does the work touch external systems? | Determines visibility and orchestration needs | | Does the work affect customers directly? | Determines monitoring and ownership | | Does volume change over time? | Determines whether worker scaling matters | The right model is the one that matches the failure mode. ## The Background Work Decision Framework Use this framework to decide whether cron jobs, task queues, workflow automation, or a hybrid model fits the workload. | Workload pattern | Best model | Why it fits | Watch out for | |---|---|---|---| | Run a cleanup task every night | Cron job | Time-based, predictable, simple | No built-in retries or distributed coordination | | Send emails after user signup | Task queue | Event-driven, should not block request | Needs retry policy and dead-letter handling | | Process uploaded files | Task queue | CPU or I/O work can run outside request path | Worker capacity and storage behavior matter | | Sync data between SaaS tools | Workflow automation | Cross-system orchestration and visibility | Secrets, permissions, and failure visibility | | Approve infrastructure changes | Workflow automation | Human decision and notification flow | Not ideal for high-volume compute jobs | | Recalculate analytics hourly | Cron plus queue | Cron triggers batches; queue distributes work | Prevent duplicate batch execution | | Retry failed webhooks | Queue or workflow automation | Needs retry, backoff, and observability | Duplicate delivery must be safe | | Customer onboarding flow | Workflow automation plus app jobs | Mixes business steps and technical tasks | Keep core product logic in code | The central trade-off is simple: **cron answers when, queues answer how much work, and workflow automation answers who or what must be coordinated**. A small team can use all three without overengineering. The key is not to force every background task into one model. ## Cron Jobs Are Best for Predictable Time-Based Work Cron is the classic tool for scheduled server tasks. The Linux cron manual describes `crond` as a daemon that executes scheduled commands, and cron checks stored crontabs to decide whether a job needs to run in the current minute. [Linux cron manual](https://www.man7.org/linux/man-pages/man8/cron.8.html) That makes cron a strong fit for work with a predictable clock: - daily cleanup, - hourly cache refresh, - monthly report generation, - certificate renewal checks, - scheduled database maintenance, - log rotation, - periodic health checks. Cron is attractive because it is simple. It does not require a message broker, worker system, or orchestration platform. For a small app on one VM, that simplicity is often exactly right. But cron is not a full background processing system. It does not automatically distribute work across workers, track job state, retry failed tasks safely, or coordinate multiple machines without extra design. It can trigger work, but it should not always own the whole workflow. | Cron is a good fit when | Cron becomes risky when | |---|---| | The job is time-based | The job volume is unpredictable | | The task is short or predictable | The task can overlap with itself | | Failure is easy to detect | Retries require business rules | | One server owns the schedule | Multiple servers may run the same job | | The work does not need rich visibility | Stakeholders need status and audit history | Cron should feel boring. If a cron job starts needing complex state, retries, concurrency rules, or manual approvals, it may be trying to do the work of a queue or workflow system. ## Queues Are Best for Asynchronous Workload Control A task queue separates work from the request or event that created it. Instead of making a user wait for expensive work to finish, the application creates a task. A worker process later pulls that task and executes it. RabbitMQ’s work queue tutorial explains the core idea as avoiding immediate execution of resource-intensive work, scheduling it for later, and having background workers process tasks from the queue. [RabbitMQ Work Queues](https://www.rabbitmq.com/tutorials/tutorial-two-swift) Queues are strongest when the workload needs: - retries, - worker scaling, - request decoupling, - backpressure, - parallel processing, - delayed execution, - and failure tracking. Celery describes itself as a distributed system for processing messages and a task queue focused on real-time processing while also supporting scheduling. [Celery Documentation](https://docs.celeryq.dev/) That distinction matters: queues are not just for “background tasks.” They are for controlling work that may outgrow one process, one request, or one machine. | Queue is a good fit when | Queue becomes risky when | |---|---| | Work should not block a user request | The team cannot monitor workers | | Tasks need retries | Tasks are not safe to run twice | | Volume changes over time | Queue growth is ignored | | Workers can scale separately | The broker becomes a single point of failure | | Failure must be visible | Business owners need visual workflow control | Queues introduce operational responsibility. The team now needs to think about workers, broker availability, queue depth, retry policy, dead-letter handling, and duplicate execution. That extra responsibility is worthwhile when the workload needs it. It is unnecessary when the job is just “run this cleanup task every night.” ## Workflow Automation Is Best for Cross-System Coordination Workflow automation is not simply a prettier queue. A workflow automation tool coordinates actions across systems. It can receive a trigger, call APIs, transform data, branch based on conditions, notify people, wait for approval, and continue after another event occurs. n8n’s documentation describes n8n as a workflow automation tool that combines AI capabilities with business process automation. [n8n Documentation](https://docs.n8n.io/) Raff already has a dedicated n8n guide that explains n8n as a platform for connecting applications, APIs, databases, schedules, and webhooks into reusable workflows. That guide owns the self-hosted n8n decision. This guide uses n8n as one example inside a broader background work model. [n8n Self-Hosted Workflow Automation Guide](https://rafftechnologies.com/learn/guides/n8n-self-hosted-workflow-automation-guide) Workflow automation is strongest when the work is not only technical execution. It is coordination. | Workflow automation is a good fit when | It becomes risky when | |---|---| | The process crosses multiple systems | It hides core product logic outside the app | | Non-developers need visibility | It becomes a high-volume compute engine | | Approvals or notifications matter | Secrets and permissions are poorly managed | | The flow changes often | Version control and testing are weak | | APIs and webhooks drive the process | Failure handling is unclear | Good examples include customer onboarding, lead routing, invoice follow-ups, support escalations, internal approval flows, provisioning requests, and operational notifications. Poor examples include image processing at scale, high-volume email sending, long CPU-heavy jobs, or critical product logic that must be tested and deployed with the application. ## The Trigger Type Usually Decides the First Model The fastest way to choose a background work model is to identify the trigger. | Trigger type | Best starting model | Example | |---|---|---| | Clock-based | Cron | Run cleanup every night | | User action | Queue | Send signup email after registration | | External webhook | Queue or workflow automation | Process payment event | | Human approval | Workflow automation | Approve a VM provisioning request | | System threshold | Queue or workflow automation | Notify team when usage crosses limit | | Batch schedule | Cron plus queue | Start hourly analytics batch | | Cross-tool event | Workflow automation | Create CRM update after billing event | Time-based work usually starts with cron. Request-driven technical work usually starts with a queue. Cross-system business work usually starts with workflow automation. The trigger is not the only factor, but it prevents the most common mistake: using cron as a universal hammer. ## Failure Behavior Matters More Than Convenience The wrong background work model usually reveals itself during failure. A cron job fails silently and nobody notices. A queue retries a non-idempotent payment task and creates duplicate side effects. A visual workflow succeeds halfway, then leaves a CRM record updated but a billing action incomplete. Each model has a different failure shape. Before choosing a model, ask what should happen when the work fails. | Failure question | Why it matters | |---|---| | Can the task run twice safely? | Determines idempotency requirements | | Should the task retry automatically? | Determines queue or workflow retry design | | Is partial completion dangerous? | Determines compensation or rollback needs | | Who needs to know about failure? | Determines alerts and visibility | | How long can the work wait? | Determines urgency and worker capacity | | Is data consistency required? | Determines whether the logic belongs inside the app | A queue is powerful, but unsafe tasks can make retries dangerous. Workflow automation is visible, but partial cross-system success can create messy cleanup. Cron is simple, but quiet failures can become invisible operational debt. The best background model is not the one that succeeds cleanly. It is the one that fails in a way your team can detect, understand, and recover from. ## A Hybrid Model Is Often the Best Architecture Small teams sometimes frame this as a single choice: cron or queues or workflow automation. In production systems, the answer is often a hybrid. For example, an hourly analytics process might use cron to start the batch, a queue to distribute account-level calculations, and workflow automation to notify the team if the job falls behind. A customer onboarding process might use workflow automation for human-readable coordination, while the application sends technical tasks into a queue for reliable execution. Raff’s auto-scaling guide already treats queue depth as one of the useful scaling signals, alongside CPU, RAM, disk I/O, latency, and traffic patterns. [Auto-Scaling VM Planning](https://rafftechnologies.com/learn/guides/auto-scaling-vm-planning) That is a useful clue: once queue depth becomes important, background work is no longer just a code organization detail. It becomes part of infrastructure planning. | Hybrid pattern | Why it works | |---|---| | Cron triggers queue jobs | Keeps scheduling simple while distributing work | | Queue triggers workflow notification | Keeps technical execution separate from team visibility | | Workflow starts app task | Keeps business coordination visible while app owns core logic | | Cron checks stuck workflows | Adds operational safety to long-running processes | | Queue workers run on separate VM | Isolates background work from user-facing traffic | The hybrid rule is straightforward: **use cron for timing, queues for workload, and workflow automation for coordination**. ## Where Each Model Runs on Cloud Infrastructure Background work eventually becomes an infrastructure decision. On a single VM, cron, web app, database, cache, and workers may all run together. Raff’s single vs multi-server architecture guide describes this as a common starting point for MVPs, internal tools, staging environments, and moderate-traffic applications. [Single Server vs Multi-Server Architecture](https://rafftechnologies.com/learn/guides/single-server-vs-multi-server-architecture) As the application grows, background work may need its own process, container, VM, or scaling plan. | Infrastructure stage | Background work pattern | |---|---| | One small VM | Cron and lightweight workers run beside the app | | One larger VM | App, workers, and scheduler run as separate services | | App plus worker VM | User-facing traffic and background work are isolated | | App plus queue plus workers | Queue depth controls worker capacity | | Workflow automation VM | n8n or similar tool coordinates external processes | | Multi-server architecture | Schedulers, queues, workers, and app servers have separate roles | The transition should be driven by pressure, not fashion. If background work slows user requests, split it. If scheduled jobs compete with production traffic, isolate them. If queue depth grows faster than workers can process tasks, scale worker capacity. If workflows touch business systems and people need visibility, consider workflow automation. ## How This Applies on Raff Raff is a practical environment for all three models because it gives developers full server control without forcing one architecture. A small team can start with cron on a Linux VM, run background workers beside a web application, add Redis or another broker when task queues become necessary, or deploy a self-hosted workflow automation tool such as n8n when orchestration becomes the real problem. Raff’s Linux VM product page lists full root access, SSH key authentication, Docker-ready infrastructure, KVM virtualization, unmetered bandwidth, DDoS protection, cloud firewall, custom ISOs, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) A practical Raff evolution path looks like this: | Stage | Background work model | |---|---| | MVP or internal tool | Cron for simple schedules | | Growing web app | Queue for emails, webhooks, and file processing | | Operational workflow | n8n for approvals, notifications, and cross-tool actions | | Scaling workload | Separate workers onto their own VM | | Business-critical automation | Add backups, monitoring, network controls, and ownership | The design rationale is simple: Raff should let teams start small without trapping them in the first model they choose. A cron job can be enough for a small workload. A queue can protect the user experience as volume grows. Workflow automation can make operations visible when people, APIs, and approvals enter the process. Aybars’ practical angle for this guide is that background work should be designed around failure, not convenience. If the team knows what triggers the work, how it fails, who owns it, and how it scales, the tool choice becomes much easier. ## Common Background Work Mistakes **Using cron for everything.** Cron is excellent for schedules, but weak for retries, distributed work, and event-driven execution. **Adding a queue before defining failure behavior.** A queue can retry failed tasks, but retries are dangerous when tasks are not idempotent. **Moving product logic into workflow automation.** Workflow tools are useful for coordination. Core product behavior usually belongs in tested application code. **Ignoring queue depth.** A queue is not healthy just because workers are running. Queue depth, processing time, and failure rate matter. **Running heavy jobs beside user-facing traffic forever.** At some point, background workers should be isolated so they do not compete with the app. **Treating visual workflows as operationally free.** Workflow automation still needs secrets management, backups, access control, monitoring, and ownership. ## A Practical Policy for Choosing Background Work A small-team policy does not need to be complicated. It needs to stop the team from choosing tools by habit. | Decision area | Recommended baseline | |---|---| | Scheduled maintenance | Use cron when timing is the main requirement | | Request-driven work | Use a queue when work should not block the request | | External API coordination | Use workflow automation when visibility and branching matter | | High-volume processing | Use queues and separate workers | | Human approval | Use workflow automation | | Critical product logic | Keep it in application code | | Scaling signal | Watch queue depth, task duration, and worker failure rate | | Failure design | Define retries, ownership, alerts, and idempotency before production use | This policy keeps the model flexible. It allows cron, queues, and workflow automation to work together without confusing their responsibilities. ## The Right Model Keeps Background Work Boring Background work should make applications feel faster, safer, and easier to operate. It should not become a hidden system nobody understands. Use cron when the work belongs on a clock. Use queues when the work needs reliable asynchronous execution. Use workflow automation when the work crosses tools, teams, approvals, and business processes. Use a hybrid model when timing, workload, and coordination all matter. For deeper reading, this guide should link to Raff’s n8n self-hosting guide, n8n infrastructure automation guide, MCP vs n8n vs API integration guide, single vs multi-server architecture guide, and auto-scaling VM planning guide. Together, those articles help readers move from one-server simplicity to a background work architecture that can scale without unnecessary complexity. On Raff, the practical path is to start with the simplest model that fits the failure mode, then split background work into dedicated workers, queues, or workflow automation only when the workload proves it needs that structure. --- ### WebSocket Hosting Explained: Persistent Connections, Scaling, and Cost URL: https://rafftechnologies.com/learn/guides/websocket-hosting-persistent-connections-scaling-cost Description: Understand WebSocket hosting with a decision framework for persistent connections, scaling, latency, reverse proxies, reliability, and cloud server cost. WebSocket hosting is the practice of running applications that keep persistent, two-way connections open between clients and servers. For developers building real-time applications, WebSocket hosting changes the way infrastructure behaves. A normal HTTP request connects, receives a response, and ends. A WebSocket connection can stay open while the browser and server exchange messages whenever either side has something to send. Raff Technologies gives small teams full root access, Docker-ready Linux VMs, unmetered bandwidth, NVMe SSD storage, and fast deployment, which makes it practical to start with a simple WebSocket server and scale only when connection pressure becomes real. Raff’s Linux VM page lists deployment in under 60 seconds, 9 Linux distributions, full root access, unmetered bandwidth, and plans from $4.99/month. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s real-time application and infrastructure planning cluster. Raff already covers reverse proxies, load balancers, single-server vs multi-server architecture, auto-scaling, background work models, and performance bottlenecks. This guide focuses on the missing decision: when WebSockets are the right communication model, what makes WebSocket hosting different, and how persistent connections affect scaling and cost. ## WebSockets Change the Shape of Server Load The WebSocket API allows a browser and server to open a two-way interactive communication session, so the client can send messages and receive server responses without repeatedly polling for updates. [MDN WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) That sounds like a small technical detail, but it changes the hosting model. With normal HTTP, server load is mostly about request rate, response time, CPU, database work, and bandwidth. With WebSockets, you still care about those things, but you also care about how many clients stay connected at the same time. A WebSocket application can have low request volume but high connection count. For example, a live dashboard might have 5,000 users connected, even if each user receives only a few updates per minute. A chat app might have fewer users but more frequent messages. A multiplayer game might have lower payload size but stricter latency needs. | Hosting metric | Why it matters for WebSockets | |---|---| | Concurrent connections | Each connected client consumes server resources | | Message rate | Frequent messages increase CPU and network pressure | | Message size | Larger payloads increase bandwidth and memory pressure | | Connection duration | Long sessions make capacity planning different from HTTP | | Latency | Real-time apps feel broken when messages arrive late | | State handling | Multi-server WebSocket apps need shared session or message state | | Reconnection behavior | Many clients reconnecting at once can create traffic spikes | The main lesson: **WebSocket hosting is not only about serving requests; it is about managing live connections**. ## WebSockets Are Not Always the Right Real-Time Model WebSockets are powerful, but they are not the only way to deliver live updates. Some applications can use normal HTTP polling. Some can use long polling. Some only need Server-Sent Events. Some need WebSockets because both client and server must send messages at any time. The WebSocket protocol, defined in RFC 6455, provides full-duplex communication over a single TCP connection. Its relationship to HTTP is mainly the opening handshake, where an HTTP request upgrades into the WebSocket protocol. [RFC 6455](https://www.rfc-editor.org/rfc/rfc6455.html) That full-duplex behavior is useful, but it also adds operational responsibility. | Communication model | Best for | Watch out for | |---|---|---| | HTTP polling | Simple periodic checks | Wasteful at high frequency | | Long polling | Occasional updates with broad compatibility | More request overhead than WebSockets | | Server-Sent Events | Server-to-client updates like feeds or dashboards | One-way from server to browser | | WebSockets | Two-way real-time communication | Persistent connection scaling and state management | | WebRTC data channels | Peer-to-peer low-latency data | More complex networking and signaling | The decision should start with direction and frequency. If the server only needs to push updates to the browser, Server-Sent Events may be enough. If the client and server both need to send messages frequently, WebSockets are usually a better fit. If the update frequency is low, polling may be simpler and cheaper to operate. ## The WebSocket Hosting Decision Framework Use this framework to decide whether WebSocket hosting fits your application and how much infrastructure planning it needs. | Workload pattern | Best model | Why it fits | Hosting concern | |---|---|---|---| | Live dashboard with frequent updates | WebSockets or SSE | Users need fresh state without refreshing | Connection count and update fan-out | | Chat application | WebSockets | Both sides send messages in real time | Presence, message delivery, reconnection | | Multiplayer game | WebSockets or custom real-time protocol | Low-latency interaction matters | Latency, regional hosting, tick/update rate | | Notification bell | SSE or polling | Mostly server-to-client updates | Simpler than full WebSockets | | Stock, crypto, or metrics stream | WebSockets | Continuous updates and low latency | Message rate and bandwidth | | Collaborative editor | WebSockets | Multiple users need shared live state | State synchronization and conflict handling | | Background job status page | SSE, polling, or WebSockets | Depends on update frequency | Avoid overbuilding if updates are rare | | Webhook receiver | HTTP | External systems send discrete events | WebSockets are usually unnecessary | A practical rule: **use WebSockets when bidirectional, low-latency, persistent communication is central to the product experience**. If real-time behavior is only a small convenience, simpler models may be easier to host and maintain. ## Persistent Connections Change Capacity Planning A WebSocket server must keep many connections alive at the same time. That does not automatically mean WebSockets are expensive. An idle WebSocket connection may use very little CPU. But each connection still consumes memory, file descriptors, event loop capacity, and network tracking. When message volume rises, CPU and bandwidth can grow quickly. The hosting cost depends on five main variables: | Variable | Why it affects cost | |---|---| | Concurrent users | More open connections require more server capacity | | Messages per second | Higher message rate increases CPU and network usage | | Payload size | Larger messages increase bandwidth and memory pressure | | Fan-out pattern | One message sent to many clients multiplies work | | Connection lifetime | Long-lived sessions require stable process and network handling | Example: 1,000 connected users receiving one small update per minute is a very different workload from 1,000 connected users receiving 20 updates per second. The user count is the same. The cost is not. This is why WebSocket pricing and sizing should not be based only on “monthly visitors.” It should be based on active connections, message frequency, payload size, and uptime expectations. ## Reverse Proxies Need WebSocket Awareness Many WebSocket applications sit behind a reverse proxy such as Nginx, Caddy, Traefik, or another edge layer. That reverse proxy may handle TLS, host routing, path routing, request filtering, and forwarding traffic to the application process. Raff already has a guide explaining the difference between a reverse proxy and a load balancer, including TLS termination, request routing, and when each layer matters. [Reverse Proxy vs Load Balancer](https://rafftechnologies.com/learn/guides/reverse-proxy-vs-load-balancer) WebSockets need special attention because the connection starts as HTTP and then upgrades. Nginx’s WebSocket proxy documentation explains that WebSocket proxying uses the HTTP/1.1 protocol switch mechanism, and that the `Upgrade` header is hop-by-hop, so it must be handled correctly between proxy and upstream. [Nginx WebSocket Proxying](https://nginx.org/en/docs/http/websocket.html) For a decision-stage guide, the important point is not the exact configuration. It is that WebSocket hosting needs the edge layer to preserve the upgrade behavior and not treat the connection like a short HTTP request. | Proxy concern | Why it matters | |---|---| | HTTP upgrade support | WebSocket traffic must switch protocols correctly | | Timeouts | Idle connections may be closed too aggressively | | TLS termination | Secure WebSockets usually use `wss://` | | Path routing | WebSocket endpoints may need separate routing | | Connection limits | Edge limits can cap concurrency before the app does | | Load balancing | Multi-node WebSocket apps need connection-aware routing | A reverse proxy can be enough for a single WebSocket backend. A load balancer becomes more important when several backend servers need to share connection load. ## Scaling WebSockets Is Different From Scaling HTTP HTTP scaling is often stateless. If requests are independent, a load balancer can send each request to any healthy backend. WebSockets are different because the client holds a live connection to one backend server. Once connected, future messages usually travel through that same connection. That means connection distribution, backend state, and reconnection behavior matter. Raff’s single-server vs multi-server architecture guide explains that a single server is a common starting point for MVPs and moderate traffic, while multi-server architecture becomes useful when resource contention, scaling ceilings, deployment risk, or availability requirements increase. [Single Server vs Multi-Server Architecture](https://rafftechnologies.com/learn/guides/single-server-vs-multi-server-architecture) For WebSockets, the scaling path often looks like this: | Stage | Architecture | When it fits | |---|---|---| | Single VM | Web app and WebSocket server on one machine | MVP, internal tool, early product | | Single VM with reverse proxy | Edge proxy routes HTTP and WebSocket paths | Cleaner TLS and routing | | App plus worker processes | Background work separated from socket handling | Message processing grows | | Multiple WebSocket servers | Connections distributed across nodes | Concurrency exceeds one VM | | Shared message layer | Redis, pub/sub, broker, or database coordinates events | Users on different nodes need shared state | | Regional or edge-aware design | Traffic moves closer to users | Latency-sensitive workloads | The main scaling issue is state. If all connected users are on one server, broadcasting messages is simple. If users are spread across five servers, a message created on one server may need to reach users connected to the others. That usually requires a shared message layer, pub/sub system, broker, or application-level coordination. ## Sticky Sessions Are Helpful, But Not a Complete Plan Sticky sessions mean a load balancer keeps sending the same client to the same backend server. For WebSockets, this can help because a client’s connection is already tied to a specific server. But sticky sessions do not solve every scaling problem. If one backend receives too many long-lived connections, it can become overloaded. If a backend fails, those clients still need to reconnect somewhere else. If users on different backends need to receive the same event, the application still needs shared state or message fan-out. | Scaling concern | Sticky sessions help? | Still needed | |---|---:|---| | Keeping one client on one backend | Yes | Connection health and reconnect handling | | Sharing events across servers | No | Pub/sub or shared message layer | | Backend failure recovery | Partly | Reconnect strategy and state recovery | | Uneven connection load | Partly | Load balancing and capacity monitoring | | User presence across nodes | No | Shared presence store or coordination | | Deployments without disconnecting everyone | Partly | Drain strategy and rolling deployment plan | The practical rule is: **sticky sessions help route connections, but shared state helps the application behave correctly**. A small team can start without a complex distributed design. But once WebSocket connections are spread across multiple backends, state must be handled deliberately. ## WebSocket Cost Depends on Connections, Messages, and State WebSocket hosting cost is not only the VM price. A WebSocket workload can cost more than a normal web app when it needs more memory for connections, more CPU for message handling, more bandwidth for frequent updates, more monitoring, or more servers for availability. Cost grows through: | Cost area | WebSocket-specific reason | |---|---| | VM size | More connections and messages may need more RAM and CPU | | Bandwidth | Frequent updates and large payloads increase transfer | | Reverse proxy / load balancer | Edge routing and multi-node distribution may be needed | | Shared message layer | Redis, broker, or database coordination may be required | | Monitoring | Connection count, reconnects, latency, and message rate need visibility | | Backups | Persistent state still needs protection | | Development time | Reconnect logic, presence, and fan-out add complexity | Raff’s cloud server cost guide explains that cloud server pricing should include compute, memory, storage, bandwidth, backups, licensing, and support rather than only the VM price. That same principle applies to WebSocket applications. [Cloud Server Cost in 2026](https://rafftechnologies.com/learn/guides/cloud-server-cost-2026) For small teams, the cost question should be: | Question | Why it matters | |---|---| | How many users are connected at once? | Drives memory and connection limits | | How often do they receive messages? | Drives CPU and bandwidth | | Are messages small or large? | Drives transfer and serialization cost | | Do messages need to reach many users? | Drives fan-out complexity | | Can users reconnect safely? | Affects reliability and deployment strategy | | Does state need to be shared across nodes? | Adds infrastructure complexity | A real-time feature that updates once every few minutes may be cheap to run. A real-time feature that streams high-frequency updates to thousands of users is a different infrastructure problem. ## Reliability Depends on Reconnection Behavior Every WebSocket application needs a reconnection story. Connections can drop because of network changes, browser behavior, mobile devices moving between networks, proxies, server restarts, deployments, timeouts, or backend failures. A good WebSocket system assumes disconnection will happen. The question is what happens next. | Reliability concern | Better design question | |---|---| | Client disconnects | Can the client reconnect without user confusion? | | Server restarts | Are clients routed back cleanly? | | Message missed during reconnect | Does the client need replay, sync, or refresh? | | Backend deploys | Can connections drain gracefully? | | Mobile network changes | Does the client retry with backoff? | | Duplicate messages | Can the app handle repeated events safely? | For some apps, missing a message is acceptable because the next state update corrects the UI. For others, every event matters. A chat message, payment update, game action, or collaborative edit may need stronger delivery semantics. This is why WebSocket reliability is partly an application design problem, not only a hosting problem. ## Security Still Starts With Normal Web Security WebSockets do not remove normal web security concerns. Authentication, authorization, TLS, origin checks, input validation, rate limiting, logging, and abuse protection still matter. In some ways, they matter more because a WebSocket connection can stay open and continue sending messages after the initial handshake. Security decisions include: | Security area | WebSocket concern | |---|---| | TLS | Use secure WebSockets with `wss://` for production | | Authentication | Decide how clients prove identity before or during connection | | Authorization | Users should only join rooms or channels they are allowed to access | | Origin checks | Prevent unwanted browser origins from connecting | | Rate limits | Limit connection attempts and message frequency | | Message validation | Treat every inbound message as untrusted input | | Logging | Record connection errors and suspicious message patterns | | Abuse handling | Disconnect or throttle clients that misbehave | Raff’s Cloud Security Fundamentals guide frames security as reducing exposure, controlling access, patching, backups, monitoring, and incident readiness. WebSocket hosting should follow the same discipline. [Cloud Security Fundamentals](https://rafftechnologies.com/learn/guides/cloud-security-fundamentals) A WebSocket endpoint is not “just a socket.” It is a public application surface that needs the same security thinking as HTTP routes. ## Observability Should Track Connection Health Traditional web monitoring often focuses on response time, error rate, CPU, RAM, and HTTP status codes. WebSocket applications need additional signals. Raff’s observability guide explains metrics, logs, and traces as the three signals small teams use to understand system behavior. [Observability for Small Teams](https://rafftechnologies.com/learn/guides/observability-small-teams-metrics-logs-traces) For WebSockets, useful signals include: | Signal | Why it matters | |---|---| | Active connections | Shows real-time capacity usage | | Connection attempts | Reveals traffic spikes or abuse | | Connection duration | Shows whether sessions are stable | | Reconnect rate | Reveals network, timeout, or deployment problems | | Messages per second | Shows application-level load | | Average message size | Helps estimate bandwidth and memory pressure | | Send latency | Shows whether updates are delayed | | Dropped connections | Reveals reliability issues | | Backend memory use | Shows connection overhead | | Queue or pub/sub lag | Shows fan-out or shared-state pressure | The most important operational mistake is waiting until users complain. Real-time apps feel broken quickly when updates lag or connections repeatedly drop. Monitoring should show connection health before support messages arrive. ## When a Single VM Is Enough A single VM can be a good starting point for many WebSocket applications. This is especially true for MVPs, internal dashboards, private tools, small chat systems, game prototypes, collaborative tools with limited users, and early SaaS features. Starting with one VM keeps the architecture understandable. The team can focus on connection behavior, message design, authentication, monitoring, and product fit before adding distributed complexity. A single VM is usually enough when: | Condition | Why it helps | |---|---| | Connection count is modest | One server can manage the active sessions | | Message rate is low to moderate | CPU and bandwidth stay predictable | | Downtime tolerance exists | Simpler deployment is acceptable | | State is local or easy to rebuild | No cross-node coordination needed | | Team is still validating product | Complexity would slow learning | A single VM becomes risky when WebSocket traffic is central to revenue, connection counts grow, reconnect storms become painful, or downtime affects customers immediately. The right move is not to scale early by default. It is to know which signal will tell you when one VM is no longer enough. ## When WebSocket Apps Need Multi-Node Scaling A WebSocket app usually needs multi-node scaling when one server can no longer handle the connection count, message rate, reliability requirement, or deployment risk. Raff’s auto-scaling guide explains that scaling decisions should be based on measurable pressure, including CPU, RAM, disk I/O, latency, traffic patterns, and queue depth. WebSocket apps add active connections, message rate, and reconnect behavior to that list. [Auto-Scaling VM Planning](https://rafftechnologies.com/learn/guides/auto-scaling-vm-planning) | Scaling trigger | What it suggests | |---|---| | Active connections approach safe limit | Add capacity or optimize connection memory | | Message processing creates CPU pressure | Move work to workers or add servers | | Broadcasts delay under load | Add pub/sub or fan-out design | | Deployments disconnect too many users | Use rolling deployments and connection draining | | One VM is a single point of failure | Add redundant nodes | | Users are geographically far away | Consider regional strategy or edge delivery | | Reconnect storms overload server | Add backoff, capacity, and better restart behavior | The key point: scaling WebSockets is not only “add another server.” It usually also means changing how messages, presence, sessions, and reconnection are coordinated. ## How WebSocket Hosting Applies on Raff Raff gives developers a practical environment for hosting WebSocket workloads because it provides server-level control without forcing a managed application platform. A small team can start with a Node.js, Go, Python, Elixir, Java, or other WebSocket-capable application on a Linux VM. It can place a reverse proxy in front for TLS and routing, run the application directly or in Docker, and add a shared message layer later if the workload grows. Raff Linux VMs provide full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) A practical Raff path looks like this: | Stage | WebSocket hosting model | |---|---| | Prototype | One Linux VM, app process, simple monitoring | | Early production | Reverse proxy plus WebSocket backend | | Growing app | Separate app process, background workers, better observability | | Multi-node | Load balancing, shared message layer, connection tracking | | Business-critical | Redundancy, backups, incident response, deployment discipline | The design rationale is simple: WebSocket hosting should start from the workload, not the architecture trend. If one VM is enough, keep it simple. If connection pressure grows, split the right layer. If messages need to reach users across servers, add shared state deliberately. Aybars’ practical angle for this guide is that real-time infrastructure should stay boring. A WebSocket app feels impressive to users only when the connection layer is stable, measurable, and easy to reason about. ## Common WebSocket Hosting Mistakes **Using WebSockets when polling would be enough.** If updates are rare, polling or Server-Sent Events may be simpler and cheaper to operate. **Ignoring connection count.** Monthly visitors do not tell you enough. Active concurrent connections matter more. **Treating WebSockets like normal HTTP requests.** Persistent connections affect timeouts, memory, process stability, and deployments. **Forgetting reverse proxy behavior.** The edge layer must support HTTP upgrade behavior and avoid closing connections too aggressively. **Scaling without shared state.** Multiple WebSocket servers need a way to coordinate messages, presence, and events. **Not planning reconnect behavior.** Clients will disconnect. A production app should expect it and recover cleanly. **Sending too much data too often.** Payload size and message frequency can turn a small real-time feature into a bandwidth and CPU problem. **Keeping real-time and heavy background work in the same process forever.** Background jobs can delay message handling and make the app feel unstable. ## A Practical WebSocket Hosting Policy A small-team WebSocket policy should be clear enough to guide architecture decisions before the app becomes fragile. | Policy area | Recommended baseline | |---|---| | Communication model | Use WebSockets only when two-way persistent communication is needed | | Starting architecture | Begin with one VM when connection count and message rate are modest | | Reverse proxy | Ensure the edge layer supports WebSocket upgrade and sensible timeouts | | Security | Use `wss://`, authentication, authorization, origin checks, and message validation | | Observability | Track active connections, reconnects, message rate, latency, and errors | | Scaling trigger | Add nodes when connection count, message rate, or reliability needs exceed one VM | | Shared state | Add pub/sub or a broker when users on different nodes need shared events | | Cost review | Estimate cost from connections, message frequency, bandwidth, and redundancy | | Reliability | Define reconnect behavior, drain strategy, and recovery path | The best policy is not the most complex one. It is the one your team can follow while the product grows. ## WebSocket Hosting Is Real-Time Infrastructure Planning WebSocket hosting is not just opening a socket in an application. It is infrastructure planning for persistent communication. Use WebSockets when two-way real-time behavior is central to the product. Use polling or Server-Sent Events when they are simpler and good enough. Start with one VM when the workload is modest. Add reverse proxy discipline, observability, shared state, and multi-node scaling only when connection pressure and reliability needs make them necessary. For related reading, this guide should link to Raff’s Reverse Proxy vs Load Balancer guide, Single Server vs Multi-Server Architecture guide, Auto-Scaling VM Planning guide, Performance Bottlenecks guide, Background Work Models guide, and Observability guide. On Raff, the practical path is to host the first real-time workload simply, measure concurrent connections and message behavior, then scale the architecture only when the workload proves it needs more than one server. --- ### Production Launch Infrastructure Checklist: Traffic, Rollback, Monitoring, and Cost URL: https://rafftechnologies.com/learn/guides/production-launch-infrastructure-checklist-traffic-rollback-monitoring-cost Description: Prepare production infrastructure for launch with a checklist covering traffic, rollback, monitoring, backups, access, scaling, and cost readiness. A production launch infrastructure checklist is a structured review of the systems, controls, and recovery paths needed before real users rely on a cloud application. For founders and small teams, launch day is not only a product milestone. It is the first moment when infrastructure decisions become customer-facing. A server that was “good enough for testing” now has to handle real traffic, real support requests, real data, real costs, and real recovery pressure. Raff Technologies gives small teams full-root Linux VMs, Windows VMs, unmetered bandwidth, backups, snapshots, and fast deployment, which helps teams launch with infrastructure they can understand and operate. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) This guide belongs in Raff’s startup infrastructure and cloud operations cluster. Raff already has guides on enterprise customer readiness, cloud budget guardrails, idle infrastructure cost, cost dashboards, performance bottlenecks, and incident response. This guide focuses on the final production-launch layer: what to check before opening the door to traffic. ## Production Launch Readiness Is Not the Same as Feature Readiness A feature can be ready while the infrastructure is not. The app may pass QA. The landing page may look polished. The payment flow may work in staging. The demo may impress investors or early customers. But production launch readiness asks a different set of questions. Can users reach the service? Can the team roll back if the release fails? Can the team see errors before customers complain? Can data be restored if something goes wrong? Can cloud spend remain predictable if traffic spikes? Does anyone know who owns the first incident? Those questions matter because launch pressure changes the environment. Before launch, problems are internal. After launch, problems become customer experience, reputation, support load, and cost. | Product-ready question | Infrastructure-ready question | |---|---| | Does the feature work? | Can the feature survive real traffic? | | Did QA approve it? | Can we monitor it in production? | | Does staging look correct? | Can production roll back safely? | | Can users sign up? | Can we protect account, payment, and data flows? | | Is the launch date set? | Is the team ready if launch traffic exceeds expectations? | The goal is not to delay launch forever. The goal is to launch with enough control that problems do not become chaos. ## The Production Launch Decision Framework Use this framework to decide whether the infrastructure is ready for launch, needs a small fix, or should pause. | Launch area | Ready signal | Warning signal | Better decision | |---|---|---|---| | Traffic path | DNS, TLS, firewall, reverse proxy, and app route are validated | Public path differs from staging or has not been tested | Validate before launch | | Rollback | Previous app version, snapshot, or restore path is known | Team does not know how to undo the release | Pause or define rollback | | Monitoring | Errors, latency, uptime, and resource usage are visible | Customers are the first alert system | Add basic monitoring | | Backups | Important data has a tested recovery path | Backups exist but restore is untested | Test restore or lower launch risk | | Access | Production access is named and limited | Shared admin credentials or unknown SSH keys | Review access | | Cost | Expected VM, bandwidth, backup, and scaling cost is estimated | Team does not know what launch traffic may cost | Define budget guardrails | | Support | Ownership and escalation are clear | Everyone assumes someone else is watching | Assign launch owner | | Performance | CPU, RAM, disk, and network headroom are reasonable | Production is sized like a disposable test server | Right-size before launch | | Data | Sensitive data paths are understood | Test/demo data practices carry into production | Clean and restrict data | | Incident response | First-response plan exists | No one knows what happens if launch fails | Create a short runbook | A practical rule: **launch when the team knows how to detect, contain, roll back, and explain the most likely failures**. The checklist should not become an excuse for overengineering. It should reduce avoidable risk. ## Traffic Readiness Starts With the Public Path Production traffic does not care that the application worked locally. Users reach your product through DNS, TLS, firewalls, reverse proxies, load balancers, application routes, authentication, databases, storage, and sometimes third-party services. A production launch checklist should validate that full path. | Traffic component | Launch check | |---|---| | DNS | Domain points to the right production destination | | TLS / HTTPS | Certificate is valid and secure pages load correctly | | Firewall | Only required ports are exposed | | Reverse proxy | Routes traffic to the correct app or service | | Load balancer | Healthy targets receive traffic if used | | Application routes | Critical pages and APIs respond correctly | | Authentication | Login, signup, password reset, and session behavior work | | Database | Production app connects to the correct database | | Storage | Uploads, downloads, and static assets work | | External services | Payment, email, analytics, and API integrations are reachable | Raff’s first-server guide already covers important early server steps such as login, updates, users, firewall, monitoring, and first deployment. Production launch readiness builds on that foundation and asks whether the full public path is safe for real users. [First Cloud Server After Provisioning](https://rafftechnologies.com/learn/guides/first-cloud-server-after-provisioning) The launch mistake is checking only the server. A server can be healthy while DNS is wrong. The app can be running while TLS fails. The homepage can work while signup is broken. Production readiness means testing the path that customers will actually use. ## Rollback Planning Should Happen Before Launch A rollback plan is the answer to one uncomfortable question: what do we do if this launch makes production worse? Small teams often delay this question because nobody wants to plan for failure during a launch. But the best time to define rollback is before the team is under pressure. Rollback can mean different things depending on what changed. | Launch change | Better rollback path | |---|---| | Application code | Redeploy previous version | | Container image | Revert to previous image tag | | VM configuration | Restore snapshot or reapply known-good config | | Database migration | Use tested migration rollback or restore plan | | DNS change | Revert DNS record if TTL and propagation allow | | Reverse proxy change | Restore previous proxy configuration | | Windows app update | Restart service, roll back app files, or restore snapshot | | Large infrastructure change | Use staged cutover or fallback environment | The most dangerous launch is one where the team can only move forward. A rollback plan should include: | Rollback detail | Why it matters | |---|---| | Trigger | Defines when rollback begins | | Owner | Avoids debate during pressure | | Previous version | Confirms what “back” means | | Data impact | Prevents unsafe database reversal | | Time window | Defines how long the team tries to fix forward | | Verification | Confirms rollback actually worked | | Communication | Keeps internal and customer updates aligned | A practical rule: **if the team cannot roll back, it should know exactly why and what the safer alternative is**. Sometimes the answer is not rollback. Sometimes it is feature flagging, disabling a workflow, restoring a backup, or fixing forward. The point is to decide before launch. ## Monitoring Should Be Ready Before Users Arrive Monitoring is not something to add after customers complain. At launch, the team should be able to see whether the app is reachable, whether errors are rising, whether latency is increasing, whether resources are under pressure, and whether critical workflows still work. Raff’s observability guide explains metrics, logs, and traces as the three signals small teams use to understand system behavior. [Observability for Small Teams](https://rafftechnologies.com/learn/guides/observability-small-teams-metrics-logs-traces) A launch monitoring baseline should include: | Signal | Why it matters | |---|---| | Uptime | Confirms the public service is reachable | | Error rate | Shows whether users are experiencing failures | | Latency | Shows whether the app is becoming slow | | CPU usage | Reveals compute pressure | | RAM usage | Reveals memory pressure and crash risk | | Disk usage | Prevents full-disk failures | | Network traffic | Helps understand launch traffic patterns | | Database health | Shows connection, query, and storage pressure | | Application logs | Explains what failed | | Key user journey checks | Confirms signup, login, checkout, or dashboard works | The monitoring goal is not to build a perfect observability stack before launch. The goal is to avoid flying blind. A small team should at least know: - is the app up, - are errors increasing, - are users getting slow responses, - is the VM under resource pressure, - and which workflow is failing. ## Backups and Snapshots Are Launch Safety Tools Backups and snapshots should not be treated as optional afterthoughts. A production launch can introduce new data, new customers, new payments, new files, new accounts, and new operational risk. If something goes wrong, the team needs a way to recover important state. Raff’s Data Protection product page describes snapshots, automated backups, retention options, replicated storage, and recovery-focused data protection. [Raff Data Protection](https://rafftechnologies.com/products/data-protection) The launch checklist should separate snapshots and backups: | Protection type | Launch use | |---|---| | Snapshot before launch | Quick rollback before a risky release or configuration change | | Automated backup | Recovery for important data after launch | | Database backup | Protection against corruption or migration mistakes | | File/storage backup | Protection for uploads, media, and generated assets | | Configuration backup | Recovery for reverse proxy, firewall, and service config | | Restore test | Confidence that recovery actually works | A snapshot can help if a server change breaks the environment. A backup can help if data needs to be restored. Neither should be assumed useful unless the team knows how to use it. A practical rule: **do not treat “backup exists” as launch readiness until someone knows how restore works**. ## Cost Readiness Prevents Launch-Surprise Bills A launch can change cost quickly. More users can mean more CPU, RAM, bandwidth, storage, backups, logs, database activity, and support work. Sometimes cost increases are healthy because they come from real usage. Sometimes they are waste because the team overprovisioned, left test infrastructure running, or failed to set retention rules. Raff’s cloud budget guardrails guide explains that cloud spend often drifts through small decisions: oversized instances, forgotten test servers, unused disks, excessive snapshots, and always-on staging environments. [Cloud Budget Guardrails for Startups](https://rafftechnologies.com/learn/guides/cloud-budget-guardrails-startups-vm-spend-drift) A launch cost review should include: | Cost area | Launch question | |---|---| | Production VM | Is it sized for expected launch traffic? | | Staging | Should it remain online after launch? | | Preview/test VMs | Can they be deleted before launch? | | Backups | What retention and storage cost are expected? | | Logs | Could log volume grow quickly? | | Bandwidth | Could traffic or downloads increase cost? | | Windows licensing | Does the workload require Windows-specific planning? | | Monitoring | Are observability costs predictable? | | Support | Who handles incidents and user issues? | Raff’s cloud server cost guide frames cloud server pricing as more than the VM price, including compute, memory, storage, bandwidth, backups, licensing, and support. [Cloud Server Cost in 2026](https://rafftechnologies.com/learn/guides/cloud-server-cost-2026) The launch goal is not to minimize cost at all costs. It is to understand which costs are expected, which are tied to growth, and which are avoidable waste. ## Performance Headroom Should Match Launch Risk Production launch does not require buying the largest possible server. It does require enough headroom for expected launch behavior. The right amount depends on product type, launch campaign, user count, workload shape, database activity, and recovery tolerance. Raff’s performance bottlenecks guide explains that CPU, RAM, disk I/O, and network can all become limiting resources, and that teams should diagnose the bottleneck before resizing blindly. [Cloud Server Performance Bottlenecks](https://rafftechnologies.com/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) Before launch, check: | Resource | Launch concern | |---|---| | CPU | Can the app handle expected request volume? | | RAM | Will the app, database, cache, and workers fit safely? | | Disk | Is there room for logs, uploads, database growth, and backups? | | Disk I/O | Will database or file-heavy work slow the system? | | Network | Can traffic, uploads, downloads, and API calls move reliably? | | Database connections | Will app workers exhaust database limits? | | Background jobs | Will workers compete with user-facing traffic? | | Cache | Is cache behavior understood under load? | A launch server should not be sized like a disposable test VM if customers and revenue depend on it. At the same time, overbuying too early can hide bad architecture and increase burn. The founder-level decision is to choose enough capacity for launch confidence, then review real usage after launch. ## Access Control Should Be Clean Before Launch Production launch increases the value of access. Before launch, access may feel informal. After launch, production contains real users, real data, real billing, and real operational risk. The team should know who can access the server, dashboard, database, backups, secrets, and deployment pipeline. A launch access review should include: | Access surface | Launch question | |---|---| | SSH keys | Who can access Linux production servers? | | Root or sudo | Who can run privileged commands? | | RDP access | Who can access Windows production servers? | | Admin users | Are admin accounts individual or shared? | | Cloud dashboard | Who can create, resize, delete, or manage VMs? | | Secrets | Who can view production credentials? | | Database | Who can read or modify production data? | | Backups | Who can restore or delete backups? | | Deployment | Who can push to production? | | Emergency access | Is break-glass access documented? | Raff’s cloud access reviews guide is the natural sibling topic here because it explains SSH keys, admin users, RDP access, API keys, service accounts, and offboarding as recurring access review concerns. If access is unclear before launch, it will be harder to clean up after launch. A practical rule: **every production access path should have an owner, a reason, and a removal condition**. ## Deployment Timing Should Be a Business Decision Technical teams often think launch timing is only about when the code is ready. But production launch timing also affects support, monitoring, communication, rollback, and incident response. A launch on Friday night may feel convenient until something fails over the weekend. A launch during a marketing push may create traffic pressure. A launch before backups are verified may create unnecessary risk. | Timing question | Why it matters | |---|---| | Who is available after launch? | Incidents need owners | | Is support ready? | Users may need help | | Is monitoring watched? | Early issues need fast detection | | Is rollback possible? | Launch should not trap the team | | Is traffic expected to spike? | Capacity and support planning matter | | Are third-party dependencies stable? | External outages can affect launch | | Is this near a holiday or weekend? | Response availability may be weaker | A good launch window is not only convenient. It is observable, staffed, and reversible. The best time to launch is often when the people who can fix the system are actually available. ## Staging and Production Must Be Clearly Separated Production launch becomes dangerous when staging and production are too similar in the wrong ways or too different in the wrong ways. Staging should help test release behavior without putting real users at risk. Production should contain real user data and real traffic. Confusing the two can create data leaks, broken integrations, or false confidence. Raff’s Dev, Staging, and Production guide explains why these environments should serve different roles. [Dev, Staging, and Production Cloud Environments](https://rafftechnologies.com/learn/guides/dev-staging-production-cloud-environments) Before launch, verify: | Environment issue | Launch risk | |---|---| | Staging uses production secrets | Security risk | | Production points to test payment system | Revenue or checkout failure | | Staging data copied carelessly | Privacy risk | | Production has debug settings enabled | Security and performance risk | | Staging is much smaller than production | Performance results may mislead | | Production migrations untested | Launch failure | | Feature flags differ unexpectedly | Wrong features exposed | A practical rule: **staging should be similar enough to catch mistakes, but separate enough to protect production data and users**. ## Support and Incident Ownership Should Be Named During launch, “everyone is watching” can quickly become “nobody owns it.” A launch checklist should name the person responsible for launch coordination, technical monitoring, customer support, and rollback decision. In a small team, one person may hold several roles. That is fine as long as everyone knows it. | Launch role | Responsibility | |---|---| | Launch owner | Coordinates go/no-go and timeline | | Technical owner | Watches health, logs, errors, and resources | | Rollback owner | Decides whether rollback or fix-forward is safer | | Support owner | Handles customer questions and reports | | Communications owner | Updates internal team or public channels if needed | | Cost owner | Reviews infrastructure usage after launch | Raff’s incident response guide explains that incident ownership, severity, containment, recovery, communication, and post-incident review are all part of calm response when production is unstable. [Server Incident Response for Small Teams](https://rafftechnologies.com/learn/guides/server-incident-response-small-teams-triage-containment-recovery) Production launch is not always an incident. But the same ownership discipline helps. ## The Go / No-Go Launch Checklist Use this checklist before opening production to real traffic. | Area | Go signal | No-go or pause signal | |---|---|---| | Traffic | DNS, TLS, routing, firewall, and app path validated | Public path untested | | App | Critical user journeys pass | Signup, login, checkout, dashboard, or API path fails | | Rollback | Clear rollback or fix-forward plan exists | No known recovery path | | Backup | Important data is backed up and restore path is understood | Backup exists but nobody knows how to restore | | Monitoring | Errors, uptime, latency, and resources are visible | Team cannot see production health | | Performance | VM has reasonable CPU, RAM, disk, and network headroom | Server is already near limits before launch | | Access | Production access is named and controlled | Shared or unknown admin access | | Cost | Expected cost range is understood | Team has no cost expectation | | Support | Launch owner and support owner are named | No one owns customer reports | | Incident response | First-response path is defined | Team would improvise under pressure | A launch can proceed with known imperfections. It should not proceed with unknown critical risks. The right go/no-go question is: **if this launch fails, can we detect it, respond to it, and recover from it without guessing?** ## After Launch, Review the First 24–72 Hours Launch readiness does not end when the product goes live. The first 24–72 hours reveal how infrastructure behaves under real usage. This is when teams learn whether sizing was correct, monitoring is useful, logs are too noisy, cost assumptions were accurate, and users behave as expected. Review: | Post-launch area | Question | |---|---| | Traffic | Did traffic match expectations? | | Errors | Which errors appeared after real users arrived? | | Latency | Did key pages or APIs slow down? | | Resources | Did CPU, RAM, disk, or network approach limits? | | Database | Were queries, locks, or connections a problem? | | Backups | Did scheduled backups run successfully? | | Logs | Are logs useful or too noisy? | | Cost | Did spend match the expected launch budget? | | Support | What did users report? | | Rollback plan | Would the team have been ready if needed? | The post-launch review should produce decisions, not just observations. Examples: resize the VM, reduce log noise, add a synthetic check, delete staging clones, adjust backup retention, restrict admin access, or create a runbook for a repeated issue. ## How Production Launch Planning Applies on Raff Raff is designed for teams that want clear, controllable infrastructure without unnecessary cloud complexity. For launch planning, Raff Linux VMs give teams full root access, SSH key authentication, Docker-ready infrastructure, NVMe SSD storage, unmetered bandwidth, DDoS protection, cloud firewall, and deployment in under 60 seconds. [Raff Linux VM](https://rafftechnologies.com/products/linux-vm) Raff Windows VMs are useful when production launch depends on Windows Server, RDP, IIS, .NET, business software, or Windows-native workloads. [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) Raff Data Protection supports snapshots and automated backups for teams that need a recovery path before launching. [Raff Data Protection](https://rafftechnologies.com/products/data-protection) A practical Raff launch model looks like this: | Launch need | Raff context | |---|---| | Production compute | Linux or Windows VM sized for launch traffic | | Public traffic | Firewall, DNS, TLS, and application routing validation | | Rollback | Snapshot before risky changes and app rollback plan | | Recovery | Automated backups and restore awareness | | Monitoring | VM metrics, logs, app health, and user journey checks | | Cost control | Transparent VM pricing and review of staging/test environments | | Access | SSH key, root/sudo, RDP, and admin access review | | Growth | Resize or split workloads after usage becomes measurable | From Batuhan’s founder perspective, the launch principle is simple: do not wait for perfect infrastructure, but do not launch blindly either. A good production launch is not the one with the most complex architecture. It is the one where the team knows what matters, what might fail, what it will cost, and how to recover. ## Common Production Launch Mistakes **Testing only the application, not the traffic path.** DNS, TLS, firewall, reverse proxy, and public routing all matter. **Launching without rollback.** A launch should have a known recovery path before it affects users. **Adding monitoring after launch.** If users are the first alert system, the team is already late. **Forgetting backup restore.** Backups are not useful if nobody knows how to restore them. **Using staging cost assumptions for production.** Real users create different traffic, storage, logs, and support behavior. **Launching with unclear access.** Shared admin accounts, old SSH keys, or unknown RDP users create avoidable risk. **Overbuying infrastructure out of fear.** More capacity can help, but it should match real launch risk, not anxiety. **Ignoring the first 72 hours.** Post-launch usage is the best source of infrastructure truth. ## A Practical Launch Policy for Small Teams A small-team launch policy should be short and repeatable. | Policy area | Recommended baseline | |---|---| | Traffic | Validate DNS, TLS, firewall, proxy, app routes, and critical user journeys | | Rollback | Define rollback, restore, or fix-forward decision before launch | | Monitoring | Track uptime, errors, latency, CPU, RAM, disk, network, and key workflows | | Backups | Confirm backup coverage and restore path for important data | | Access | Review SSH keys, RDP users, admin accounts, secrets, and deployment access | | Cost | Estimate launch cost and review after 24–72 hours | | Performance | Right-size for expected launch traffic with reasonable headroom | | Support | Assign launch owner, technical owner, and support owner | | Review | Run a post-launch review and turn findings into action | This policy is intentionally practical. A startup does not need enterprise launch governance on day one. It needs enough structure to avoid preventable chaos. ## Production Launch Is the Moment Infrastructure Becomes Real Before production launch, infrastructure decisions are mostly internal. After launch, they affect customers. That is why a production launch infrastructure checklist matters. Traffic paths need validation. Rollback needs a plan. Monitoring needs to be visible. Backups need to be usable. Access needs to be controlled. Cost needs to be understood. Support ownership needs to be clear. For related reading, this guide should link to Raff’s Startup Infrastructure Checklist, Cloud Budget Guardrails, Idle Infrastructure Cost, Cloud Cost Management in Power BI, Performance Bottlenecks, and Server Incident Response guides. On Raff, the practical path is to launch with infrastructure that is simple enough to understand, strong enough to recover, and transparent enough to control as real users arrive. --- ### Cloud VPS vs Traditional VPS: What Developers Should Know URL: https://rafftechnologies.com/learn/guides/cloud-vps-vs-traditional-vps Description: Understand cloud VPS vs traditional VPS hosting with a decision framework for control, scaling, storage, pricing, reliability, and developer workflows. Cloud VPS is a virtual private server model that adds cloud infrastructure features such as faster provisioning, scalable resources, modern storage, and stronger networking.![Comparison matrix showing traditional VPS and cloud VPS across control, scaling, storage, bandwidth, operating systems, developer workflow, and long-term fit.](https://raff-images.s3.raffusercloud.com/Cloud_VPS_vs_Traditional_VPS_Concept_Diagram_8919ceac06.png) Traditional VPS hosting still works for many simple projects. If you need a small fixed server for a basic website, lightweight application, or personal project, a traditional VPS plan may be enough. But when developers and small teams need infrastructure that can grow with applications, databases, Windows workloads, Docker stacks, and production environments, cloud VPS usually becomes the stronger model. Raff Technologies supports more than 10,000 deployed VMs and builds cloud infrastructure for users who want fast deployment, clear pricing, NVMe SSD storage, unmetered bandwidth, and Linux or Windows server options. This guide is part of the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting) cluster and explains how cloud VPS compares with traditional VPS hosting, when each model makes sense, and how to choose the right path before deploying a workload. ## Cloud VPS and Traditional VPS Explained A VPS, or virtual private server, is an isolated server environment created through virtualization. It gives you your own operating system, allocated compute resources, storage, network access, and administrative control. Traditional VPS hosting usually packages that experience into fixed plans. You choose a plan, select an operating system, deploy the server, and manage it. Traditional VPS platforms are often simple, affordable, and familiar. They are useful when the workload is predictable and does not need many additional infrastructure features. ![Comparison matrix showing traditional VPS and cloud VPS across control, scaling, storage, bandwidth, operating systems, developer workflow, and long-term fit.](https://raff-images.s3.raffusercloud.com/Cloud_VPS_vs_Traditional_VPS_Comparison_Matrix_90213d494c.png) Cloud VPS keeps the same basic idea — an isolated virtual server — but places it inside a more cloud-like infrastructure model. That usually means stronger support for: * Faster provisioning * Modern CPU and storage * More flexible resizing * Better networking options * Snapshots and backups * Linux and Windows workloads * Clearer scaling paths * API or automation readiness * Integration with other cloud infrastructure layers The difference is not only the word “cloud.” The difference is the platform behavior around the server. Traditional VPS hosting asks: which fixed server plan do you want? Cloud VPS asks: what kind of virtual infrastructure does this workload need now, and how should it grow later? ## The Platform Behind the Server Is the Main Difference Traditional VPS and cloud VPS may look similar at first because both give you a virtual server. The difference becomes clearer once the workload starts to grow. Traditional VPS hosting is often built around fixed plans and simple hosting workflows. That can be helpful for basic websites, low-traffic applications, and users who want a straightforward server. Cloud VPS is usually built around a more flexible infrastructure layer. The VM is still the starting point, but it is not the whole story. The server may connect to snapshots, backups, object storage, private networking, monitoring, API-driven workflows, and larger VM sizes as the workload becomes more serious. This matters because infrastructure decisions are rarely only about the first deployment. A small project might begin as one virtual server. Later, it may need a staging environment, database separation, backup policy, private network, object storage, Windows access, or more RAM. If the platform cannot grow with the workload, the team may need to migrate earlier than expected. A traditional VPS can be enough when the workload is fixed. A cloud VPS is better when the workload is expected to evolve. ## The Cloud VPS vs Traditional VPS Decision Framework Use this framework before choosing between traditional VPS hosting and cloud VPS infrastructure. | Decision factor | Traditional VPS | Cloud VPS | | ------------------ | ----------------------------------- | -------------------------------------------------------- | | Best fit | Simple and fixed workloads | Growing applications and flexible infrastructure | | Provisioning | Usually simple but plan-based | Fast and often more flexible | | Scaling | Often manual or tier-limited | Easier resizing and growth paths | | Storage | Varies by host and plan | More likely to use SSD or NVMe storage | | Bandwidth | Often capped or plan-dependent | More likely to offer clearer bandwidth policies | | Networking | Basic public access | Better fit for private networks and multi-service setups | | Operating systems | Usually Linux, sometimes Windows | Stronger fit for Linux and Windows VM options | | Developer workflow | Good for simple hosting | Better for development, staging, APIs, and automation | | Cost model | Predictable fixed plans | Predictable plans or flexible cloud-style billing | | Long-term fit | Best when the workload stays simple | Best when the workload may grow or change | Traditional VPS is often enough when your project has one server, one purpose, limited traffic, and little need for infrastructure changes. Cloud VPS is usually the better path when you need more than a rented box: resizing, faster storage, predictable bandwidth, backups, Windows support, development environments, private networking, or future platform growth. A useful decision rule is this: if the workload will stay simple for 12 months, traditional VPS may be enough. If the workload may gain users, services, databases, environments, or team access within 12 months, cloud VPS is usually safer. ## Traditional VPS Hosting Is Enough for Simple Fixed Workloads Traditional VPS hosting is not outdated for every use case. It can be a practical choice when the workload is simple, the budget is tight, and the server does not need to evolve much. Many users only need a place to run a small website, test a project, host a personal application, or keep a lightweight service online. Traditional VPS hosting is often a good fit for: * Personal websites * Small blogs * Static sites * Small CMS projects * Low-traffic applications * Simple scripts * Learning Linux * Fixed workloads with predictable resource needs The benefit is simplicity. You choose a plan, deploy the server, and use it. If the provider is reliable and the workload stays small, this can work well. The limitation is flexibility. A traditional VPS can become restrictive when you need to resize quickly, separate services, run heavier databases, add safer backups, support Windows workloads, improve storage performance, or build a more structured deployment workflow. This is why the decision should not be emotional. Traditional VPS is not “bad.” It is simply optimized for a narrower infrastructure model. If your workload is narrow, traditional VPS can be enough. ## Cloud VPS Is Better for Workloads That Need Room to Grow Cloud VPS becomes more valuable when your server is not just hosting files but supporting a real workflow. Developers and small teams often move toward cloud VPS when they need to run applications, APIs, development environments, staging servers, databases, Windows workloads, Docker containers, automation tools, or business systems. Cloud VPS is usually a better fit for: * Web applications * APIs and backend services * Development and staging environments * Docker stacks * Databases with growth potential * Windows remote desktop workloads * Internal business applications * Customer-facing dashboards * Automation tools * Projects that may need more resources later The main advantage is not only performance. It is optionality. A cloud VPS gives you a stronger starting point when the workload may change. You can begin with one VM, then later think about storage, backups, network design, server sizing, or other cloud layers without immediately migrating to a completely different platform. That matters because early infrastructure decisions often become long-term habits. A simple server that works on day one may become a constraint by day one hundred if it cannot support the next stage. For cost planning, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). For sizing decisions, read [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). ## Cost, Storage, and Bandwidth Change the Real Comparison Traditional VPS plans often look cheaper at first glance. That can be true, especially for very small workloads. But the real comparison should include more than the base monthly price. ![Diagram showing VPS cost factors including CPU, RAM, NVMe storage, bandwidth, backups, snapshots, operating system, and support.](https://raff-images.s3.raffusercloud.com/Real_VPS_Cost_Factors_7ef306746b.png) You should compare: * CPU allocation * RAM * Storage type * Storage size * Bandwidth policy * Port speed * Backups * Snapshots * Windows support * Upgrade path * Support quality * Reliability expectations A low-cost traditional VPS may be excellent for a small website or test project. It becomes less attractive if slow storage affects the database, bandwidth caps create surprises, resizing is difficult, or backups are not part of the plan. Cloud VPS pricing is usually stronger when the provider makes the full resource model clear. For example, a cloud VPS with NVMe storage, predictable bandwidth, and resize-friendly plans may cost slightly more than the cheapest traditional VPS, but it can be less expensive operationally if it prevents downtime, migration work, or performance problems. The right comparison is not “which plan has the lowest monthly price?” The better comparison is: “which option gives this workload the safest resource fit for the next stage?” ## Developer Workflow Is Where Cloud VPS Often Wins Developers usually do not evaluate infrastructure only by server specs. They evaluate how quickly they can move from idea to working environment. Traditional VPS can be fine for one-off hosting. But it often feels limited when a team needs repeatable environments, staging, testing, background workers, Docker, automation, API deployments, or multiple operating systems. Cloud VPS fits developer workflows because it supports a more flexible way of working. A developer might use cloud VPS to: * Spin up a clean test environment * Run a staging version of an application * Deploy an API * Host a database for development * Test Linux packages * Run Docker containers * Create a Windows test environment * Run automation jobs * Share a remote environment with a team * Keep workloads online without relying on a laptop The value is speed and control together. Shared hosting is often too limited. Traditional VPS can work, but it may feel like a fixed server plan. Hyperscaler cloud can be powerful, but it can also add complexity before a small team needs it. Cloud VPS sits in the middle: more flexible than traditional hosting, but more understandable than enterprise cloud architecture. ## Raff VM Fits the Cloud VPS Model Raff VM is designed for users who want the practical benefits of cloud VPS without turning infrastructure into a complicated project. The decision behind Raff VM is simple: many developers, learners, startups, and small teams need cloud infrastructure that feels approachable on day one and still useful as the workload grows. That is why Raff VM starts with virtual machines but also connects naturally to broader cloud infrastructure needs such as storage, backups, networking, Windows workloads, and scalable plans. Raff VM supports cloud VPS workloads with AMD EPYC processors, NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and Linux or Windows VM options. Plans start from $4.99/month for entry-level workloads. That makes Raff VM a good fit when your decision framework points toward cloud VPS because you need: * Faster deployment than traditional server setup * Predictable monthly pricing * Modern CPU and NVMe storage * Unmetered bandwidth * Linux or Windows support * A path from small testing to larger workloads * Less complexity than hyperscaler cloud platforms Raff is not trying to make every workload look like the same VPS plan. The platform direction is to make cloud infrastructure easier to start and clearer to grow with. For users comparing traditional VPS and cloud VPS, that distinction matters: the VM is the starting point, but the larger value is the infrastructure path around it. ## Common Mistakes When Comparing Cloud VPS and Traditional VPS ### Comparing only the cheapest plan The cheapest plan may be enough for testing or a small website. It may be the wrong choice for databases, Windows workloads, production apps, or anything customers depend on. Price should be compared against workload risk, not just against other prices. ### Ignoring storage type Storage affects application responsiveness, database performance, updates, file operations, logs, and backups. A plan with slow storage can feel expensive even if the monthly price is low. ### Treating bandwidth as an afterthought Bandwidth matters for public websites, APIs, downloads, dashboards, media, and growing applications. If bandwidth is capped or unclear, the real cost may be harder to predict than the server price suggests. ### Choosing based only on today’s workload A fixed VPS can work well today and become a constraint later. If the workload may need staging, backups, more RAM, Windows support, object storage, or private networking, choose a platform that can grow with it. ### Confusing simplicity with limitation Simple infrastructure is good. Limited infrastructure is not. The best cloud VPS platforms stay simple at the beginning while still leaving room for more serious workloads later. ![Flowchart helping users choose between traditional VPS and cloud VPS based on workload simplicity, scaling needs, storage, bandwidth, and growth plans.](https://raff-images.s3.raffusercloud.com/Choose_Your_VPS_Model_Flowchart_b3bf03ce99.png) ## Choosing the Right VPS Model The best VPS model depends on how much the workload needs to grow. Traditional VPS hosting is still useful for simple websites, personal projects, and fixed workloads. Cloud VPS is usually the better choice when you need modern storage, clearer scaling, predictable bandwidth, Linux or Windows options, and infrastructure that can support the next stage of the project. For the broader decision, read the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If your workload fits the cloud VPS path, Raff VM gives you a practical way to start with predictable pricing, NVMe SSD storage, unmetered bandwidth, and Linux or Windows server options. [Explore Raff VM](/products/raff-vm) --- ### VPS vs AWS EC2: What Small Teams Should Know URL: https://rafftechnologies.com/learn/guides/vps-vs-aws-ec2 Description: Learn how to compare VPS hosting and AWS EC2 with a decision framework for pricing, billing, storage, bandwidth, networking, scaling, and team complexity. VPS hosting is a virtual server model that gives users isolated compute, storage, networking, and operating system control without requiring a full cloud architecture. AWS EC2 is also virtual compute, but it belongs to a much broader cloud platform. That difference matters. A small team choosing between VPS hosting and AWS EC2 is not only choosing a server. It is choosing between a simpler server-first model and a flexible cloud platform with more configuration, billing, security, networking, and service design decisions. Raff Technologies builds cloud VM infrastructure for developers, founders, startups, and small teams that want fast deployment, predictable pricing, NVMe SSD storage, unmetered bandwidth, and Linux or Windows options. This guide is part of the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting) cluster and explains when VPS hosting is enough, when AWS EC2 makes sense, and how small teams should compare both paths before deploying a workload. ## VPS and AWS EC2 Explained A VPS, or virtual private server, is usually sold as a hosting product. You choose a plan, select an operating system, deploy a virtual server, and manage the workload. A VPS is commonly used for: * Websites * Web applications * APIs * Databases * Development servers * Staging environments * Docker workloads * Windows remote desktop * Internal business tools * Small SaaS projects * Self-hosted software AWS EC2, or Amazon Elastic Compute Cloud, is a cloud compute service that provides resizable virtual server capacity inside AWS. EC2 instances can also run websites, applications, APIs, databases, Docker workloads, Windows workloads, and development environments. The difference is that EC2 usually sits inside a larger AWS architecture involving services such as IAM, VPC, EBS, Elastic IPs, load balancers, monitoring, security groups, snapshots, autoscaling, managed databases, object storage, and data transfer pricing. That flexibility is powerful, but it also adds decisions. A VPS usually asks: what server size do you need? AWS EC2 often asks: what cloud architecture do you need? For small teams, that distinction can decide the better path. ## The Core Difference Is Simplicity vs Platform Depth VPS hosting and AWS EC2 are not opposites. They are different levels of infrastructure abstraction. A VPS gives you a virtual server with a simpler product experience. It is usually easier to understand, easier to budget, and faster for teams that mainly need one or a few servers. ![Diagram showing VPS hosting focused on simple virtual servers and AWS EC2 connected to advanced cloud platform services.](https://raff-images.s3.raffusercloud.com/vps_ec2_simplicity_vs_platform_depth_webp_37582a1610.png) AWS EC2 gives you flexible cloud compute inside a large cloud ecosystem. It is powerful when your team needs advanced networking, service integrations, IAM, autoscaling, custom infrastructure design, multiple environments, compliance controls, or architecture that extends beyond a few virtual machines. The trade-off is straightforward: | Model | Main advantage | Main trade-off | | ----------- | ----------------------------------------------------- | ---------------------------------------------------------- | | VPS hosting | Simpler virtual server deployment and pricing | Fewer advanced cloud architecture options | | AWS EC2 | Highly flexible compute inside a broad cloud platform | More billing, networking, IAM, and architecture complexity | A VPS is often better when the workload is simple enough to run on one or a few virtual servers. AWS EC2 is often better when the workload belongs inside a broader cloud architecture. The decision is not “small provider versus big provider.” The decision is whether the team needs a server product or a cloud platform. ## The VPS vs AWS EC2 Decision Framework Use this framework before choosing between VPS hosting and AWS EC2. | Decision factor | VPS hosting is usually better when... | AWS EC2 is usually better when... | | ------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- | | Team size | Small team, solo developer, founder, or freelancer | Dedicated DevOps, platform, or cloud engineering support | | Workload complexity | One app, one API, one database, or simple stack | Multi-service architecture or distributed system | | Billing preference | Predictable monthly server pricing matters | Usage-based cloud billing is acceptable | | Setup speed | You want to deploy quickly with fewer decisions | You need custom architecture and AWS integrations | | Networking | Public server access and basic firewalling are enough | VPC design, subnets, peering, routing, or private architecture matter | | Identity and access | Basic account and server access is enough | IAM roles, policies, service access, and account separation matter | | Storage | Included or attached VM storage is enough | EBS, S3, snapshots, lifecycle policies, and storage classes matter | | Scaling | Manual resizing or larger plans are enough | Autoscaling groups, load balancers, and fleet design matter | | Monitoring | Basic server monitoring is enough | CloudWatch, alarms, logs, metrics, and service-level monitoring matter | | Cost control | You want a clear monthly plan | You can estimate instance, storage, transfer, IP, and service costs | | Best fit | Small apps, APIs, websites, staging, developer workloads | Larger applications, regulated systems, complex AWS-native workloads | Choose VPS hosting when the workload mostly needs a reliable virtual server. Choose AWS EC2 when the workload needs cloud platform depth around the server. A useful rule: if the infrastructure conversation starts with “we need a server,” VPS may be enough. If it starts with “we need a cloud architecture,” EC2 may be the better foundation. ![Decision matrix comparing VPS hosting and AWS EC2 by team size, workload complexity, pricing, networking, storage, scaling, and operations.](https://raff-images.s3.raffusercloud.com/vps_vs_aws_ec2_decision_matrix_webp_30deac55a3.png) ## When VPS Hosting Is the Better Choice VPS hosting is often the better choice when simplicity, predictability, and speed matter more than deep cloud customization. A VPS is usually a strong fit for: * Simple websites * Web applications * APIs * Small SaaS MVPs * Developer environments * Staging servers * Docker Compose stacks * Internal dashboards * Self-hosted tools * Small databases * Windows remote desktop workloads * Business applications * Freelance and agency projects * Learning Linux or Windows Server For these workloads, the value of VPS hosting is clarity. You choose a plan, deploy a server, connect over SSH or RDP, install your software, and run the workload. The platform does not require your team to design IAM policies, VPC routing, autoscaling groups, load balancers, instance profiles, multiple storage services, or detailed cost models before the first deployment. That does not mean VPS hosting is less serious. It means the product is focused. Many small teams do not need a full cloud platform before they have product-market fit, revenue, traffic, or an engineering team large enough to manage it. VPS hosting is often the better starting point when a team wants to launch quickly, keep billing understandable, and avoid unnecessary infrastructure decisions. ## When AWS EC2 Is the Better Choice AWS EC2 is usually the better choice when the workload belongs inside a broader AWS architecture. EC2 makes sense when your team needs: * Autoscaling groups * Elastic Load Balancing * IAM roles and fine-grained access policies * VPC architecture with private subnets * Multi-AZ or multi-region planning * Integration with managed AWS services * Custom AMIs * Infrastructure as code * Advanced monitoring and alerting * Enterprise account governance * Compliance controls * Large-scale automation * Spot, Reserved Instance, or Savings Plan strategies * Complex storage and data lifecycle planning This is where AWS is strong. If your application needs to integrate deeply with services such as S3, RDS, Lambda, ECS, EKS, CloudWatch, IAM, Route 53, CloudFront, or other AWS-native services, EC2 may be part of the right architecture. The trade-off is that EC2 is rarely “just a server” in practice. Once you use EC2 properly inside AWS, you often also need to understand regions, Availability Zones, VPCs, security groups, key pairs, IAM roles, EBS volumes, snapshots, Elastic IPs, monitoring, and data transfer costs. That complexity can be worthwhile for the right workload. It can also be unnecessary for a small team that only needs a dependable virtual server. ## Pricing and Billing Are Different Problems VPS pricing is usually plan-based. You choose a server size and pay a predictable monthly amount. AWS EC2 pricing is more flexible. That flexibility can reduce costs in advanced setups, but it also means the total bill depends on multiple variables. ![Diagram comparing predictable VPS pricing with AWS EC2 billing factors including instance runtime, storage, data transfer, IPs, monitoring, and services.](https://raff-images.s3.raffusercloud.com/vps_pricing_vs_ec2_billing_model_webp_139d803b05.png) An EC2-based workload may include costs for: * Instance runtime * Instance type * Region * Operating system * EBS volumes * EBS snapshots * Data transfer * Elastic IP usage * Load balancers * Monitoring * NAT gateways * Managed databases * Object storage * Support plans * Additional AWS services This is not a criticism of AWS. It is the nature of a flexible cloud platform. For a team with cloud experience, usage-based billing can be optimized. For a small team without cloud operations experience, the same billing model can be difficult to estimate. VPS pricing is usually easier when the team wants to know the monthly cost before launching. AWS EC2 pricing is usually stronger when the team has the skill and time to model usage, optimize commitments, and manage supporting services. For broader budgeting, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). ## Storage, Bandwidth, and IPs Change the Real Cost The visible instance price is not always the full server cost. This matters especially when comparing VPS hosting with AWS EC2. With many VPS platforms, storage and bandwidth are bundled into the plan. The exact policy depends on the provider, but the buyer is often comparing complete server plans. With EC2, compute, storage, transfer, and network architecture are more modular. That modularity is powerful, but it also makes cost modeling more detailed. ### Storage A VPS plan may include a specific amount of storage in the monthly price. EC2 instances often use EBS volumes for persistent block storage. EBS is flexible, but storage size, volume type, snapshots, and data lifecycle decisions should be planned separately. For small teams, this means EC2 storage can be more customizable but also more complex to estimate. ### Bandwidth Bandwidth can change the real cost of infrastructure. A simple VPS with clear or unmetered bandwidth can be easier to budget. AWS data transfer pricing depends on traffic direction, region, services, and architecture. For public websites, APIs, dashboards, downloads, and SaaS applications, data transfer should be part of the decision. ### IP addresses A VPS plan often includes a public IP address. In cloud platforms, public IP and Elastic IP behavior may depend on configuration and usage. The details matter because small networking decisions can affect billing and operations. The pricing lesson is simple: compare the full workload, not only the base compute line. ## Networking and Security Are Simpler on VPS, Deeper on AWS VPS hosting usually gives you a simpler access model. You deploy the server, connect over SSH or RDP, configure firewall rules, and manage the operating system. For many small teams, that is enough. AWS EC2 has a deeper security and networking model. An EC2 deployment may involve: * AWS accounts * IAM users and roles * Instance profiles * Security groups * Key pairs * VPCs * Public and private subnets * Route tables * Internet gateways * NAT gateways * Network ACLs * CloudTrail * CloudWatch * Secrets management * Multi-account governance This depth is useful when a team needs precise control. It also increases the knowledge required to deploy safely. A small team should not choose EC2 only because it is powerful. It should choose EC2 when that power is needed and someone on the team can operate it responsibly. A VPS is usually better when the team needs secure server access without designing a complete cloud network first. For basic server security planning, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ## Developer Workflow Differences Developers often choose infrastructure based on how quickly they can turn an idea into a working environment. VPS hosting supports simple developer workflows: * Deploy a VM * SSH or RDP into the server * Install packages * Run Docker * Deploy an app * Host an API * Test a database * Create a staging environment * Run an automation job * Share a remote environment with a team This workflow is straightforward and often enough for early products, freelance projects, internal tools, demos, and small production apps. AWS EC2 supports a broader cloud workflow: * Define VPC and network access * Choose instance type and AMI * Configure IAM roles * Attach EBS volumes * Set up security groups * Configure logging and monitoring * Integrate with S3, RDS, CloudWatch, Route 53, or other services * Automate with Terraform, CloudFormation, or CI/CD pipelines * Design scaling and failover patterns That workflow is more powerful, but it asks more from the team. For developer and DevOps-specific VPS planning, read [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers). ## Migration and Growth Considerations A common mistake is assuming every small project should start on the largest possible cloud platform. Sometimes that is true. Many teams choose AWS early because they expect complex scale, enterprise customers, AWS-native integrations, or compliance requirements. But many projects do not need that on day one. A small SaaS product, internal dashboard, staging environment, API, Docker workload, or business tool may run well on a VPS for months or years. The team can move to a larger cloud architecture later if the workload proves it needs autoscaling, managed services, global redundancy, or advanced governance. The reverse can also be true. If a team already knows it needs AWS-native services, large-scale automation, managed databases, S3-heavy storage, event-driven architecture, or enterprise compliance, starting with AWS EC2 may avoid a later migration. The decision should follow expected architecture, not brand recognition. Ask these questions: | Question | VPS path | AWS EC2 path | | --------------------------------------------------- | ------------- | ---------------------------------- | | Do we need one or a few servers? | Strong fit | Possible but may be more complex | | Do we need AWS-native services now? | Usually no | Strong fit | | Do we need autoscaling from day one? | Usually no | Strong fit | | Do we need predictable monthly cost? | Strong fit | Requires modeling | | Do we have cloud operations experience? | Less required | More important | | Will the app need enterprise cloud governance soon? | Usually no | Strong fit | | Can we migrate later if needed? | Often yes | Less concern if already AWS-native | The best infrastructure path is the one that fits the current workload while keeping a practical path for the next stage. ## Raff VM in the VPS vs AWS EC2 Decision Raff VM fits the VPS and cloud VM side of this decision. The product direction is simple: many developers, founders, and small teams need cloud compute without starting inside a complex hyperscaler environment. They want a virtual machine that is fast to deploy, easy to understand, predictable to price, and capable enough for real workloads. Raff VM supports VPS and cloud VM workloads with AMD EPYC processors, NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and Linux or Windows VM options. Plans start from $4.99/month for entry-level workloads. This makes Raff VM a fit when your decision framework points toward: * Simple VPS or cloud VM infrastructure * Predictable monthly pricing * Fast deployment * Developer environments * Web applications * APIs * Docker workloads * Staging servers * Databases * Windows remote desktop * Small business tools * Less complexity than AWS EC2 The first-hand product decision is intentional. Raff is not trying to replace every AWS architecture. AWS remains a powerful platform for complex cloud systems. Raff focuses on the many cases where a small team needs dependable compute without turning a server deployment into a full cloud architecture project. If the workload needs one or a few clear virtual servers, Raff VM can be the simpler path. If the workload needs AWS-native services, complex networking, autoscaling, and enterprise governance, AWS EC2 may be the better foundation. ## Common Mistakes When Comparing VPS and AWS EC2 The biggest mistake is treating VPS hosting and AWS EC2 as if they are only two ways to rent a server. They can both run virtual machines, but they solve different infrastructure problems. VPS hosting is usually a server-first model: simple deployment, predictable pricing, and fewer platform decisions. AWS EC2 is part of a broader cloud platform: more flexible, more powerful, and more complex when used properly. If you are still defining the broader VPS model, start with the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If the main question is pricing, compare this section with [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). | Mistake | Why it happens | What it can cause | | ------------------------------------------------------------ | ------------------------------------------------------------------ | --------------------------------------------------------------------- | | Comparing only the server price | Teams compare the VPS plan against the EC2 instance line item | Missing storage, transfer, IP, monitoring, support, and service costs | | Choosing AWS only because it is bigger | AWS feels like the “serious” default | Extra complexity before the workload needs it | | Choosing VPS when the workload needs AWS-native architecture | The team wants simplicity even though the system needs cloud depth | Rebuilding later for IAM, VPC, autoscaling, or managed services | | Ignoring team skill level | Infrastructure is chosen without considering who will operate it | Security gaps, billing surprises, and slow troubleshooting | | Forgetting storage and transfer design | Compute looks like the main cost | Underestimated data transfer, EBS, snapshots, backups, and monitoring | | Overbuilding before usage is real | The team designs for scale before proving demand | Higher cost, slower delivery, and unnecessary operational burden | | Underplanning migration paths | The first choice is treated as permanent | Harder transition when the workload grows or changes | ### Comparing only the server price The EC2 instance price is not always the full workload price. An EC2-based setup may also involve EBS volumes, snapshots, data transfer, Elastic IP behavior, monitoring, load balancers, NAT gateways, managed databases, support, and other AWS services. Those pieces may be useful, but they make the real cost broader than the instance itself. A VPS plan is often easier to understand because compute, storage, bandwidth policy, and public access are usually packaged more directly. The better comparison is not “which server is cheaper?” It is “which model gives this workload the safest total cost and operational fit?” For more budget planning, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). ### Choosing AWS only because it is bigger AWS is powerful, but power does not automatically mean fit. A small team running one website, API, dashboard, Docker stack, staging server, or business tool may move faster with VPS hosting because there are fewer architecture decisions before deployment. AWS EC2 becomes stronger when the team needs platform depth: IAM, VPC design, autoscaling, AWS-native storage, managed databases, monitoring, event-driven services, or enterprise governance. A practical rule: choose AWS because the workload needs AWS architecture, not because AWS is the biggest brand in cloud. ### Choosing VPS when the workload needs cloud architecture VPS hosting is not the right answer for every system. If the workload needs autoscaling, private subnets, load balancers, IAM roles, multi-account governance, AWS-native integrations, managed databases, or large-scale automation, EC2 may be a better starting point. A VPS is strongest when the system can be run as one or a few clear virtual servers. EC2 is strongest when compute is only one part of a larger cloud architecture. For a broader look at simple VPS infrastructure versus modern cloud VPS models, read [Cloud VPS vs Traditional VPS](/learn/guides/cloud-vps-vs-traditional-vps). ### Ignoring team skill level Infrastructure should match the team’s ability to operate it. A solo founder, freelancer, student, agency, or small team may not have time to manage IAM, VPC design, security groups, EBS planning, CloudWatch alarms, transfer costs, and service integrations. In that case, VPS simplicity can be a strategic advantage. A team with AWS experience may benefit from EC2 because they can use the platform depth responsibly. The question is not only “what can this platform do?” It is also “can our team secure, monitor, troubleshoot, and explain this setup?” For developer-focused VPS planning, read [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers). ### Forgetting data transfer and storage design Compute is only one part of the comparison. A small VPS plan may include storage and a clearer bandwidth model. EC2 separates more infrastructure pieces, which gives flexibility but also requires better planning. Storage decisions may include EBS volume type, size, snapshots, backup retention, and performance needs. Data transfer decisions may depend on traffic direction, architecture, region, public access, and service relationships. This matters for public websites, APIs, dashboards, backups, downloads, object storage, logs, and monitoring data. If the workload has meaningful traffic or important data, storage and transfer should be evaluated before choosing the platform. ### Overbuilding before usage is real Some projects begin with complex architecture before they have users. That can slow down delivery. A simple VPS can often support an early app, API, staging environment, internal tool, or MVP while the team learns what the workload actually needs. This does not mean teams should ignore future scale. It means they should match complexity to evidence. Start simple when the workload is still proving itself. Add AWS-style platform depth when the workload earns it. ### Treating the first infrastructure choice as permanent The first infrastructure decision does not need to last forever. A small project can start on VPS hosting and later migrate to AWS if it needs managed services, autoscaling, global architecture, or deeper AWS integrations. An AWS-native product can start on EC2 if those needs are already obvious. The important thing is to choose a path that does not trap the workload. For sizing decisions before deployment, read [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). For security fundamentals after choosing a server path, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ## Best Practices for Choosing Between VPS and AWS EC2 The best choice depends on workload shape, team skill, cost tolerance, and how much cloud architecture the system actually needs. Use this decision model before choosing a path: | Decision area | Choose VPS when... | Choose AWS EC2 when... | | ------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------ | | Workload shape | One app, API, database, staging server, or small stack is enough | The system needs multiple AWS services or distributed architecture | | Team capacity | The team wants fewer infrastructure decisions | The team has AWS or DevOps experience | | Cost planning | Predictable monthly server pricing matters | Usage-based billing can be modeled and optimized | | Networking | Public access and basic firewalling are enough | VPCs, private subnets, routing, and cloud network design matter | | Scaling | Manual resizing or a larger plan is enough | Autoscaling, load balancers, and fleet design matter | | Storage | Included VM storage or simple attached storage is enough | EBS, snapshots, lifecycle policies, and managed storage are needed | | Security model | Server-level access control is enough | IAM roles, account governance, and service permissions matter | | Long-term direction | The workload may stay simple | The workload is clearly AWS-native | ### Start with workload shape A simple website, API, staging server, Docker stack, database VM, or internal business app may not need full AWS architecture. A distributed application, enterprise platform, AWS-native system, or multi-service cloud product might. Start by defining what the workload needs in the next 3–12 months, not what it might theoretically need one day. ### Estimate the full monthly cost Compare the total workload, not only the base server. For VPS hosting, check CPU, RAM, storage, bandwidth policy, backups, snapshots, operating system options, and support. For EC2, include instance runtime, EBS volumes, snapshots, data transfer, Elastic IP behavior, monitoring, load balancers, NAT gateways, managed services, and support. For small teams, predictable pricing can be more valuable than flexibility that nobody has time to optimize. ### Match complexity to the team Small teams should avoid infrastructure that nobody can confidently operate. The right platform is the one your team can secure, monitor, troubleshoot, document, and explain. A simple setup that your team understands is often safer than a powerful setup nobody fully owns. If the team already has AWS experience, EC2 can be a strong choice. If not, VPS hosting may help the team launch faster and reduce operational friction. ### Choose VPS for clarity when possible Choose VPS hosting when the workload needs a dependable virtual server, root or administrator access, Linux or Windows options, predictable pricing, and less platform complexity. This is especially useful for founders, freelancers, agencies, students, developers, and small teams building apps, APIs, staging servers, Docker workloads, dashboards, or business tools. For the broader VPS path, read the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). ### Choose EC2 when platform depth matters Choose AWS EC2 when the workload clearly needs AWS integrations, IAM, VPC design, autoscaling, load balancing, managed databases, monitoring, infrastructure as code, or enterprise cloud governance. EC2 is strongest when compute is one part of a larger AWS system. If those platform features are required, the extra complexity is not waste. It is part of the architecture. ### Avoid building for imaginary scale Many small projects do not fail because the first server was too simple. They fail because the team spends too much time on infrastructure before proving the workload. If the product is still early, a simple VPS can be the fastest way to validate the application, understand traffic, and learn real resource needs. Scale the architecture when usage patterns justify it. ### Leave a migration path The first infrastructure choice should support the next stage, not trap the project. A VPS-first project can later move toward AWS if it needs managed services, autoscaling, advanced networking, or enterprise architecture. An EC2-first project can stay in AWS if those needs are clear from the beginning. The best decision is the one that fits today’s workload while keeping tomorrow’s options open. ## Choosing the Right Infrastructure Path VPS hosting and AWS EC2 can both run serious workloads. The better choice depends on the level of infrastructure the team actually needs. Choose VPS hosting when the workload needs a dependable virtual server, predictable pricing, fast deployment, Linux or Windows options, and less cloud platform complexity. Choose AWS EC2 when the workload needs deep AWS integration, autoscaling, advanced networking, IAM, managed services, or enterprise-scale architecture. For the broader VPS decision, start with the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If your workload fits the VPS or cloud VM path, Raff VM gives you a simple way to deploy cloud infrastructure with predictable monthly pricing, NVMe SSD storage, unmetered bandwidth, and Linux or Windows server options. [Explore Raff VM](/products/raff-vm) --- ### VPS for Web Hosting: What Small Teams Should Know URL: https://rafftechnologies.com/learn/guides/vps-for-web-hosting Description: Learn when VPS web hosting makes sense for small teams, with a decision framework for shared hosting, VPS hosting, managed hosting, cloud VMs, performance, security, and cost. VPS web hosting is a hosting model where a website runs on a virtual private server with isolated CPU, RAM, storage, networking, and operating system control. For small teams, VPS hosting sits between shared hosting and full cloud architecture. It gives more control than a shared hosting plan, but it does not require the same platform design work as a hyperscaler setup. That makes it useful for websites, WordPress projects, APIs, staging environments, small business sites, and web applications that need better performance and flexibility. This guide is part of the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting) cluster and explains when VPS web hosting makes sense, when shared hosting is still enough, and how small teams should compare cost, performance, security, and operational effort. ## VPS Web Hosting Explained VPS web hosting means using a virtual private server to host a website or web application. ![Diagram showing a VPS web hosting stack with web server, database, application runtime, SSL, files, caching, and monitoring.](https://raff-images.s3.raffusercloud.com/website_stack_on_vps_webp_8532ea3022.png) Instead of sharing one hosting environment with many unrelated websites, your team gets its own virtual server. That server can run a web server, database, application runtime, caching layer, background workers, SSL certificates, monitoring tools, and other software needed by the website. A VPS can host different types of web workloads: * Business websites * WordPress sites * PHP applications * Node.js applications * Static websites * Landing pages * Portfolio sites * Client websites * Internal dashboards * APIs * Staging environments * Small SaaS applications * E-commerce experiments * Web apps with databases The main benefit is control. With VPS hosting, you can usually choose the operating system, install packages, configure the web server, manage the database, control security rules, and tune the environment for the workload. That control is valuable when a website needs more than a basic shared hosting plan can provide. ## VPS Hosting Is Not Always the First Web Hosting Choice A VPS is powerful, but it is not automatically the right starting point for every website. A simple brochure website, personal blog, or small static site may not need a VPS. Shared hosting, managed WordPress hosting, or static site platforms can be enough when the site has low traffic, minimal customization, and no complex backend requirements. The decision changes when the website becomes more important. A VPS becomes more attractive when the site needs custom software, predictable resources, better performance control, direct server access, staging environments, database control, private services, or more flexible deployment options. The goal is not to choose the most powerful hosting model. The goal is to choose the smallest hosting model that can safely run the website. For a wider comparison of hosting models, read the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). ## The VPS Web Hosting Decision Framework Use this framework before choosing a VPS for web hosting. ![Decision matrix comparing shared hosting and VPS web hosting by website type, control, performance, software stack, database, security, growth, and team skill.](https://raff-images.s3.raffusercloud.com/vps_web_hosting_decision_matrix_webp_60c5ec2ba5.png) | Decision factor | Shared hosting may be enough when... | VPS web hosting is better when... | | --------------- | ----------------------------------------------------- | --------------------------------------------------------------------- | | Website type | Simple brochure site, basic blog, or low-traffic page | Dynamic website, app, API, dashboard, or database-backed site | | Control | You do not need server-level access | You need root access, custom packages, or server configuration | | Performance | Traffic is low and performance needs are basic | You need more predictable CPU, RAM, storage, or caching control | | Software stack | Standard PHP or CMS setup is enough | You need Node.js, Docker, custom runtimes, queues, or background jobs | | Database | Basic shared database is enough | You need database tuning, dedicated resources, or direct access | | Security | Basic hosting controls are enough | You need firewall rules, user management, hardening, and isolation | | Growth | The site is unlikely to change much | The site may grow into an app, API, or multi-service stack | | Team skill | Nobody wants to manage a server | The team can manage Linux, Windows, security, backups, and updates | Choose shared hosting when the website is simple and the team does not want to manage infrastructure. Choose VPS hosting when the website needs more control, more flexibility, or a stronger foundation for growth. ## When Shared Hosting Is Still Enough Shared hosting can still be a good choice for simple websites. It is usually enough when the website is small, mostly static, and does not need custom server configuration. A local business website, portfolio, landing page, personal blog, or basic marketing site can run well on shared hosting if traffic is modest and the software stack is standard. Shared hosting is also useful when the team wants the least operational responsibility. The provider manages much of the hosting environment, and the user mainly uploads content or manages the CMS. Shared hosting may be enough when: * The website is simple * Traffic is low * Custom software is not required * Server access is not important * Performance requirements are modest * The team does not want to manage updates or server security * The site can live inside a standard hosting control panel The trade-off is limited control. If the website starts needing custom packages, higher performance consistency, staging environments, background jobs, API services, or database control, shared hosting may become restrictive. ## When VPS Web Hosting Makes More Sense VPS web hosting makes more sense when the website becomes closer to an application. This can happen with WordPress sites, custom PHP apps, Node.js apps, Laravel projects, Django apps, Next.js applications, APIs, dashboards, client portals, e-commerce experiments, or internal business tools. A VPS gives the team control over the server environment. That means you can install the software you need, configure the web server, manage SSL, run databases, set up caching, tune memory, and create separate staging or production environments. A VPS is usually a better fit when: * The website needs root or administrator access * The site runs custom software * The team needs SSH or RDP access * Performance is important * The website includes an API * The website uses a database heavily * The site needs a staging environment * The project uses Docker or background workers * The team wants predictable monthly infrastructure cost * The website may grow into a larger application For developer-focused workloads, read [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers). ## VPS for WordPress, PHP, Node.js, and Static Sites Different website types place different pressure on a VPS. A small static site may need very little server power. A WordPress site with plugins, database activity, admin traffic, backups, and media uploads may need more memory and storage performance. A Node.js app may need process management, reverse proxy configuration, logs, and background services. The workload matters more than the word “website.” | Website workload | VPS fit | Main thing to watch | | ------------------- | --------------------------------- | --------------------------------------------------- | | Static website | Often lightweight | Web server setup, SSL, caching, bandwidth | | WordPress website | Strong fit when control is needed | RAM, database performance, backups, updates | | PHP application | Strong fit | Web server, PHP version, database, file permissions | | Node.js application | Strong fit | Process management, reverse proxy, logs, memory | | API backend | Strong fit | CPU, RAM, latency, database, monitoring | | E-commerce site | Possible, but needs care | Security, backups, database, uptime, payments | | Client sites | Strong fit for agencies | Isolation, backups, access control, staging | | Internal dashboard | Strong fit | Access security, database, uptime, user permissions | A VPS gives flexibility across these website types, but flexibility also means responsibility. The team should plan updates, backups, firewall rules, SSL renewal, monitoring, and recovery before treating the VPS as production infrastructure. ## VPS vs Managed Hosting for Websites Managed hosting and VPS hosting solve different problems. Managed hosting is usually better when the team wants someone else to handle most infrastructure details. Managed WordPress hosting, for example, may include updates, caching, backups, security features, support, and performance tuning for WordPress specifically. VPS hosting is better when the team wants more control over the server. | Hosting model | Best for | Main trade-off | | ------------------- | ------------------------------------------------- | -------------------------------------------------------- | | Managed hosting | Teams that want less infrastructure work | Less flexibility and sometimes higher cost | | VPS hosting | Teams that want control and predictable resources | More responsibility for setup, security, and maintenance | | Shared hosting | Simple websites with low complexity | Limited control and resource isolation | | Full cloud platform | Complex applications and cloud-native systems | More billing, networking, and architecture complexity | Managed hosting can be the right choice for non-technical website owners. VPS hosting is usually better for developers, agencies, founders, and small teams that want control over the stack and are comfortable managing a server. For the difference between cloud VPS and older VPS models, read [Cloud VPS vs Traditional VPS](/learn/guides/cloud-vps-vs-traditional-vps). ## Sizing a VPS for Web Hosting The right VPS size depends on traffic, software stack, database usage, plugins, background jobs, caching, and the number of sites running on the server. ![Visual guide showing VPS sizing considerations for static sites, WordPress, business websites, Node.js apps, databases, and production web applications.](https://raff-images.s3.raffusercloud.com/vps_web_hosting_sizing_guide_webp_92e8662c19.png) A small website may start with a modest plan. A dynamic website, WordPress site, or app with database activity usually needs more headroom. | Web hosting scenario | Typical starting point | Notes | | ------------------------------ | -------------------------- | ------------------------------------------------- | | Static website or landing page | Small CPU and RAM plan | Usually light unless traffic is high | | Small WordPress site | 1–2 vCPU and 1–2 GB RAM | More plugins and traffic may need more RAM | | Business website with CMS | 2 vCPU and 2–4 GB RAM | Good for stronger admin and database performance | | Node.js or PHP app | 2+ vCPU and 2–4 GB RAM | Depends on runtime, database, and background jobs | | Website plus database | More RAM and fast storage | Database performance often becomes the limit | | Multiple client websites | More CPU, RAM, and storage | Isolation and backups become important | | Production web app | Size from real usage | Monitor CPU, RAM, disk, network, and latency | Avoid choosing the smallest plan only because it is cheaper. A VPS that is too small may create slow page loads, failed updates, database instability, crashes, swap usage, and poor admin performance. Starting modestly is smart, but the plan should leave enough room for normal website activity. For more detailed sizing guidance, read [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). ## Performance Factors That Matter for VPS Web Hosting Website performance depends on more than the VPS plan name. CPU, RAM, storage type, network speed, web server configuration, caching, database behavior, image size, application code, and traffic patterns all affect the result. The most important VPS performance factors are: | Factor | Why it matters for websites | | ------------------ | ---------------------------------------------------------------------------------------- | | CPU | Handles application logic, PHP, Node.js, web requests, compression, and background tasks | | RAM | Supports the operating system, web server, database, cache, and app runtime | | NVMe SSD storage | Improves database activity, file access, logs, package installs, and responsiveness | | Bandwidth | Affects public traffic, media delivery, downloads, and predictable cost | | Network port speed | Helps with transfer capacity and responsiveness under load | | Caching | Reduces repeated processing and database load | | Database tuning | Often determines dynamic website performance | | Web server setup | Nginx, Apache, reverse proxies, SSL, and compression all matter | | Monitoring | Helps identify pressure before users complain | A fast VPS does not replace good website optimization. Large images, heavy plugins, inefficient database queries, and poor caching can make any server feel slow. But a weak server can limit even a well-built website. The best approach is to combine a properly sized VPS with basic website optimization and monitoring. ## Security and Backups for VPS Web Hosting A VPS gives more control than shared hosting, but that also means more responsibility. For production web hosting, security and backups should not be treated as optional. A website may contain customer data, business content, admin credentials, forms, user accounts, configuration files, and database records. Important VPS web hosting security practices include: * Use SSH keys where possible * Keep the operating system updated * Keep the web server updated * Keep CMS software and plugins updated * Configure firewall rules * Use HTTPS with SSL certificates * Limit admin access * Disable unnecessary services * Use strong passwords and access controls * Monitor logs * Create backups * Test recovery before an emergency Backups matter most when the website stores data that cannot be easily recreated. A static site may be rebuilt from a repository. A WordPress site, database-backed app, or business dashboard may need regular database and file backups. For a broader security foundation, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ## Cost Factors for VPS Web Hosting VPS web hosting cost is not only the server price. The real monthly cost may include compute, storage, bandwidth, backups, snapshots, operating system requirements, monitoring, domains, SSL management, email services, support, and the time needed to manage the server. For small teams, predictable cost is often one of the main reasons to choose VPS hosting. A VPS can be more transparent than large cloud platforms when the website needs one or a few servers. Instead of estimating many separate services, the team can often start with a clear monthly plan and add backups or upgrades as needed. Still, the cheapest VPS is not always the best value. A very low-cost plan may become expensive if it causes slow performance, downtime, migrations, support issues, or lost time. For a full budgeting view, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). ## Raff VM for VPS Web Hosting Raff VM fits the VPS web hosting path for small teams that want more control than shared hosting without starting inside a complex hyperscaler setup. Many website projects do not need a full cloud architecture on day one. They need a fast virtual server, predictable pricing, strong storage, clear bandwidth, and the flexibility to run the web stack their project requires. Raff VM supports web hosting workloads with AMD EPYC processors, NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and Linux or Windows VM options. Plans start from $4.99/month for entry-level workloads. That makes Raff VM relevant for small business websites, WordPress projects, PHP applications, Node.js apps, APIs, staging servers, internal dashboards, agency projects, and developer-managed websites. The practical advantage is simplicity. A team can deploy a VM, choose an operating system, configure the web stack, connect over SSH or RDP, and run the workload without designing a full cloud account, complex network architecture, or unpredictable billing model first. Raff is not a managed WordPress host and not a replacement for every enterprise cloud architecture. It is a cloud VM platform for teams that want VPS-style control, fast deployment, predictable pricing, and infrastructure that can support real web workloads as they grow. ## Common Mistakes When Choosing VPS for Web Hosting Most VPS web hosting mistakes happen before the server is deployed. The problem is usually not that VPS hosting is too difficult or too expensive. The problem is that the team chooses a server without clearly defining the website type, software stack, traffic pattern, database needs, backup strategy, and who will maintain the environment after launch. A VPS gives more control than shared hosting, but that control only helps when the team uses it intentionally. For the broader server decision, read the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). For sizing and budget planning, compare this section with [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size) and [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). | Mistake | What it looks like | Why it becomes a problem | | -------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------- | | Choosing VPS before defining responsibility | The team wants more power but has no server maintenance plan | Updates, security, backups, and monitoring are ignored | | Buying the smallest plan by default | The plan fits the budget, but not the workload | WordPress, databases, plugins, and traffic quickly create pressure | | Treating backups as an optional add-on | Backups are delayed until the site becomes important | Recovery is difficult after content, forms, orders, or data accumulate | | Treating dynamic websites like static pages | WordPress or CMS sites are sized like simple landing pages | Database activity, admin traffic, and plugins consume more resources | | Hosting too many sites on one small VPS | Multiple websites share one weak environment | One busy or compromised site can affect the rest | | Ignoring operational maintenance | The VPS is deployed and then forgotten | Security patches, logs, SSL, and uptime issues accumulate | | Planning only for the first version of the website | A landing page later becomes an app, API, or portal | The team needs an urgent migration instead of a controlled upgrade | ### Choosing VPS before defining operational responsibility A VPS is not only a hosting product. It is also an operational responsibility. With shared hosting, many server-level decisions are handled by the provider. With VPS hosting, the team has more control over the operating system, web server, database, firewall, SSL, packages, updates, backups, and monitoring. That control is valuable when the team needs it. It becomes a liability when nobody owns it. Before choosing VPS hosting, define who will manage: * Operating system updates * Web server configuration * Firewall rules * SSL certificates * Database updates * Backups * Monitoring * Log review * Recovery after failure A VPS is a strong fit when the team wants server-level control and has someone who can manage the environment. If nobody wants that responsibility, managed hosting may be the better choice. ### Buying the smallest plan without matching the workload Starting small is sensible. Starting too small is expensive in a different way. The smallest VPS plan may work for a static site, landing page, or lightweight test project. It may not work well for a WordPress site with plugins, a PHP application, a Node.js app, a database-backed website, or multiple client sites. The real question is not “what is the cheapest VPS?” It is “what is the smallest VPS that can run this website safely?” A web hosting VPS should leave room for: * The operating system * Web server processes * Database activity * PHP, Node.js, or application runtime * Admin activity * Backups * Updates * Logs * Traffic spikes * Security tools * Future website changes If the server is too small, the symptoms may look like website problems: slow admin panels, failed plugin updates, database timeouts, random crashes, high swap usage, or inconsistent page speed. For practical sizing decisions, use [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). ### Treating backups as something to add later Many websites begin as simple projects and become important gradually. A landing page gains form submissions. A WordPress site gains months of content. A small store gains orders. A client demo becomes a production portal. A dashboard becomes part of daily business operations. If backups are not planned early, the website can quietly become business-critical without a recovery path. For VPS web hosting, backups should match the value of the website: | Website type | Backup priority | | ----------------------------- | ---------------------------------------------------------------- | | Static site deployed from Git | Lower, because the source can usually be redeployed | | WordPress site | High, because files, media, plugins, and database content change | | Business website with forms | High, especially if submissions are stored | | E-commerce site | Very high, because orders and customer data matter | | Client website | High, because reputation and delivery obligations matter | | Internal dashboard | Depends on whether business data is stored | | Database-backed web app | Very high, because application state is difficult to recreate | A VPS for production web hosting should not be judged only by CPU and RAM. It should also be judged by how easily the site can be restored. For a wider security and recovery foundation, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ### Treating WordPress like a static website WordPress is often described as “just a website,” but operationally it behaves like a dynamic application. A WordPress VPS may need to handle PHP execution, database queries, plugin activity, media uploads, scheduled tasks, admin sessions, cache generation, backups, security scans, and frequent updates. That means a WordPress site can place more pressure on RAM, CPU, and storage than a simple static page. This is especially true when the site uses: * Page builders * E-commerce plugins * Membership plugins * Security plugins * Backup plugins * Heavy themes * Large media libraries * High admin activity * Frequent content updates * Multiple user roles A WordPress site can run very well on a VPS, but it should be sized and maintained like dynamic software, not like a brochure page. ### Consolidating too many websites on one small VPS Putting multiple websites on one VPS can be efficient for agencies, freelancers, and small teams. It can also concentrate risk. When several websites share the same small server, they also share CPU, RAM, disk I/O, bandwidth, security exposure, and maintenance windows. If one website becomes busy, misconfigured, or compromised, the others may be affected. This does not mean every website needs a separate VPS. It means the consolidation model should be intentional. Before hosting multiple sites on one VPS, decide: * How many sites will run on the server * Whether each site needs its own user or container * How backups will be separated * How logs will be reviewed * How SSL certificates will be managed * How resource usage will be monitored * What happens if one site is compromised * When a site should be moved to its own server For agencies and developer teams, VPS consolidation can be practical, but it should not be treated as unlimited shared hosting. ### Ignoring storage performance Website owners often compare storage by capacity only. For active websites, storage speed also matters. NVMe SSD storage can improve responsiveness for database queries, CMS admin panels, plugin updates, package installs, log writes, file uploads, cache generation, and application deployments. This matters most for dynamic websites, WordPress, PHP applications, Node.js apps, databases, and web applications with frequent reads and writes. A plan with more unused storage is not always better than a plan with faster storage and enough capacity for the actual workload. For cost and storage trade-offs, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). ### Forgetting that web hosting has a lifecycle A website is not finished when it launches. After launch, the workload changes. Traffic grows or falls. Plugins are added. Content expands. Databases grow. Logs accumulate. Backups consume storage. Security updates arrive. New pages, APIs, forms, dashboards, and integrations appear. A VPS should be reviewed after real usage begins. The review should include: * CPU usage * RAM usage * Disk usage * Disk I/O * Network traffic * Page speed * Database behavior * Error logs * Backup success * SSL status * Uptime * Admin performance The right VPS plan is not fixed forever. It should evolve with the website. ## Best Practices for VPS Web Hosting A good VPS web hosting decision starts with the website’s operating model, not the server plan. The goal is to choose infrastructure that matches the website’s current needs, supports the next stage of growth, and remains simple enough for the team to operate confidently. Use this model before choosing a VPS: | Decision area | Ask this question | Why it matters | | ------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | Website type | Is this static, CMS-based, application-based, or database-backed? | Different website types create different server pressure | | Stack complexity | Does the site need PHP, Node.js, Docker, database, cache, or background jobs? | The stack determines CPU, RAM, storage, and maintenance needs | | Business importance | What happens if the site is slow or offline? | Production and revenue-facing sites need stronger reliability planning | | Data value | Does the site store content, users, orders, forms, or application state? | Data determines backup and recovery requirements | | Team skill | Who will manage updates, security, logs, and troubleshooting? | VPS hosting requires operational ownership | | Growth path | Could this become an app, API, portal, or multi-site environment? | The hosting model should avoid urgent migration later | ### Build a workload profile before choosing the VPS Start by describing the website as a workload. A useful workload profile includes: * Website type * Expected traffic * CMS or framework * Database requirements * Runtime requirements * Storage needs * Backup needs * Security requirements * Number of admins * Number of websites * Expected growth over the next 3–12 months This prevents the team from choosing a VPS based only on price or plan names. A static landing page, WordPress site, Laravel application, Node.js app, API backend, and client portal should not all use the same hosting decision model. ### Choose VPS only when the website benefits from control VPS hosting is best when control creates real value. Choose VPS web hosting when the website needs: * Root or administrator access * Custom packages * Nginx or Apache configuration * PHP, Node.js, Python, or custom runtime support * Database control * SSH or RDP access * Docker or background services * Staging and production environments * Predictable resources * Better isolation than shared hosting * Room to grow into a larger web application Do not choose VPS only because it sounds more advanced. If the website is simple and the team does not want server responsibility, shared hosting or managed hosting may still be the cleaner option. ### Design the web stack before deployment A VPS plan should be chosen after the web stack is understood. At minimum, define whether the site will need: * Linux or Windows * Nginx or Apache * PHP, Node.js, Python, or another runtime * MySQL, PostgreSQL, or another database * Redis or another cache layer * Docker * SSL certificates * File uploads * Email handling * Backups * Monitoring * CDN or external storage This matters because every component consumes resources. A VPS that looks large enough for a basic website may be too small once the database, runtime, cache, backups, logs, and updates are included. For developer-oriented web stacks, read [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers). ### Keep production and experimentation separate when risk increases Early projects often combine everything on one server. That can be acceptable at the beginning. Over time, the team should separate workloads when risk increases. A production website should not always share the same environment as experiments, test scripts, unfinished apps, or unstable side projects. The more important the website becomes, the more carefully the environment should be protected. Separation may mean: * A separate staging site * A separate database server * Separate users or containers * Separate backups * Separate VPS instances for important sites * A cleaner deployment process * A stricter firewall and access model The goal is not to over-engineer. The goal is to prevent one risky workload from damaging an important one. ### Size for normal pressure, not perfect conditions A VPS should not be sized only for the quietest moment of the day. Real websites have updates, crawlers, traffic spikes, admin sessions, backups, form submissions, scheduled jobs, and occasional inefficient requests. Dynamic sites also need room for database activity and cache rebuilding. A stable VPS web hosting setup should leave headroom for normal pressure. For many small websites, this means avoiding the absolute smallest plan once the site becomes dynamic, public, or business-relevant. Monitor real usage and resize before the server becomes fragile. ### Treat storage as a performance factor Storage is not only where files live. For web hosting, storage affects: * Database responsiveness * CMS admin performance * Plugin and package installs * Media uploads * Log writing * Cache files * Docker layers * Backup creation * Application deployment For static websites, storage performance may be less important. For WordPress, databases, dashboards, APIs, and web applications, faster storage can directly affect the user and admin experience. NVMe SSD storage is especially useful when the site is active, database-backed, or frequently updated. ### Make backups part of the hosting model A production website should have a recovery model before it needs one. Backups should cover the parts of the site that are hard to recreate: * Database * Uploaded files * Website files * Configuration files * SSL and deployment notes * Application state * CMS content * Customer or form data A backup is only useful if it can be restored. Small teams should periodically confirm that backups exist, are recent, and can be used in a real recovery scenario. ### Secure the server before traffic arrives A VPS connected to the public internet should be treated as production infrastructure. Before launch, the team should review: * SSH or RDP access * Firewall rules * User permissions * OS updates * Web server updates * CMS and plugin updates * SSL certificates * Database exposure * Admin URLs * Logs * Monitoring * Backup access Security is easier to build into the VPS early than to repair after the site is already public. For the broader checklist, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ### Review the hosting plan after launch The first VPS choice is an estimate. Real usage gives better evidence. After launch, review performance and resource usage regularly. Look for patterns, not only emergencies. Useful signals include: * Slow page loads * High RAM usage * Swap usage * CPU spikes * Database slowdowns * Failed backups * Growing logs * SSL renewal issues * Unusual traffic * Increasing storage usage * Admin panel slowness * Application errors Resize or adjust the stack before these signals become outages. A good VPS web hosting setup should remain understandable, maintainable, and ready for the next stage of the website. ## Choosing the Right Web Hosting Path VPS web hosting is strongest when a website needs more control, flexibility, and performance ownership than shared hosting can provide. It is useful for dynamic websites, WordPress, PHP applications, Node.js apps, APIs, staging environments, and small business tools that need room to grow. Shared hosting can still be enough for simple sites. Managed hosting can be better when the team wants less operational responsibility. Full cloud platforms can be better when the website belongs inside a larger cloud architecture. For the broader decision, start with the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If your website fits the VPS path, Raff VM gives you a simple way to deploy cloud infrastructure with predictable monthly pricing, NVMe SSD storage, unmetered bandwidth, and Linux or Windows server options. [Explore Raff VM](/products/raff-vm) --- ### VPS for Docker Containers: What Developers Should Know URL: https://rafftechnologies.com/learn/guides/vps-for-docker-containers Description: Learn when running Docker containers on a VPS makes sense, with a decision framework for Docker Compose, Kubernetes, storage, networking, security, backups, and cost. Docker VPS hosting is a deployment model where Docker containers run on a virtual private server with isolated CPU, RAM, storage, networking, and operating system control. For developers and small teams, this can be a practical middle ground between manual server setup and larger container platforms like Kubernetes. A VPS gives you a real Linux server. Docker gives you repeatable application packaging. Together, they make it possible to run apps, APIs, databases, workers, dashboards, and self-hosted tools without building a full platform engineering layer on day one. This guide explains when running Docker containers on a VPS makes sense, when Kubernetes or managed containers may be better, and how to think about CPU, RAM, storage, volumes, networking, security, logs, backups, and cost before deploying containerized workloads. For the broader VPS foundation, read the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If your containers are part of an application stack, also read [VPS for Application Hosting](/learn/guides/vps-for-application-hosting). ## Docker on a VPS Explained Docker on a VPS means installing Docker on a virtual private server and using containers to run one or more services. A basic Docker VPS setup might include: * Web application container * API container * Database container * Redis container * Background worker container * Reverse proxy container * Monitoring container * Logging tools * Persistent volumes * Environment variables * Docker networks * Backup process The VPS provides the infrastructure. Docker provides the packaging and runtime model. A simple Docker VPS deployment may look like this: ```text Public traffic ↓ VPS public IP ↓ Reverse proxy ↓ Docker network ↓ App container + database + cache + workers ↓ Volumes, logs, backups, monitoring ``` This setup is popular because it is understandable. You can SSH into the server, inspect containers, review logs, restart services, back up volumes, and resize the VPS when usage grows. Docker does not remove server operations. It changes how applications are packaged and managed. The VPS still needs enough CPU, RAM, storage, bandwidth, security, and monitoring for the containers running on it. ## Docker VPS Hosting Is Different From Traditional App Hosting Traditional VPS application hosting often means installing the app runtime directly on the server. For example, a Node.js app might be installed with Node and npm. A Python app might use a virtual environment. A PHP app might run under Nginx and PHP-FPM. The server itself becomes the application environment. Docker changes that model. The application and its dependencies live inside containers. The VPS runs Docker, Docker Compose, volumes, networks, and the host operating system. | Area | Traditional VPS app hosting | Docker VPS hosting | | ------------------ | ---------------------------------------------- | --------------------------------------------------------- | | Runtime | Installed directly on the server | Packaged inside containers | | Dependencies | Managed on the host OS | Defined in images and Compose files | | Deployment | Copy files, install packages, restart services | Pull or build images, recreate containers | | Isolation | Process and user-level isolation | Container-level isolation | | Configuration | Host files and service configs | Environment variables, Compose files, secrets | | Multi-service apps | Manually configured services | App, database, cache, and workers can be defined together | | Port management | App ports and web server configs | Container ports, internal networks, exposed ports | | Backups | App files and database paths | Volumes, databases, uploads, Compose files | | Operations | OS services and runtime management | Docker, images, volumes, logs, and container lifecycle | Docker is useful when the team wants repeatability. Instead of rebuilding the server environment manually, the team defines how services should run. That makes Docker attractive for small teams, staging environments, SaaS MVPs, APIs, internal tools, and self-hosted software. For broader developer VPS planning, read [Best VPS Hosting for Developers and DevOps Teams](/learn/guides/best-vps-hosting-for-developers). ## The VPS Docker Hosting Decision Framework Use this framework before choosing a VPS for Docker containers. | Decision factor | Docker on a VPS is usually a fit when... | Kubernetes or managed containers may be better when... | | ---------------- | -------------------------------------------------------- | ---------------------------------------------------------- | | Workload size | The stack can run on one VPS or a few servers | The system needs many nodes or distributed orchestration | | Team size | A small team wants control without platform complexity | A platform or DevOps team manages container infrastructure | | Deployment model | Docker Compose is enough | The team needs cluster scheduling and service discovery | | Scaling | Vertical scaling or manual scaling is acceptable | Autoscaling and multi-node placement are required | | Networking | Basic reverse proxy and container networks are enough | Advanced service mesh or cloud networking is needed | | Storage | Volumes can be managed and backed up clearly | Storage needs dynamic provisioning or managed persistence | | Operations | The team can manage Docker, logs, updates, and backups | The team wants a managed container platform | | Cost preference | Predictable monthly VPS pricing matters | Usage-based container platform pricing is acceptable | | Best fit | Apps, APIs, SaaS MVPs, dashboards, staging, self-hosting | Large platforms, microservices, enterprise-scale systems | A useful rule: Choose Docker on a VPS when your stack is containerized but still operationally simple. Choose Kubernetes or managed containers when the container platform itself becomes necessary. ![Decision matrix showing when Docker on a VPS fits small teams and when Kubernetes or managed container platforms may be better.](https://raff-images.s3.raffusercloud.com/docker_on_vps_decision_matrix_webp_65a79a7509.png) Docker on a VPS is often the right step before Kubernetes, not a replacement for every Kubernetes use case. ## A VPS Is a Good Fit for Simple and Moderate Docker Stacks A VPS can be a strong Docker host when the workload is clear, bounded, and does not need cluster-level orchestration. This often includes: * SaaS MVPs * APIs * Web applications * Internal dashboards * Admin panels * Staging environments * Development environments * Self-hosted tools * Automation services * Small databases * Redis-backed apps * Background workers * Docker Compose stacks * Customer portals * Agency projects For these workloads, a VPS keeps the environment direct. You know which server runs the containers. You can review container logs, inspect volumes, restart services, update images, configure the reverse proxy, and monitor resource usage. This is valuable for teams that want practical control without managing a cluster. A Docker VPS can also be easier to understand than a large cloud-native setup. Instead of dealing with many managed services, cluster objects, ingress controllers, and platform abstractions, the team works with a smaller set of moving parts. That simplicity is often enough for early and moderate workloads. ## Docker Compose Is Often Enough Before Kubernetes Docker Compose is one of the main reasons a VPS works well for container hosting. A Compose file can define multiple services in one place: ```text web api database redis worker reverse proxy ``` This makes it useful for small application stacks where related services should run together. ![Diagram showing a Docker Compose stack running on a VPS with public traffic, reverse proxy, internal Docker network, app container, database container, Redis cache, worker container, volumes, logs, and back](https://raff-images.s3.raffusercloud.com/docker_compose_on_vps_architecture_webp_c09d4d4eb8.png) A typical Docker Compose VPS stack may include: | Service | Role | | ------------------ | ------------------------------------- | | App container | Runs the application | | Database container | Stores application data | | Redis container | Handles cache, sessions, or queues | | Worker container | Processes background jobs | | Reverse proxy | Routes traffic to the correct service | | Volume | Stores persistent data | | Docker network | Connects services privately | | Environment file | Provides configuration values | Docker Compose is usually enough when: * The app runs on one server * Manual scaling is acceptable * The team wants simple deployment * The stack has a small number of services * The team can tolerate planned maintenance * Volumes and backups are manageable * High availability is not required yet Kubernetes becomes more relevant when the stack needs multi-node scheduling, autoscaling, service discovery, rolling deployments, self-healing, and platform-level automation. The mistake is not using Kubernetes. The mistake is using Kubernetes before the workload requires it. ## Containers Still Need Real VPS Resources Docker does not make CPU, RAM, storage, or bandwidth problems disappear. ![Visual map showing how different Docker workloads use VPS resources including CPU, RAM, NVMe storage, bandwidth, disk I/O, logs, and volumes](https://raff-images.s3.raffusercloud.com/docker_vps_resource_pressure_map_webp_66c2638493.png) Containers still consume server resources. If the VPS is undersized, the containers will compete for the same limited capacity. Common pressure points include: | Resource | Why it matters for Docker workloads | | -------------- | ------------------------------------------------------------ | | CPU | App requests, builds, workers, compression, database queries | | RAM | Containers, databases, caches, workers, runtime overhead | | NVMe storage | Images, volumes, databases, logs, builds, package layers | | Bandwidth | Public traffic, API responses, image pulls, backups, updates | | Disk capacity | Images, volumes, logs, uploads, database files | | Disk I/O | Databases, queues, caches, logging, backup jobs | | Network ports | Public exposure, internal service communication | | Process limits | Too many containers or workers can create instability | Docker can make deployment cleaner, but it can also hide resource pressure until the server becomes slow. A VPS running one lightweight container is very different from a VPS running an app, database, Redis, workers, monitoring, and backups. Before choosing the VM size, identify the full container stack. For practical sizing, read [Choosing the Right VM Size](/learn/guides/choosing-right-vm-size). ## Docker Volumes Are the Core of Persistence Containers are designed to be replaceable. Data is not. That is why volumes matter. A Docker container can be stopped, removed, recreated, or updated. If important data lives only inside the container filesystem, it can be lost during normal operations. Persistent data should live in volumes or external storage. Common persistent data includes: * Database files * Uploaded files * User content * App-generated files * Configuration data * Queue state * Logs that must be retained * Self-hosted tool data A Docker VPS setup should clearly separate disposable containers from persistent volumes. A simple rule: ```text Containers should be replaceable. Volumes should be protected. ``` This is especially important for databases, CMS platforms, automation tools, dashboards, file services, and self-hosted software. For database-specific planning, read [VPS for Databases](/learn/guides/vps-for-databases). ## Docker Networking Should Stay Intentional Docker networking is powerful, but it can become messy if ports are exposed without planning. A common safe pattern is: ```text Public internet ↓ Reverse proxy on ports 80/443 ↓ Internal Docker network ↓ App containers, database, cache, workers ``` In this model, only the reverse proxy receives public traffic. Internal services communicate through Docker networks. You usually do not need to expose every container port to the public internet. For example: | Service | Public exposure | | ------------------ | ----------------------------- | | Reverse proxy | Public on 80/443 | | App container | Usually internal | | Database container | Usually internal | | Redis container | Internal only | | Worker container | No public port | | Admin tools | Restrict or protect carefully | Exposing the wrong port can create security risk. A database container should usually not be public. Redis should usually not be public. The Docker socket should not be public. Admin panels should be protected with authentication and firewall rules. A clean Docker VPS setup makes public access intentional and keeps internal services private. ## Reverse Proxies Make Docker VPS Hosting Cleaner A reverse proxy is useful for Docker workloads because it creates a clean public traffic layer. Instead of exposing each container directly, the reverse proxy receives traffic and routes it to the right service. A reverse proxy can handle: * Domain routing * HTTPS * Redirects * Headers * Compression * Multiple apps on one VPS * API routing * WebSocket support * Static file routing * Access rules Common reverse proxy options include: * Nginx * Caddy * Traefik * Apache * Nginx Proxy Manager For small teams, Nginx or Caddy can be enough. Traefik can be useful when container labels and dynamic routing are important. Nginx Proxy Manager can be practical when a team wants a web UI. The reverse proxy should be treated as part of the production architecture, not an afterthought. It is the layer that connects public traffic to private containers. ## Logs, Images, and Volumes Can Fill the Disk One of the easiest Docker VPS problems to miss is disk growth. Docker can consume storage through: * Container logs * Old images * Build cache * Volumes * Database files * Uploads * Temporary files * Backups * Package layers * Unused containers A VPS may feel stable at first, then suddenly run out of disk space because logs or old images were never cleaned. This can break containers, databases, and deployments. A Docker VPS should include a storage review process. Useful checks include: ```text docker system df docker ps docker images docker volume ls ``` Teams should also review container log behavior. Large logs can quietly consume disk space. For production workloads, disk usage should be monitored before it reaches emergency levels. ## Backups Must Protect Volumes, Not Just Code Docker makes app deployment repeatable, but it does not automatically protect data. The code may live in Git. The image may be rebuilt. The server may be replaced. ![Diagram showing replaceable Docker containers and protected persistent volumes with backup storage, restore testing, and recreated VPS recovery path.](https://raff-images.s3.raffusercloud.com/docker_volumes_backup_model_webp_050df13d3f.png) But volumes often contain the important state. A Docker VPS backup plan should include: * Database volumes * Upload volumes * Compose files * Environment files * Reverse proxy config * SSL configuration * Application config * Important logs * Documentation for restore Backups should be stored somewhere other than the same VPS when the data matters. The restore process should also be tested. A backup is only useful if the team can recreate the stack and restore the data when something fails. For broader recovery planning, read [Cloud Security Fundamentals](/learn/guides/cloud-security-fundamentals). ## Docker Security Depends on Boundaries Docker improves packaging, but it is not a security strategy by itself. A Docker VPS still needs basic server hardening and container security. Important Docker VPS security practices include: * Keep the host operating system updated * Keep Docker updated * Avoid exposing unnecessary ports * Do not expose the Docker socket publicly * Use strong SSH access controls * Restrict firewall rules * Avoid running everything as root when possible * Use least-privilege container permissions * Keep secrets out of images * Store secrets in environment files or secret managers * Protect admin panels * Keep databases and Redis private * Review image sources * Remove unused containers and images * Monitor logs and access patterns The Docker socket is especially sensitive. Access to it can often mean control over the host. A production Docker VPS should treat container boundaries, host security, and network exposure as one system. ## Docker on a VPS Becomes Risky When the Platform Needs Grow Docker on a VPS is practical, but it has limits. The model becomes risky when the workload needs platform capabilities that a single VPS cannot comfortably provide. Docker on one VPS may become the wrong model when the application needs: * Multiple nodes * Automatic container scheduling * Horizontal autoscaling * Built-in service discovery * Rolling deployments across nodes * Self-healing across servers * Strong multi-tenant isolation * Cluster-wide secrets management * Multi-region availability * High availability for databases * Large-scale observability * Complex network policies * Formal platform governance At that point, Kubernetes, managed container services, or a larger cloud architecture may be a better fit. This is not a failure of VPS hosting. It means the workload has moved into a different operations category. A good infrastructure path starts simple, measures real pressure, and moves to a larger platform when the need becomes real. ## Cost Planning Should Include the Whole Container Stack The cost of Docker VPS hosting is not only the VM price. The full cost depends on: * VM size * CPU needs * RAM needs * NVMe storage * Bandwidth * Volume growth * Backups * Snapshots * Monitoring * Image storage * Database needs * Security tools * Admin time * Migration risk * Upgrade path Docker can make deployment efficient, but it can also encourage teams to put too many services on one small server. A low-cost VPS may become expensive if it causes slow containers, failed jobs, disk pressure, database instability, or emergency migrations. The right cost question is: ```text What is the smallest reliable VPS for this container stack? ``` Not: ```text What is the cheapest VPS that can install Docker? ``` For broader budget planning, read [Cloud Server Cost in 2026](/learn/guides/cloud-server-cost-2026). ## Raff VM in the Docker VPS Hosting Context Raff VM fits the Docker VPS hosting path for teams that want practical container deployment without starting with Kubernetes or hyperscaler platform complexity. Many developers and small teams do not need a full container orchestration platform for the first version of an app. They need a Linux VM where they can install Docker, run a Compose stack, connect a domain, manage volumes, monitor logs, and scale the server when usage grows. Raff VM supports this model with AMD EPYC processors, NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and Linux VM options. Plans start from $4.99/month for entry-level workloads. This makes Raff VM relevant for: * Docker Compose stacks * APIs * SaaS MVPs * Internal dashboards * Self-hosted tools * Automation services * App plus database deployments * Redis-backed apps * Background workers * Staging environments * Developer-managed production apps Raff also supports a Docker marketplace path for teams that want a faster starting point for Docker-based server setup. The broader decision remains the same: use Docker on a VPS when the workload fits one or a few clear servers, and move to Kubernetes or managed containers when the app truly needs platform-level orchestration. For teams that want simple cloud VM infrastructure, Docker on Raff VM can be a practical middle ground between manual server setup and complex container platforms. ## Common Mistakes When Running Docker on a VPS Most Docker VPS mistakes happen when teams treat containers as if they remove infrastructure responsibility. Docker makes deployment cleaner, but the VPS still needs sizing, storage planning, backups, security, and monitoring. | Mistake | What it looks like | What it can cause | | ---------------------------------------------------- | --------------------------------------------------- | ----------------------------------------------- | | Treating containers as stateless when volumes matter | Data lives in unnamed or unmanaged volumes | Data loss during updates or migrations | | Exposing too many ports | Every service is reachable from the public internet | Security risk and harder network management | | Ignoring logs and image cleanup | Docker storage grows quietly | Full disk, failed deployments, broken databases | | Running database containers without backups | The database works until failure | Permanent data loss or difficult recovery | | Choosing the smallest VPS by price | The stack fits today but has no headroom | Slow apps, crashed containers, failed workers | | Using Docker instead of understanding operations | The team deploys but does not monitor | Problems appear first through user complaints | | Jumping to Kubernetes too early | The team adds orchestration before demand exists | Higher cost, slower delivery, more complexity | | Staying on one VPS too long | The workload outgrows a single server | Shared failures and painful migration | ### Treating volumes casually Volumes are where important data often lives. If the team does not know which volumes matter, what they contain, and how they are backed up, the Docker setup is not production-ready. ### Exposing internal services publicly A database, Redis instance, worker service, or Docker socket should not be public without a very specific and secured reason. Use internal Docker networks and expose only the public entry point. ### Forgetting disk cleanup Old images, logs, build cache, and stopped containers can accumulate. A Docker VPS needs regular storage review, especially when it hosts databases or upload-heavy apps. ### Running too many services on one small VPS Docker makes it easy to add services. That does not mean the server has unlimited capacity. Each service consumes memory, CPU, storage, and operational attention. ### Using Kubernetes before the workload needs it Kubernetes is powerful, but it is not the default requirement for every containerized app. A VPS with Docker Compose can be faster, cheaper, and easier for many early-stage teams. ## Best Practices for Docker VPS Hosting A good Docker VPS setup starts with the container stack, data model, and operations plan. Before deploying, define what the containers do, what data must persist, what should be public, and who will maintain the server after launch. Use this model before choosing a VPS: | Decision area | Ask this question | Why it matters | | ------------- | ---------------------------------------------------- | ----------------------------------------------- | | Stack shape | How many containers will run? | Determines CPU, RAM, storage, and network needs | | Persistence | Which containers store data? | Defines volumes and backup requirements | | Public access | Which services need public ports? | Reduces security exposure | | Reverse proxy | How will traffic reach the right container? | Simplifies HTTPS and domain routing | | Database | Is the database containerized, separate, or managed? | Affects backups, memory, and recovery | | Logs | Where will container logs go? | Prevents disk growth and improves debugging | | Updates | How will images and containers be updated? | Reduces deployment mistakes | | Growth | Can the stack stay on one VPS? | Helps decide when to move beyond VPS | ### Define the container stack before sizing the VPS List every container the server will run. Include the app, database, cache, workers, reverse proxy, monitoring tools, admin tools, and any scheduled jobs. A VPS that is fine for one app container may not be enough for a full Compose stack with PostgreSQL, Redis, workers, uploads, and logs. ### Keep public traffic behind a reverse proxy Use a reverse proxy as the public entry point. Expose ports 80 and 443 publicly. Keep app, database, Redis, and worker services internal unless there is a clear reason to expose them. This keeps the architecture cleaner and reduces unnecessary risk. ### Protect persistent volumes Identify which volumes contain important data. Back up those volumes regularly and document how to restore them. For databases, prefer database-aware backup methods instead of only copying raw files while the database is active. ### Monitor CPU, RAM, disk, and logs Docker issues often appear as resource pressure. Monitor the VPS and the containers. Watch disk usage especially closely, because Docker images, logs, and volumes can grow over time. ### Keep Compose files and environment files organized The Compose file is part of the deployment. Keep it versioned when possible. Store environment variables carefully. Avoid committing secrets to public repositories. A clean Compose setup makes recovery and migration easier. ### Start with Docker Compose before Kubernetes For many small teams, Docker Compose is enough. Move to Kubernetes when the workload needs orchestration, not because containers automatically require a cluster. ### Plan the migration path A Docker VPS can be a strong starting point, but not every workload should stay there forever. When the app needs multiple servers, autoscaling, high availability, or advanced release workflows, plan the next infrastructure stage before the current setup becomes fragile. ## Choosing the Right Docker VPS Path Docker on a VPS is strongest when a team wants repeatable container deployment without the complexity of a full orchestration platform. It works well for APIs, SaaS MVPs, dashboards, staging environments, self-hosted tools, small databases, background workers, and Docker Compose stacks that can run on one or a few virtual servers. It is not the right answer for every container workload. Kubernetes, managed container platforms, or larger cloud architectures may be better when the application needs autoscaling, multi-node scheduling, service discovery, high availability, or platform-level operations. For the broader VPS foundation, start with the [Virtual Private Server Hosting Guide](/learn/guides/virtual-private-server-hosting). If your containers support an app, read [VPS for Application Hosting](/learn/guides/vps-for-application-hosting). If your stack includes databases, read [VPS for Databases](/learn/guides/vps-for-databases). If your Docker workload fits the VPS path, Raff VM gives you a simple way to deploy cloud infrastructure with predictable monthly pricing, NVMe SSD storage, unmetered bandwidth, and Linux server options. [Explore Raff VM](/products/raff-vm) --- ### VM Sizing: How to Choose the Right Size for Your Workload URL: https://rafftechnologies.com/learn/guides/choosing-right-vm-size Description: Learn VM sizing by matching CPU, RAM, storage, network, and operating headroom to real workload behavior, then validate the choice with production metrics. VM sizing is the process of matching virtual CPU, memory, storage, network capacity, and operating headroom to a workload's expected demand. The safest starting VM is not the largest plan you can afford or the cheapest plan that can boot the application. It is the smallest profile that can run normal demand reliably, absorb expected peaks and maintenance work, and leave a clear path to resize when the workload produces better evidence. Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff infrastructure reviews, Serdar's recurring sizing lesson is that teams often choose a VM from one headline number—usually vCPU—before identifying which resource will actually control latency, throughput, or stability. This guide is the connector for Raff's VM sizing, performance, and scaling content. Use it for the **initial sizing decision**. If a VM is already running and you are optimizing cost or correcting over- or under-provisioning, use [Right-Sizing Cloud Servers](/learn/guides/right-sizing-cloud-servers). If the deployed server is slow and the constraint is unclear, use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). ![VM sizing decision diagram showing CPU, RAM, storage, and network capacity connected to different cloud workload types.](https://raff-images.s3.raffusercloud.com/vm_sizing_decision_framework_png_1f77abbb4e.png) ## VM sizing starts with workload behavior and failure impact A plan table shows capacity. The workload determines whether that capacity is useful. Before choosing a VM, describe the workload in operational terms: - Is it production, staging, development, CI, or temporary testing? - Is demand steady, bursty, scheduled, or still unknown? - Does it serve users directly or process background work? - Does it run a database, cache, queue, containers, builds, or remote sessions? - Which failure appears first when capacity is tight: slow requests, queue growth, restarts, swap, or a full disk? - How expensive is a slowdown or restart? - Can the workload be resized or separated later without a major migration? This prevents two opposite mistakes. **Undersizing** creates latency, swap, failed jobs, OOM events, full disks, risky deployments, and operational noise. **Oversizing** spends money on unused capacity and can hide inefficient queries, memory leaks, unbounded workers, or poor application design. The correct starting point sits between them: enough capacity for normal demand and known peaks, but not so much excess that the team loses the signal needed to understand the application. The same environment label can require very different resources. A quiet production API may fit a smaller VM than a development build runner that compiles several projects in parallel. Size the work, not the label. ## CPU, memory, storage, and network create different constraints Sizing improves when each resource is evaluated separately. ### CPU determines available parallel compute CPU matters when useful work is waiting to be scheduled or completed: request handlers, builds, tests, workers, compression, indexing, encryption, data transformation, and other compute-heavy tasks. Useful CPU signals include: - sustained CPU pressure during the affected workload period; - growing runnable work or worker backlog; - p95/p99 latency rising with compute demand; - build or test duration increasing under equivalent work; - one thread saturating while other vCPUs remain idle. More vCPU helps only when the application has useful parallel work. A serial critical path, slow database query, external API, or storage wait may gain little from additional cores. For the narrower choice, read [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms). ### Memory determines how much active state can remain resident RAM is shared by the operating system, application runtime, database buffers, caches, containers, workers, and monitoring agents. Stronger memory-pressure evidence includes: - low available memory during normal peaks; - sustained swap-in or swap-out activity; - memory pressure or reclaim stalls; - out-of-memory events; - containers or processes restarting; - database or application latency increasing with memory pressure. Do not size memory from a universal utilization percentage. Linux can use otherwise idle RAM for useful filesystem cache. The better question is whether the working set fits safely and whether pressure affects the workload. For memory-specific sizing, use [How Much RAM Do I Need for a VPS?](/learn/guides/how-much-ram-do-i-need-for-vps) and [HiMem VMs Explained](/learn/guides/himem-vms-explained). ### Storage has both capacity and performance requirements Storage sizing must cover how much data exists, how quickly it grows, and how the workload reads and writes it. Include: - operating-system and application files; - database and index growth; - uploads; - logs; - container images and volumes; - temporary files; - build artifacts; - monitoring data; - backup staging. A disk can have free capacity and still be limited by I/O latency. It can also be fast but fail because logs or data fill it. Track free space, growth rate, latency, throughput, and queueing separately. ### Network capacity is only one part of network behavior APIs, file transfer, backups, media, replication, remote access, and service-to-service traffic depend on more than advertised bandwidth. Consider: - expected transfer volume; - user geography; - round-trip latency; - packet loss and retransmissions; - request and payload size; - internal service traffic; - whether bandwidth is included or metered. A faster VM cannot remove latency from a remote dependency or an inefficient application protocol. ## A practical VM sizing framework maps evidence to the first decision Use the following framework before selecting a specific plan. | Workload pattern or evidence | First resource to examine | Safer starting direction | What would change the decision | |---|---|---|---| | Static site or small proxy | Memory and storage | Small balanced VM | Dynamic features, traffic, or storage growth | | Small web app or API | CPU concurrency and memory | Balanced VM | Sustained CPU pressure, memory pressure, or DB contention | | Database-backed app on one VM | Memory, storage, DB behavior | Balanced VM with headroom | Working-set growth or app/DB contention | | Dedicated database | Memory, storage latency, recovery needs | Memory-conscious shape | CPU-heavy queries or independent scaling needs | | Container host | Aggregate CPU and memory | Balanced VM with OS headroom | More containers or one dominant service | | CI/CD runner | CPU and temporary storage | Compute-oriented shape | Parallel job count and build duration | | Background workers | CPU and queue depth | Size to measured throughput | Backlog growth or downstream bottleneck | | File-heavy application | Storage growth and transfer | VM plus separate storage where useful | I/O or retention requirements | | Unknown new workload | CPU/RAM balance | Smallest safe balanced VM | First week of real workload data | Then apply five questions: 1. **What is the workload's main job?** User requests, database work, background processing, builds, storage, or remote access? 2. **Which resource is most likely to become constrained first?** CPU, memory, disk, or a dependency? 3. **What peak must the VM survive?** Normal traffic peak, deployment, backup, scheduled job, or campaign? 4. **How much failure headroom is justified?** A test VM and a revenue-critical API should not carry the same margin. 5. **What is the next safe change?** Resize one resource, change CPU class, separate storage, or split a service? **A VM size is defensible when its resource profile matches the workload's likely constraint and the team knows which measurements will validate the choice.** Universal recommendations such as "production needs 4 vCPU" or "upgrade at 80% RAM" are too crude because they ignore the workload and failure impact. ## General Purpose and CPU-Optimized solve different CPU allocation problems ![General Purpose versus CPU-Optimized VM comparison showing balanced workloads on one side and compute-heavy workloads on the other.](https://raff-images.s3.raffusercloud.com/general_purpose_vs_cpu_optimized_vm_png_4f38bae148.png) VM size and CPU allocation class are related but different decisions. Raff General Purpose VMs use shared CPU resources and are the natural starting point for variable or balanced workloads such as websites, development environments, staging, internal tools, and moderate application traffic. Raff CPU-Optimized VMs use dedicated CPU cores. They are more appropriate when sustained compute and CPU consistency matter enough to justify a different allocation model, including selected databases, CI/CD, workers, processing jobs, and latency-sensitive services. A practical class decision looks like this: | Evidence | Better direction | |---|---| | Workload is variable or still early | General Purpose | | CPU bursts are occasional and acceptable | General Purpose | | CPU has headroom but RAM is constrained | More memory, not a CPU-class change | | Sustained compute demand controls completion time | Evaluate CPU-Optimized | | CPU timing variance affects latency or business outcomes | Evaluate dedicated CPU | | Database is slow but CPU is comfortable | Diagnose query, lock, memory, and storage behavior first | Use [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained) for the full class decision and [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) when CPU predictability is the main question. ## Databases and container hosts need explicit operating headroom Some workloads create resource pressure indirectly because several processes share the same VM. A database-backed application may contain a reverse proxy, API runtime, PostgreSQL or MySQL, Redis, background workers, scheduled jobs, and monitoring. A container host may package the same components separately while still sharing one physical memory and CPU budget. For databases, review: - working-set size and cache behavior; - active and peak connections; - read/write pattern; - query and lock duration; - database and index growth; - backup and restore behavior; - storage latency; - whether application traffic and database maintenance overlap. For container hosts, review: - aggregate container memory limits; - CPU-active services during peaks; - image and volume storage growth; - deployment overlap between old and new containers; - logging and monitoring overhead; - restart behavior; - background workers and queues. Headroom should cover expected operational events, not only idle steady state. Package updates, deployments, migrations, backups, compaction, imports, and scheduled jobs are part of the workload. When one service repeatedly dominates the host or needs different scaling and recovery behavior, a larger VM may no longer be the cleanest answer. [Separate App and Database Server](/learn/guides/separate-app-database-server) covers that architecture boundary. ## Initial sizing and right-sizing happen at different stages This guide answers **what should we start with?** Right-sizing answers **does the running VM still fit?** Keeping those questions separate prevents two Raff pages from competing for the same intent. Before launch, you usually have estimates rather than production history. The goal is to choose the smallest safe starting profile with deliberate headroom and a resize path. After launch, use real evidence: - peak CPU rather than only averages; - available memory, swap, and OOM events; - p95/p99 application latency; - queue depth or oldest-job age; - storage growth and I/O latency; - database query and lock time; - network path behavior; - deployment and backup impact. A safe post-launch process is: 1. define the workload outcome that matters; 2. compare normal and peak periods; 3. identify the constrained resource or dependency; 4. change one variable where practical; 5. repeat an equivalent workload; 6. keep the change only when the workload outcome improves; 7. check whether the bottleneck moved downstream. If the server is already running and the goal is to reduce waste or correct under-provisioning, continue with [Right-Sizing Cloud Servers](/learn/guides/right-sizing-cloud-servers). If the correct move is more capacity but you are deciding between a larger VM and multiple nodes, use [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud). ## Raff provides a resizeable path from small balanced VMs upward Raff's current General Purpose lineup gives teams several CPU-to-memory ratios instead of forcing every workload through one fixed ladder. As of August 10, 2026, useful monthly examples include: | General Purpose shape | Monthly price | Sizing interpretation | |---|---:|---| | 2 vCPU / 2 GB / 40 GB | $8.49 | Focused lightweight workloads | | 2 vCPU / 4 GB / 80 GB | $13.99 | Same vCPU count with more memory | | 4 vCPU / 4 GB / 80 GB | $16.99 | More compute at the same memory level | | 2 vCPU / 8 GB / 160 GB | $27.99 | Higher memory-to-vCPU ratio | | 4 vCPU / 8 GB / 160 GB | $30.99 | Balanced midrange shape; currently marked Popular | This makes resource-specific resizing easier to reason about. If a 2 vCPU / 2 GB workload is memory-constrained but CPU has headroom, the 2 vCPU / 4 GB path changes memory without automatically doubling cores. If a 2 vCPU / 4 GB workload is compute-constrained, the 4 vCPU / 4 GB shape changes CPU while holding memory constant. Current Raff Cloud Server plans include a **3 Gbps public port**, unmetered bandwidth, CPU/RAM/storage resize support, one IPv4 with optional IPv6, free private networking, DDoS protection, browser console/root access, API and Terraform access, and live monitoring. That does not remove the need to measure. Platform capacity and application efficiency are separate questions. NVMe storage does not make a poor query plan efficient, and a 3 Gbps port does not remove latency from a remote API. For current plan-by-plan details, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained) and verify the live [pricing page](/pricing) before deployment. ## Conclusion: The right VM size is the smallest safe current fit VM sizing should produce a starting hypothesis, not a permanent label. Choose the smallest profile that can run normal demand, expected peaks, and routine maintenance with appropriate headroom. Match the profile to the likely constraint: CPU for parallel compute, memory for working-set pressure, storage for capacity and I/O behavior, and network for data-moving workloads. Then validate the decision with real workload evidence. For entry-size workloads, continue with [2 vCPU / 2 GB Cloud VM Workloads](/learn/guides/2-vcpu-2gb-cloud-vm-workloads). For CPU count, use [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms). For post-deployment diagnosis, use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). :::cta Explore Raff VM Compare current VM profiles and choose a starting size based on the resource your workload is most likely to constrain first. ::: ### Sources - [Linux Kernel: Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) - [Raff Cloud Servers](/products/raff-vm) - [Raff Pricing](/pricing) - [Raff FAQ](/faq) - [Raff Volumes](/products/volumes) - [Raff Object Storage](/products/object-storage) --- ### Horizontal vs Vertical Scaling: When to Scale Up or Out URL: https://rafftechnologies.com/learn/guides/horizontal-vs-vertical-scaling-cloud Description: Understand horizontal vs vertical scaling for cloud VMs: compare scale up vs scale out, state, failure capacity, databases, and operating complexity. Horizontal vs vertical scaling is the choice between adding resources to one server and adding more servers or workers to distribute the workload. Vertical scaling, or **scaling up**, increases CPU, memory, or storage on one node. Horizontal scaling, or **scaling out**, adds nodes and spreads requests or jobs across them. The better strategy depends on the measured bottleneck, where application state lives, how much failure isolation is required, and whether the team can operate a multi-node system safely. Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff infrastructure reviews, Serdar’s recurring rule is to avoid turning a resource problem into a distributed-systems problem too early: scale vertically while one node still meets the workload and recovery model, then scale horizontally when one node becomes the capacity or availability boundary. This guide is the connector for Raff’s **Scaling Strategies** cluster. Use [VM Sizing](/learn/guides/choosing-right-vm-size) when choosing the starting VM, [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) when the constraint is unclear, and [Auto-Scaling VM Planning](/learn/guides/auto-scaling-vm-planning) after the architecture is ready for automated capacity changes. ## Horizontal vs vertical scaling solve different constraints The two strategies can increase capacity, but they change the system in different ways. | Decision factor | Vertical scaling | Horizontal scaling | |---|---|---| | Method | Add CPU, RAM, or storage to one node | Add more nodes or workers | | Common term | Scale up / scale down | Scale out / scale in | | Application changes | Usually limited | Often requires statelessness and shared services | | Operational complexity | Lower | Higher | | Capacity ceiling | Limited by the largest practical node | Higher when work distributes efficiently | | Failure boundary | One active node can remain critical | Node loss can be tolerated when designed correctly | | Deployment model | Simpler single-node process | Coordinated or rolling releases | | Strong early fit | MVPs, stateful apps, primary databases | Web/API fleets, workers, replaceable app nodes | A useful distinction is: > **Scale vertically to remove a node-level resource constraint. Scale horizontally to remove one node as the capacity or availability boundary.** Neither method fixes inefficient code, a slow query, lock contention, storage latency, or an external API. Diagnose the wait path before changing the architecture. ## The decision framework starts with bottleneck, state, and failure boundary Use five questions before choosing a scaling strategy. 1. **What is limiting the workload?** CPU, memory, storage, network, database, queue, lock, or dependency? 2. **Can one larger node meet expected demand?** Include normal peaks, maintenance, and growth headroom. 3. **Can useful work be divided safely?** Requests, jobs, and data must tolerate distribution. 4. **Where does state live?** Sessions, files, queues, and durable data cannot depend on one disposable application node. 5. **Can the team operate multiple nodes safely?** Health checks, deployments, logs, networking, failure handling, and scale-in must be repeatable. | Evidence | Better first move | Reason | |---|---|---| | One VM resource is constrained | Scale vertically | Lowest-complexity capacity change | | One larger VM still meets growth and recovery needs | Keep scaling vertically | Multi-node complexity is not yet justified | | App and database compete repeatedly | Separate roles | Different components need different capacity boundaries | | Stateless app tier reaches repeatable capacity | Scale horizontally | Requests can be distributed across nodes | | Worker backlog grows and jobs are independent | Add workers horizontally | Queue work is naturally distributable | | One-node failure is unacceptable | Add redundant nodes and resilient dependencies | Availability, not only capacity, is the goal | | Database is the bottleneck | Tune or scale the database first | More app nodes can increase DB pressure | | Burst ends before a new node can become useful | Buffer, cache, schedule, or keep headroom | Reactive scale-out arrives too late | **The right scaling move is the smallest architectural change that improves the workload outcome without creating a larger operating problem.** In Raff infrastructure work, this evidence-first rule is especially important for small teams because a second or third node also creates deployment, state, health-check, networking, and recovery responsibilities. ## Vertical scaling is the lower-complexity path while one node still fits Vertical scaling increases the resources available to the current VM or moves the workload to a larger VM profile. It is usually the better first move when: - CPU or memory is the measured constraint; - one server still fits the application model; - the workload is difficult to partition; - a short maintenance interruption is acceptable; - the team wants the lowest operational complexity; - the larger node provides enough growth headroom. Common candidates include early SaaS applications, internal business systems, stateful software, primary databases, single-node APIs, and workloads with predictable growth. The main advantage is simplicity. The application keeps one active operating boundary while the team gains more capacity. Backups, monitoring, deployment, networking, and recovery remain easier to reason about than in a distributed fleet. Vertical scaling eventually reaches practical limits: - the largest useful VM size; - software that cannot use additional cores efficiently; - one-node failure exposure; - maintenance or restart impact; - app, database, workers, and monitoring competing on one host; - poor economics from continually enlarging one system instead of separating roles. A resize is not a high-availability design. More CPU or RAM can remove a resource constraint, but the workload may still depend on one active node. For CPU-specific sizing, use [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms). For memory pressure, use [VPS RAM Requirements](/learn/guides/how-much-ram-do-i-need-for-vps). ## Horizontal scaling works when workload and state can be distributed Horizontal scaling adds application instances, service replicas, or workers. ```text Users ↓ Traffic distribution ↓ App VM 1 App VM 2 App VM 3 ↓ private network Database, cache, queue, and shared storage ``` More nodes increase useful capacity only when work can be distributed without conflicting state, duplicate side effects, or an unchanged downstream bottleneck. Horizontal scaling normally requires: - health-aware traffic or job distribution; - repeatable provisioning and configuration; - sessions and durable files outside disposable app nodes; - centralized logs and metrics; - private networking and firewall rules; - database connection planning; - graceful shutdown and traffic draining; - safe scale-in behavior. ### Stateless application nodes are easier to add and remove An application node is operationally stateless when another healthy node can handle the next request without depending on state stored only on the first server. Move shared state to the correct layer: - durable records → database; - sessions → shared session store or suitable database; - uploads and assets → object storage; - background work → queue; - shared cache → distributed cache. Sticky sessions can reduce short-term migration work, but they preserve node affinity and do not solve shared files, shared events, database limits, or node-failure behavior. Read [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) before adding application instances. ### Workers are often easier to scale horizontally than web state Background jobs can be natural scale-out candidates when jobs can run independently and retries are safe. Before adding workers, confirm that: - work can run concurrently; - duplicate execution is prevented or harmless; - retries are bounded; - jobs are idempotent where practical; - database writes support added concurrency; - external API rate limits remain safe; - queue depth and oldest-job age are monitored. More workers can overload the database or an external provider. Scale the complete processing path, not only the visible queue consumer. ## Databases, queues, and dependencies define the real scale unit A scale unit is the set of resources and limits that must grow together to support additional demand. Adding application nodes may also increase: - database connections; - read and write concurrency; - cache traffic; - queue throughput; - object-storage requests; - network traffic; - logging and metrics volume; - external API usage. A useful test is: > **When one application node is added, which other limit moves closer to exhaustion?** The database is the most common example. Adding two application nodes can increase connection count and query concurrency without changing database capacity. If the data layer is already constrained, horizontal app scaling can make total latency worse. A practical primary-database sequence is: 1. measure slow queries, locks, connection use, memory, and storage latency; 2. fix inefficient queries and indexes; 3. use connection pooling where appropriate; 4. add RAM, CPU, or storage performance when measured; 5. separate analytics, backups, or heavy background work; 6. add read replicas when read demand justifies them; 7. partition or shard only when simpler options are no longer sufficient. Read replicas can distribute selected reads, but they do not automatically increase primary write capacity. Sharding can increase write scale but adds data-placement, routing, migration, and recovery complexity. This is why scaling should be measured across the complete request or job path rather than one infrastructure graph. ## Availability, deployment, and scale-in raise the operating cost of scale-out Horizontal scaling can improve capacity and availability, but those are separate goals. For availability, a multi-node design needs more than two running servers. It needs meaningful readiness checks, automatic removal of unhealthy nodes, enough remaining capacity after a node fails, state outside the failed node, and resilient database, storage, DNS, and routing dependencies. Two nodes that each require most of the total workload capacity do not create useful failure headroom. ### Load balancing needs readiness rather than simple reachability A readiness check should answer whether the node can safely receive new work. Depending on the application, that may include startup completion, required configuration, critical dependency access, or a lightweight representative operation. Use [Load Balancing Explained](/learn/guides/load-balancing-explained) for the routing and health-check decision. ### Multi-node deployments need version coexistence A rolling release normally drains one node, deploys the new version, waits for readiness, returns the node to service, and continues across the fleet. During that process, old and new versions may operate at the same time. Database schemas, message formats, sessions, and cache structures must remain compatible. Use [Blue-Green vs Rolling Deployments](/learn/guides/blue-green-vs-rolling-deployments) for the release-model decision. ### Scale-in is often riskier than scale-out Before terminating a node, confirm: - it no longer receives new work; - existing requests and connections can finish; - queued or in-progress jobs are handed off safely; - local temporary data is disposable; - leases and locks expire correctly; - the remaining fleet has enough capacity. Aggressive scale-in can create oscillation, interrupted jobs, and repeated cold starts. Automated scaling therefore belongs after the architecture can safely add **and remove** capacity. Continue with [Auto-Scaling VM Planning](/learn/guides/auto-scaling-vm-planning) when demand signals, warm-up, minimum/maximum capacity, cooldowns, and safe removal need to become a control policy. ## Raff supports a staged path from resize to multi-node architecture Raff supports the common small-team progression from one VM to separated roles and then to a multi-node application tier. A current Raff Cloud Server can be resized for CPU, RAM, and storage. Raff’s live VM documentation states that CPU or RAM changes use a quick power-off/resize/start cycle, while storage can expand as the workload grows. Current Cloud Server plans also include a **3 Gbps public port**, unmetered bandwidth, and free private networking. The current General Purpose lineup starts at **2 vCPU / 2 GB / 40 GB for $8.49/month**, while the Popular **4 vCPU / 8 GB / 160 GB** shape is **$30.99/month**. That creates a practical vertical-scaling path before distributed architecture is necessary. ```text One Raff VM ↓ measured CPU or RAM constraint Larger VM ↓ repeated role contention Separate database or workers ↓ one-node capacity or availability boundary Multiple replaceable app VMs ↓ Traffic distribution + private network + shared state ``` For horizontal designs, Raff provides Cloud Servers plus public product paths for [Load Balancers](/products/load-balancers), [VPC](/products/vpc), [Object Storage](/products/object-storage), [Volumes](/products/volumes), and [Data Protection](/products/data-protection). Verify the live feature set and service limits before implementation, especially for traffic-distribution and automation behavior. The important architecture rule does not change by provider: resize when one VM is still the correct boundary, separate roles when they need independent resources, and add nodes only when the application and dependencies are ready to distribute work safely. ## The right scaling strategy follows measured constraints Horizontal and vertical scaling are not competing ideologies. They are different tools for different boundaries. Scale vertically when one measured resource is constrained and a larger node still satisfies capacity, recovery, and operating requirements. Scale horizontally when useful work can be distributed and one node has become an unacceptable capacity or availability boundary. Combine the two when different tiers need different strategies—for example, a larger primary database behind horizontally scaled application and worker nodes. Start with [VM Sizing](/learn/guides/choosing-right-vm-size) when choosing the initial server. Use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) when performance is already degraded. Then continue to [Auto-Scaling VM Planning](/learn/guides/auto-scaling-vm-planning) only after scale-out and scale-in behavior are safe and repeatable. :::cta Explore Raff VM Start with a measurable VM foundation, then resize or distribute the workload only when the evidence justifies the added architecture. ::: ### Sources - [Microsoft Azure Architecture Center: Design to Scale Out](https://learn.microsoft.com/en-us/azure/architecture/guide/design-principles/scale-out) - [Microsoft Azure Well-Architected Framework: Reliable Scaling Strategy](https://learn.microsoft.com/en-us/azure/well-architected/reliability/scaling) - [Microsoft Azure Well-Architected Framework: Scaling and Partitioning](https://learn.microsoft.com/en-us/azure/well-architected/performance-efficiency/scale-partition) - [Raff Cloud Servers](/products/raff-vm) - [Raff Pricing](/pricing) --- ### Load Balancing Explained: L4, L7, Health Checks, and Failover URL: https://rafftechnologies.com/learn/guides/load-balancing-explained Description: Understand load balancing, L4 vs L7 routing, health checks, failover, draining, state, TLS, and multi-node architecture decisions. Load balancing is a traffic-distribution pattern that routes requests or connections across multiple backend servers to improve capacity, availability, and deployment flexibility. **Use it when one application server has become an unacceptable capacity, failure, deployment, or maintenance boundary—not simply because a multi-server design looks more advanced.** Raff Technologies supports 3,000+ customers and 15,000+ VMs from its US infrastructure. At Raff, our architecture rule is straightforward: add load balancing only after the application can distribute work safely and the team can explain what happens when one backend disappears. A load balancer can remove an unhealthy application node from traffic, but it cannot repair a database bottleneck, recover deleted data, or make local sessions portable. This guide explains the load-balancing decision, L4 vs L7 routing, health checks, failure capacity, connection draining, state, TLS, deployments, and the practical Raff architecture. For the scaling decision that comes first, read [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud). ![Load balancing architecture diagram showing user traffic distributed through a load balancer to multiple application servers and a private database.](https://raff-images.s3.raffusercloud.com/Chat_GPT_Image_Jun_20_2026_08_49_10_PM_0237fda581.png) ## Load balancing becomes useful when one node is the boundary A load balancer is justified by a specific constraint. The strongest reasons are usually capacity, availability, safer deployments, maintenance without full interruption, or protocol-aware routing. Use a load balancer when at least one of these conditions is real: - one application server cannot handle expected peak traffic; - one server failure would cause unacceptable downtime; - deployments should continue while other nodes serve traffic; - maintenance should not require taking the whole application offline; - application nodes can process requests independently; - separate hostnames, paths, protocols, or backend pools need different routing behavior. Do not add load balancing to hide a different bottleneck. It will not fix inefficient queries, a memory leak, a full disk, a saturated database, an unavailable external API, or local state that prevents another node from serving the next request. The key distinction is between **scaling a node** and **removing one node as the boundary**. If CPU or memory is the measured limit and a larger VM still meets the workload, vertical scaling is often simpler. If one-node failure or one-node throughput is the problem, horizontal scaling plus load balancing becomes more relevant. | Evidence | Better first move | |---|---| | One VM is CPU- or RAM-constrained | Optimize or resize the VM | | Database is the bottleneck | Tune or scale the database first | | Sessions and files are local | Externalize state before scaling out | | One-node failure is unacceptable | Add redundant backends and load balancing | | Deployments interrupt every user | Add multiple backends and draining | | Traffic is low and predictable | Keep the simpler single-node design | A load balancer should solve a measured architecture problem, not create one. ## A load-balancing decision framework keeps complexity proportional Before choosing a load-balancing design, answer eight questions. 1. **Goal:** Is the main requirement capacity, availability, deployment safety, maintenance, or routing? 2. **Protocol:** Is the traffic HTTP/HTTPS, TCP, UDP, TLS passthrough, or something else? 3. **State:** Can any healthy backend process the next request? 4. **Health:** What proves a backend is ready for production traffic? 5. **Failure capacity:** Can the remaining fleet absorb one backend failure? 6. **Connection behavior:** Are requests short, long-lived, streaming, or WebSocket-based? 7. **Security:** Where does TLS terminate, and which backend ports are reachable? 8. **Operations:** How are nodes added, drained, deployed, monitored, and removed? The answers determine whether the design needs a Layer 4 or Layer 7 load balancer, whether sticky sessions are acceptable, how aggressive health checks should be, and how much spare capacity must remain. A useful decision matrix is: | Requirement | Design implication | |---|---| | Route by hostname or URL path | Prefer Layer 7 behavior | | Distribute raw TCP or UDP connections | Prefer Layer 4 behavior | | Remove unhealthy app nodes | Configure meaningful health checks | | Deploy without interrupting requests | Use draining and readiness checks | | Survive one backend failure | Keep enough spare backend capacity | | Run several interchangeable app nodes | Externalize sessions and durable files | | Keep backends off the public internet | Use private networking and restricted firewall rules | **Two backends are not highly available if either backend requires more than half of total traffic capacity.** Failure capacity must be designed, not assumed. ## L4 and L7 load balancing solve different routing problems Layer 4 load balancing makes decisions using network and transport information such as IP addresses, ports, protocols, and connections. Layer 7 load balancing understands application-layer requests, most commonly HTTP and HTTPS. AWS documents Application Load Balancers as Layer 7 and Network Load Balancers as Layer 4. Google Cloud uses the same architectural distinction: Layer 4 routes from network and transport information, while Layer 7 can route using HTTP attributes such as headers and URIs. | Capability | Layer 4 | Layer 7 | |---|---|---| | Typical traffic | TCP, UDP, TLS and other transport traffic | HTTP and HTTPS | | Routing basis | Address, port, protocol, connection | Hostname, path, header, method, cookie | | Application awareness | Limited | High | | Common fit | Databases, game traffic, custom protocols, connection forwarding | Websites, APIs, application routing, microservices | | TLS options | Passthrough or termination depending on service | Commonly termination or re-encryption | Choose Layer 4 when the load balancer should distribute connections without interpreting the application request. Choose Layer 7 when routing depends on HTTP behavior. ### External and internal load balancing serve different boundaries An external load balancer accepts traffic from internet clients. An internal load balancer provides a stable entry point for services inside a private network. ```text Internet ↓ External load balancer ↓ Private web/API nodes ↓ private network Database, cache, queue, internal services ``` An internal load balancer can also sit between service tiers when several internal backends need one stable endpoint. Private placement reduces direct exposure, but authentication, firewall policy, TLS where required, and capacity planning still matter. ### Routing algorithms should match request behavior Common approaches include round robin, weighted round robin, least connections, and hash-based routing. Round robin fits similar backends and similar request durations. Least-connections behavior can fit workloads with longer or more variable connections. Weights are useful when backend sizes differ or traffic should move gradually. No routing algorithm can compensate for a shared dependency that is already overloaded. ## Health checks, failure capacity, and draining determine reliability A load balancer is only as useful as its definition of a healthy backend. A port-open check proves that something accepted a connection. A readiness check should prove that the application can safely receive new production traffic. A useful health endpoint is fast, deterministic, inexpensive, and strict enough to remove an unusable node without depending on every optional downstream service. | Check | Question | |---|---| | Liveness | Is the process running or recoverable? | | Readiness | Can this instance accept new production traffic? | | Dependency health | Are required downstream services available? | | Synthetic workflow | Can a representative user action complete? | AWS load-balancer documentation exposes configurable health-check intervals, timeouts, and healthy/unhealthy thresholds. Tune these to actual startup and failure behavior rather than copying one universal value. ### The all-backends-unhealthy case must be understood Load balancers differ in what happens when every backend fails health checks. Depending on the platform and configuration, traffic may stop, fail open, or return errors. Before production, verify what users see when every backend is unhealthy. This affects maintenance design, incident response, and whether a bad health-check rule can become a complete outage. ### Connection draining protects in-flight work When a backend is removed for deployment, maintenance, or scale-in, it should stop receiving new traffic while existing requests or connections finish. AWS describes this through deregistration delay and connection draining. A safe removal sequence is: 1. Stop sending new traffic to the node. 2. Allow routing state to propagate. 3. Let active requests or connections complete. 4. Stop application processes or workers safely. 5. Deploy, maintain, or terminate the node. 6. Return it only after readiness succeeds. The draining period should reflect real request duration. A short API request, a large upload, and a long-lived WebSocket connection do not have the same lifecycle. ### Failure capacity needs explicit headroom If three application servers run near saturation during normal traffic, losing one may overload the remaining two. Plan for backend failure, maintenance overlap, cache warming, and database connection redistribution. High availability is a capacity decision as well as a routing decision. ## Application state, TLS, and dependencies shape the design Load balancing works best when any healthy backend can serve the next request. | Local dependency | Better shared pattern | |---|---| | In-memory session | Shared session store or suitable token design | | User uploads | Object storage or approved shared storage | | Durable application files | External authoritative storage | | Background jobs | Shared queue with retry and ownership rules | | Shared cache | Distributed cache with defined loss behavior | | Local database | Separate database service or database VM | Sticky sessions can preserve compatibility for a legacy application, but they keep a user tied to one backend and can create uneven traffic. Use stickiness as a deliberate transition trade-off, not as proof that the application is stateless. Read [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) before adding application replicas. ### TLS placement creates a trust boundary Common TLS models include: | Model | Traffic path | |---|---| | Termination | HTTPS to load balancer, HTTP to protected backend | | Re-encryption | HTTPS to load balancer, HTTPS to backend | | Passthrough | Encrypted connection forwarded to backend | Termination simplifies public certificate handling and enables HTTP-aware Layer 7 routing. Re-encryption protects the backend path. Passthrough keeps TLS termination at the application but limits request-aware routing at the load balancer. When TLS terminates before the app, configure trusted proxy information carefully so the application recognizes the original scheme and client context without trusting spoofed headers from arbitrary sources. ### Scaling the app tier can expose a database bottleneck More application nodes commonly create more database connections, concurrent queries, lock contention, cache misses, queue consumers, and outbound API calls. A faster application tier can move the bottleneck into the data layer. Review connection pooling, query latency, storage performance, rate limits, and database recovery before assuming another app node improves the complete system. ## Deployment and monitoring practices make load balancing operable Multi-node traffic distribution changes deployment behavior. A single-node release may restart one service. A load-balanced release must consider version coexistence, traffic draining, database compatibility, and rollback. A basic rolling release is: 1. Drain one backend. 2. Deploy the new version. 3. Wait for readiness. 4. Return the node to service. 5. Continue with the next backend. During the rollout, old and new versions may run at the same time. Database schemas, session formats, queue messages, cache keys, and APIs should remain compatible across the transition. Read [Blue-Green vs Rolling Deployments](/learn/guides/blue-green-vs-rolling-deployments) for the release-strategy decision. ### Align timeouts across the request path A request may cross a client, CDN, load balancer, reverse proxy, app server, database, and external API. Each layer can have its own connection, idle, request, and response timeout. Document which layer should fail first. Avoid retry behavior at several layers that multiplies traffic during an incident, and do not automatically retry non-idempotent actions without an idempotency design. ### Monitor the load balancer and the backends separately Useful signals include: - request or connection rate; - p50, p95, and p99 latency; - frontend and backend error rates; - healthy and unhealthy backend count; - health-check failure reasons; - active connections; - timeout and reset counts; - backend CPU and memory saturation; - traffic distribution by node; - database connection pressure; - draining duration. Correlate these signals with deployments and application logs. A load balancer can be healthy while the application returns logical errors, and an unhealthy target can reflect a firewall, TLS, timeout, or app problem. ### Test failure, not only throughput A load test should represent real request mix, authentication, cache behavior, database queries, uploads, jobs, and external dependencies. Then remove one backend and verify that the remaining fleet carries traffic without unacceptable latency or errors. A load-balanced design succeeds when both throughput and failure behavior improve predictably. ## Raff-specific load balancing should follow a measured growth path Raff currently lists load balancers as part of its networking platform alongside VPC and related network services. The public status page also includes load balancers under network infrastructure. Because the dedicated product page still contains older launch-era copy, verify exact listener protocols, TLS behavior, routing features, limits, and current billing in the Raff dashboard or current documentation before implementation. A practical Raff growth path is: ```text Stage 1 One Raff VM App + reverse proxy Stage 2 Larger VM if CPU/RAM is the measured constraint Stage 3 Multiple stateless Raff VMs Load balancer Private networking Separate database or managed database Stage 4 Health checks + draining + monitoring Shared storage/state services Backups and tested recovery ``` A Raff multi-node application can combine: - [Raff VM](/products/raff-vm) for application servers; - [Load Balancers](/products/load-balancers) for traffic distribution; - [VPC](/products/vpc) for private backend communication; - [Security](/products/security) for network exposure controls; - [Object Storage](/products/object-storage) for shared uploads and assets; - [Data Protection](/products/data-protection) for recovery planning. The important decision is the sequence. First measure the bottleneck. Then make application nodes interchangeable. Then add load balancing when one node should no longer define throughput, availability, or deployment safety. Raff supports 15,000+ VMs, but a two-node application still needs enough spare capacity to survive one backend failure. ## Load-balancing readiness is measurable Use this checklist before treating a multi-node architecture as production-ready. ### Architecture - The reason for adding load balancing is documented. - The app can process requests on arbitrary healthy backends. - Sessions, files, and jobs are externalized where required. - Database and dependency headroom is measured. ### Routing and security - Layer 4 or Layer 7 behavior matches the protocol. - TLS termination and backend encryption are defined. - Backend ports are reachable only from approved sources. - Proxy headers are trusted only from the intended traffic layer. ### Health and lifecycle - Readiness checks represent real serving ability. - All-backends-unhealthy behavior is understood. - Draining is tested with real request durations. - New-node warm-up behavior is known. ### Reliability and operations - Remaining nodes can absorb one-backend failure. - Timeouts and retries are aligned across the path. - Deployments preserve version compatibility. - Monitoring distinguishes routing health from application health. - Database, storage, DNS, and external dependencies have separate recovery plans. :::cluster ## Conclusion Load balancing is appropriate when one application server should no longer define capacity, availability, deployment safety, or maintenance behavior. Choose Layer 4 or Layer 7 according to protocol and routing requirements. Build meaningful readiness checks, externalize state, preserve failure capacity, drain nodes safely, align timeouts, and monitor both the traffic layer and the application behind it. Continue with [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) if you are still deciding whether to scale out, or [Stateful vs Stateless Applications](/learn/guides/stateful-vs-stateless-applications) before adding interchangeable backends. :::cta Explore Load Balancers Distribute traffic across healthy application nodes when your workload is ready for a multi-server architecture. ::: ## Sources - [AWS Elastic Load Balancing API Overview](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/Welcome.html) - [AWS Application Load Balancer Health Checks](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html) - [AWS Target Registration and Deregistration](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-register-targets.html) - [Google Cloud Load Balancing Overview](https://cloud.google.com/load-balancing/docs/load-balancing-overview) - [Raff Load Balancers](/products/load-balancers) - [Raff VPC](/products/vpc) - Product state verified: 2026-08-07 --- ### Infrastructure Automation on Raff: Scripts, Cloud-Init, APIs, and IaC URL: https://rafftechnologies.com/learn/guides/automation-infrastructure-as-code-raff Description: Understand infrastructure automation on Raff across Terraform, API, CLI, cloud-init, credentials, drift, approvals, recovery, and operating boundaries. Infrastructure automation is an operating model that turns repeated cloud and server changes into versioned, reviewable workflows for provisioning, configuration, deployment, and recovery. **The practical goal is not to automate every infrastructure action. It is to give each layer one clear owner, make risky changes reviewable, and make repeated changes reproducible.** Raff Technologies supports 3,000+ customers and 15,000+ VMs, so the automation problem we care about is not whether a script can create a resource; it is whether a team can understand, repeat, audit, and recover the change later. At Raff, our decision rule is simple: **use the most declarative tool that fits the resource, but keep application releases, operating-system configuration, and cloud-resource provisioning as separate responsibilities.** Terraform, the Raff API, the Raff CLI, cloud-init, configuration management, and CI/CD are complementary layers rather than competing ways to automate everything. This guide explains how to choose between those layers, where Infrastructure as Code (IaC) fits, how to handle credentials and drift, and how to keep recovery separate from resource creation. For first-boot provisioning choices, see [Cloud-Init vs Custom Images vs One-Click Apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click). ## Infrastructure automation works best when each layer has one owner Automation becomes difficult to reason about when one script creates cloud resources, configures the operating system, deploys the application, changes DNS, runs a database migration, and decides whether the release succeeded. A clearer model separates responsibilities: | Layer | Primary job | Typical Raff interface | |---|---|---| | Cloud resources | Create and change VMs, storage, networking, access, backups | Terraform, REST API, CLI | | First boot | Establish the initial Linux baseline | cloud-init | | Ongoing server state | Maintain packages, files, users, services | configuration management or controlled scripts | | Application release | Build, deploy, validate, roll back | CI/CD pipeline | | Recovery | Restore data and service after failure | backups, snapshots, runbooks | | Verification | Confirm the intended result | health checks, monitoring, inventory | The separation matters because the layers change at different speeds. Application code may change several times a day. Network policy may change monthly. A server baseline may change with patching cycles. Backup recovery should remain available even if the provisioning workflow is broken. A useful architecture is: ```text Terraform / API / CLI ↓ cloud resources Cloud-init ↓ first-boot baseline Configuration management ↓ ongoing host state CI/CD ↓ application release Validation and recovery controls ``` The goal is not tool purity. The goal is clear ownership. ## A decision framework chooses the interface by state, scope, and risk Before automating a task, answer six questions. 1. **Layer:** Is the task cloud provisioning, first boot, host configuration, deployment, or recovery? 2. **State:** Does the team need a declared desired state or a one-time action? 3. **Frequency:** Is the change repeated often enough that manual work creates drift or delay? 4. **Risk:** Can the action delete data, interrupt production, or alter network access? 5. **Ownership:** Which repository, pipeline, or operator is authoritative for the change? 6. **Recovery:** How will the team reverse, rebuild, or restore if the automation is wrong? Use this decision matrix as a starting point: | Need | Better starting point | Why | |---|---|---| | Reviewable cloud-resource state | Terraform | Declarative plan and managed state | | Custom integration or workflow engine | REST API | Direct programmable interface | | One-off or operator-driven platform action | Raff CLI | Command-oriented and easy to inspect | | Initial Linux configuration | cloud-init | Designed for first-boot initialization | | Repeated host configuration | Configuration management | Maintains server state over time | | Frequent application releases | CI/CD | Keeps release lifecycle separate from infrastructure | | Recovery after data loss | Backup/restore workflow | Provisioning code does not restore workload data | **Infrastructure automation is safer when one change has one authoritative owner.** Two tools managing the same resource create drift even when both tools are individually correct. Start with read-only automation when the team is new to the platform: inventory, backup coverage checks, configuration reporting, or policy validation. Add mutating operations after ownership, scope, and recovery are clear. ## Terraform manages declarative cloud resources on Raff Terraform is strongest when supported infrastructure should be represented as desired state, reviewed before changes, reproduced across environments, and shared by a team. As verified on August 7, 2026, the Terraform Registry lists the official provider as `RaffTechnologies/raff`, with **v0.1.11** as the current release. Raff’s API changelog documents Terraform coverage across compute, volumes, snapshots, backups, backup schedules, VPCs, IPs, security groups, SSH keys, API keys, roles, members, projects, and catalog data sources. Treat the provider version as a current verification point, not a permanent recommendation. Pin an intentional version range, review release notes before upgrading, and confirm that every resource your architecture requires is supported by the live provider documentation. Terraform is a strong fit when the team needs: - pull-request review before infrastructure changes; - reproducible staging and production structures; - a plan showing intended changes before apply; - explicit ownership of supported cloud resources; - shared modules or environment definitions; - drift detection against declared infrastructure. Terraform is a weaker fit for frequent application releases, arbitrary shell configuration inside a server, or emergency actions that must happen outside the normal state workflow. ### Terraform state is part of the security boundary Terraform state maps configuration to real resources and can contain infrastructure identifiers or sensitive values. Protect it with restricted access, appropriate locking, versioning or backup, and separate production/non-production boundaries. A state file is not a workload backup. Losing a database cannot be repaired by recreating the Terraform resources around it. ### Plans need application-level validation afterward A successful infrastructure apply proves that the provider completed the requested resource operations. It does not prove the application is healthy, the database migration succeeded, or a customer workflow still works. Use post-change validation such as health checks, smoke tests, service metrics, and inventory checks before treating the automation as complete. ## The Raff API and CLI fit imperative workflows and custom integrations The REST API and CLI are better choices when the team needs a controlled action rather than a continuously managed desired state. Raff’s public API changelog identifies the API as **v1.0.0 beta**. Raff release notes and the changelog also confirm that the CLI is live, with command coverage for VMs, volumes, snapshots, backups, backup schedules, networking, IPs, VPCs, security groups, SSH keys, API keys, project membership, and catalog discovery. Use the **CLI** when a human operator, runbook, or pipeline benefits from a command-oriented workflow. Good examples include resource inspection, maintenance actions, incident-response commands, controlled backup operations, and small scripts. Use the **REST API** when building software that needs infrastructure logic of its own, such as: - an internal provisioning portal; - customer or project onboarding; - scheduled inventory and compliance checks; - an approval workflow; - a billing or operations integration; - a custom service that coordinates several Raff resources. The API and CLI should not casually change resources that Terraform already owns. If an emergency change is necessary, document it and reconcile the declarative configuration afterward. For key design and least-privilege patterns, read [How Small Teams Use Raff API Keys for Automation](/learn/guides/raff-api-keys-automation-small-teams). ## Cloud-init and configuration management control machine state at different times Cloud-init is a first-boot initialization layer, not a complete long-term configuration-management system. On Raff Linux VMs, cloud-init workflows are useful for instance-specific startup work such as users, SSH keys, packages, configuration files, host registration, and small bootstrap actions. Raff’s provisioning content also distinguishes cloud-init from custom images and one-click templates because they move configuration work to different stages of the VM lifecycle. Use cloud-init when values are decided at launch. Keep it small enough that a new VM can fail visibly and be replaced rather than becoming a partially configured snowflake. Use configuration management or controlled scripts when the team needs to maintain server state after first boot. That can include packages, files, service definitions, monitoring agents, permissions, and operating-system policy. A useful boundary is: ```text Cloud-init = establish the first usable baseline Configuration management = maintain the server baseline CI/CD = release the application ``` Avoid placing long-lived API keys, private keys, database passwords, or reusable production secrets directly inside cloud-init or committed scripts. Bootstrap logic can be retained in logs or instance-accessible files depending on the operating system and workflow. ## Credentials, drift, approvals, and observability determine automation safety Automation is not automatically safer than manual work. It becomes safer when the team can answer who changed what, with which credential, against which environment, and how the change was verified. ### Credentials should match the workflow Separate credentials by environment and purpose. A useful model may include distinct keys for: - production Terraform; - staging Terraform; - read-only inventory; - deployment automation; - backup verification; - human administration. Raff IAM provides roles, projects, API keys, and activity/audit controls. Use the narrowest practical scope and keep machine credentials out of source repositories and reusable examples. ### Drift needs a reconciliation process Drift occurs when real infrastructure no longer matches the system that is supposed to own it. Common causes include dashboard edits after Terraform deployment, emergency CLI/API changes, manual SSH configuration, stale inventory, and changes made by a second automation tool. Useful controls include scheduled Terraform plans without automatic apply, inventory reports, configuration checks, review of emergency changes, and an explicit rule for which system is authoritative. Do not automatically overwrite every drift event. Some drift represents a valid incident response or platform-side change that first needs investigation. ### Production changes need proportional approval A read-only inventory job does not need the same controls as deleting VMs or changing production firewall rules. Increase approval and verification as impact rises: | Change | Appropriate control | |---|---| | Read-only inventory | Automated execution | | Non-production VM creation | Automated with project limits | | Production backup check | Automated with alerts | | Production infrastructure plan | Review before apply | | Destructive resource replacement | Explicit approval and recovery check | | Network-access change | Review, validation, and rollback path | The automation should make risk visible before execution, not merely report failure afterward. ## Recovery and CI/CD should remain separate from infrastructure provisioning Infrastructure as Code can recreate supported resources. It cannot by itself restore database contents, uploaded files, application secrets, or external integrations. A complete recovery path may require: 1. recreate or repair infrastructure; 2. restore persistent data; 3. restore secrets through approved channels; 4. deploy the intended application version; 5. validate internal dependencies; 6. validate the customer-facing workflow; 7. restore routing or DNS when required. That sequence is why backups and IaC solve different problems. Raff Data Protection exposes backups, backup schedules, and snapshots through the API, CLI, and Terraform, but recovery still needs retention decisions and restore testing. Application deployment should also remain separate from Terraform wherever practical. A release pipeline owns builds, versioned artifacts, migrations, deployment, health validation, and rollback. Infrastructure tooling owns the resources on which that release runs. For release strategy, read [Blue-Green vs Rolling Deployments](/learn/guides/blue-green-vs-rolling-deployments). A small team does not need every automation layer at once. A reasonable maturity path is: ```text Dashboard for rare changes ↓ Read-only API/CLI automation ↓ Cloud-init for repeatable first boot ↓ Terraform for shared infrastructure state ↓ CI/CD and configuration management as release frequency grows ``` Introduce a layer when it removes a real operational problem. ## Raff-specific automation now has a broader supported surface Raff’s automation surface is materially broader than it was when this guide was first written. The June 2026 release notes state that the **Raff API, CLI, and Terraform provider are live**, while the API changelog documents continued expansion across compute, storage, networking, backup, catalog, and access-control resources. As verified on August 7, 2026: - the public API changelog identifies **v1.0.0 beta**; - the official Terraform Registry lists `RaffTechnologies/raff` **v0.1.11**; - VPCs and security groups are first-class API/CLI/Terraform resources; - volumes, snapshots, backups, and backup schedules have API/CLI/Terraform coverage; - API keys, roles, members, SSH keys, and project membership have programmatic interfaces; - Raff product pages explicitly describe API and Terraform support for VPC, volumes, and Data Protection. One documentation caveat remains: the generic Reference landing page still contains older “CLI coming soon” wording even though Raff’s changelog and release notes document the CLI as live. For automation planning, prefer the current command/resource documentation and changelog over stale landing-page copy. A practical small-team Raff model is: ```text Terraform ↓ VMs, networking, storage, access, recovery resources Cloud-init ↓ initial Linux baseline Configuration management ↓ ongoing host policy CI/CD ↓ application release Raff API / CLI ↓ integrations, inspection, controlled operational actions ``` Raff supports 15,000+ VMs, but scale does not change the core rule: the safest automation is the smallest system that makes ownership, review, verification, and recovery clearer. :::cluster ## Conclusion Infrastructure automation on Raff works best as a layered operating model rather than one large script. Use Terraform when supported cloud resources need declarative state and reviewable changes. Use the API or CLI for integrations and controlled imperative actions. Use cloud-init for first boot, configuration management for ongoing host state, and CI/CD for application releases. Keep credentials scoped, reconcile drift, and treat data recovery as a separate responsibility. Continue with [How Small Teams Use Raff API Keys for Automation](/learn/guides/raff-api-keys-automation-small-teams) for credential design or [Cloud-Init vs Custom Images vs One-Click Apps](/learn/guides/vm-provisioning-models-cloud-init-custom-images-one-click) for the VM provisioning decision. :::cta Explore Raff VM Deploy a VM and automate only the infrastructure layers your team actually needs. ::: **Sources** - [Raff API Changelog](https://docs.rafftechnologies.com/api-reference/changelog) - [Raff Reference](https://docs.rafftechnologies.com/reference/introduction) - [RaffTechnologies/raff Terraform Provider](https://registry.terraform.io/providers/RaffTechnologies/raff/latest) - [Raff Release Notes](/release-notes) - [Raff VPC](/products/vpc) - [Raff Volumes](/products/volumes) - [Raff Data Protection](/products/data-protection) - Automation surface verified: 2026-08-07 --- ### MSP Backup Strategy: DR, Retention, and Restore Planning URL: https://rafftechnologies.com/learn/guides/backup-dr-retention-policies-msp-managed-infrastructure Description: Understand MSP backup strategy, disaster recovery, retention, restore testing, client expectations, and recovery ownership for managed infrastructure. An MSP backup strategy is a documented operating model for protecting client workloads, retaining usable recovery points, restoring services, and proving that the recovery process works. **The strategy should begin with the client’s acceptable data-loss and downtime boundaries, not with a default backup schedule.** Raff Technologies supports 3,000+ customers and 15,000+ VMs from its US infrastructure. For managed service providers (MSPs), that infrastructure still needs a client-specific recovery model: what is protected, how far back recovery must reach, which systems return first, who performs the restore, and how the result is validated. At Raff, our decision rule for MSP backup planning is simple: **do not promise a recovery outcome that the operating team cannot demonstrate through a documented restore path.** A green backup job is useful evidence, but it is not the same as a recovered application, database, file service, or customer environment. This guide focuses on the MSP decision layer—recovery commitments, retention, isolation, restore evidence, and client ownership. Use [Cloud Server Backup Strategy](/learn/guides/cloud-server-backup-strategies) for the broader technical protection model and [Backup Retention Policy Explained](/learn/guides/backup-retention-policy-production-vms) for detailed retention design. ## MSP backup strategy starts with client recovery commitments MSPs operate several recovery relationships at once. A customer-facing application, internal file server, production database, and disposable test environment should not inherit the same protection policy simply because one backup product can protect all four. Start with five commitments for every protected workload: 1. **Recovery scope:** Which data, configuration, credentials, applications, and dependencies must return? 2. **Recovery point:** How much recent data can be lost? 3. **Recovery time:** How long may the service remain unavailable? 4. **Retention:** How far back might the client need a usable recovery point? 5. **Ownership:** Who approves, performs, validates, and communicates the recovery? These commitments become the service boundary. They are more useful than describing the backup tool itself. | Client question | MSP policy answer | |---|---| | What is protected? | Named workloads, data sets, configuration, and dependencies | | How much data can be lost? | Defined Recovery Point Objective (RPO) | | How quickly can service return? | Defined Recovery Time Objective (RTO) | | How far back can we recover? | Documented retention window and recovery tiers | | Who handles the incident? | Named technical and client-facing owners | | How do we know it works? | Restore-test evidence and recorded recovery time | NIST contingency-planning guidance treats business impact analysis, recovery strategies, testing, training, exercises, and plan maintenance as connected parts of the recovery lifecycle. An MSP policy should do the same rather than separating “backup” from the operational recovery process. ## A decision framework maps workloads to protection and recovery The central MSP decision is not “how many backups should we keep?” It is **which failure each client workload must survive and what evidence proves that protection exists.** | Workload pattern | Primary recovery concern | Practical protection direction | Evidence to retain | |---|---|---|---| | Customer-facing application | Downtime and recent state | VM recovery plus app/database-aware protection | Timed service restore | | Production database | Data integrity and point-in-time recovery | Database-aware backup plus infrastructure recovery | Database restore and application validation | | File or document server | Deleted, changed, or encrypted files | Historical file recovery plus protected server state | File and full-service restore tests | | Internal business app | Staff productivity | Retained recovery points and configuration protection | Recovery runbook and periodic restore | | Compliance-sensitive archive | Long-term availability and access control | Policy-defined retention and restricted deletion | Retention and access-review evidence | | Staging or rebuildable test system | Fast recreation | Minimal retention or rebuild automation | Rebuild documentation | Choose the smallest protection model that meets the client’s actual recovery requirement. A low-impact workload may need a straightforward scheduled backup and a documented rebuild. A transactional system may need database-aware backups, shorter recovery points, more frequent testing, and an independent copy that does not share the same access path as production. **For MSPs, recovery depth should increase with client impact, not with the number of features available in the backup platform.** ## Retention should follow detection delay and contractual needs Retention determines how far back the MSP can recover after a problem is discovered. This matters because incidents are not always noticed immediately. A failed deployment is obvious. A deleted file, incorrect data import, compromised credential, or application bug may remain unnoticed for days or weeks. Build retention from four inputs: - **Detection delay:** How long could damage remain unnoticed? - **Business history:** How far back might operations need to investigate or recover? - **Contractual or regulatory requirements:** Is a specific retention period required? - **Cost and data growth:** How much retained state can the client justify? Do not copy one retention calendar across every customer. A 7-day window may be adequate for a rebuildable server and inadequate for a client that reports data problems at month-end. Use tiers when they match the risk: ```text Frequent recent points ↓ Daily recovery history ↓ Weekly checkpoints ↓ Monthly or longer-term copies when justified ``` The exact numbers should be documented per workload rather than treated as universal recommendations. A retention policy should also define who can shorten the window, delete recovery points, place an emergency hold, and approve policy changes. Use [Backup Retention Policy Explained](/learn/guides/backup-retention-policy-production-vms) for the detailed schedule-versus-retention framework. ## Backup isolation and access controls reduce shared failure risk A backup can exist and still share too much risk with production. CISA’s ransomware guidance recommends maintaining offline, encrypted backups of critical data and regularly testing their availability and integrity. The operational principle is broader than ransomware: a recovery copy should survive the failure or compromise it is intended to address. Review whether production and recovery share: - administrator credentials; - deletion permissions; - the same VM or filesystem; - the same application identity; - the same storage access key; - the same network exposure; - the same person as the only recovery-key holder. The appropriate degree of separation depends on the client’s risk. Not every small workload needs an elaborate multi-account design, but important recovery points should not be removable by the same routine application process that writes production data. A practical MSP access model is: ```text Production workload ↓ restricted backup identity Recovery destination ↓ separate restore permission Authorized MSP recovery operator ↓ Controlled restore environment ``` Protect encryption keys, repository passwords, certificates, and credentials required during recovery. A technically complete backup is not useful if the credentials needed to restore it disappeared with the failed server. ## Restore testing turns backup evidence into service readiness Backup completion proves that a protection process reported success. Restore testing proves that the MSP can use a recovery point. A meaningful test should verify the workload, not only one file. Depending on the service, that may include: 1. locating the correct recovery point; 2. creating replacement compute or storage; 3. restoring data; 4. recovering configuration, secrets, and certificates; 5. reconnecting private services or databases; 6. starting the application; 7. validating authentication and critical workflows; 8. recording recovered-data age; 9. recording total recovery time; 10. documenting problems and updating the runbook. The MSP should retain evidence such as: - test date; - client/workload; - recovery point used; - person performing the test; - restore duration; - validation checks; - RPO/RTO result; - unresolved findings; - next review date. A failed restore test is valuable if it happens before a real incident and results in a corrected process. Use [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms) for the full verification workflow. ## Client communication and ownership make the policy operable MSP backup agreements fail when the technical policy and client expectation describe different outcomes. Every managed workload should have a short recovery record that both sides can understand: | Field | Example of what to document | |---|---| | Protected service | Accounting application and database | | Backup owner | MSP operations team | | Client approver | Named business owner | | RPO | Approved maximum data-loss window | | RTO | Approved service-recovery window | | Retention | Recent and historical recovery tiers | | Exclusions | Unprotected temporary files or unsupported data | | Restore validation | Login, database query, file access, critical transaction | | Escalation | Who is contacted and in what order | Avoid vague promises such as “daily backup” when the client expects “service restored within two hours.” Those statements measure different things. The MSP should also distinguish: - backup creation from disaster recovery; - infrastructure restoration from application validation; - retention from legal archiving; - replication from historical backup; - provider responsibility from MSP responsibility; - MSP responsibility from client responsibility. This is especially important when third-party SaaS applications, databases, identity systems, or external storage services are part of the workload. The runbook should identify dependencies that the MSP cannot restore directly. ## Raff-specific MSP backup design keeps recovery layers explicit Raff provides compute, private networking, Data Protection, Object Storage, and other infrastructure building blocks that an MSP can combine according to client requirements. Raff’s current platform materials also show backups and snapshots as part of the VM data-protection model; exact schedules, retention, exclusions, restore behavior, and commercial terms should be verified in the live dashboard before they become part of a client commitment. A practical Raff-oriented MSP model is: ```text Client workload on Raff VM ↓ VM-level recovery points ↓ Database/application-aware copies where required ↓ Independent files or archives where justified ↓ Controlled restore environment ↓ MSP validation + client handoff ``` Use [Raff Data Protection](/products/data-protection) for the VM protection layer. Use [Private Cloud Networks](/products/private-cloud-networks) when internal recovery traffic should avoid unnecessary public exposure. Use [Object Storage](/products/object-storage) when backup tooling or applications need an S3-compatible destination for independent files or archives. **Raff Technologies supports 3,000+ customers and 15,000+ VMs, but each MSP-managed workload still needs its own recovery owner and tested restore path.** The product should support the policy, not define it. Write the RPO, RTO, retention, ownership, and validation requirements first; then configure the Raff controls that meet those requirements. ## MSP backup readiness is measurable Before calling a client environment recovery-ready, confirm: ### Policy - Protected workloads are inventoried. - RPO and RTO are written. - Retention is documented by workload. - Exclusions are explicit. ### Access and isolation - Backup credentials use limited permissions. - Important recovery copies do not rely only on the failed workload. - Restore credentials and encryption keys are recoverable. - Deletion permissions are restricted appropriately. ### Operations - Backup failures and stale recovery points are monitored. - Each workload has a named owner. - Recovery order and dependencies are documented. - Client escalation and approval paths are known. ### Evidence - A restore has been tested. - The restored service passed defined validation checks. - Measured recovery fits the approved objectives. - Findings from the test were closed or accepted. An MSP backup strategy is mature when the team can explain the policy, execute the recovery, and show evidence that the result met the client’s requirement. :::cluster ## Conclusion MSP backup strategy is fundamentally a recovery commitment. Start with the client’s acceptable data loss, downtime, retention history, and workload priority. Then choose backup layers, isolation, access controls, and testing that can deliver that outcome. Do not use one retention schedule for every customer, and do not treat successful backup jobs as proof of recoverability. The most useful MSP evidence is a documented restore that returns the expected service within the agreed recovery boundaries. Continue with [Cloud Server Backup Strategy](/learn/guides/cloud-server-backup-strategies) for the underlying protection architecture and [Restore Testing Checklist](/learn/guides/restore-testing-checklist-production-vms) for the verification process. :::cta Explore Data Protection Build recovery points and restore workflows around each client’s documented recovery requirements. ::: ## Sources - [NIST SP 800-34 Rev. 1: Contingency Planning Guide for Federal Information Systems](https://csrc.nist.gov/pubs/sp/800/34/r1/upd1/final) - [CISA StopRansomware Guide](https://www.cisa.gov/stopransomware/ransomware-guide) - [Raff Data Protection](/products/data-protection) - [Raff Pricing](/pricing) - Product and guidance state verified: 2026-08-07 --- ### Cloud Server Performance Bottlenecks: CPU, Memory, Disk I/O, and Network URL: https://rafftechnologies.com/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network Description: Diagnose cloud server performance bottlenecks across CPU, memory, disk I/O, network, databases, and dependencies before resizing or scaling. Cloud server performance bottlenecks are resources or dependencies that limit latency, throughput, or stability by forcing useful work to wait. The busiest metric is not automatically the bottleneck. A server can run at high CPU and still meet every latency target, while another can show moderate CPU and feel slow because requests are waiting on memory reclaim, storage, database locks, DNS, or an external API. The diagnostic question is therefore: **where does the affected work wait, and does that wait control an outcome users or operators care about?** Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff infrastructure reviews, a recurring diagnostic mistake is reacting to the highest utilization graph before correlating it with request latency, queue growth, failed jobs, or service restarts. This guide is the diagnostic branch of Raff’s VM sizing and performance content. Start with [How to Choose the Right VM Size for Your Workload](/learn/guides/choosing-right-vm-size) for initial sizing, then use this framework when a running server becomes slow, unstable, or difficult to scale. ## Cloud server performance bottlenecks are waiting problems A performance bottleneck is the resource, dependency, or serialized step that controls how quickly the workload can complete useful work. That distinction matters because utilization alone is ambiguous. High utilization can mean a resource is being used efficiently. Low utilization can hide a blocked workload. The stronger diagnosis combines **impact** with **pressure or wait evidence**. Linux Pressure Stall Information (PSI) is useful here because it reports time tasks lose while waiting for CPU, memory, or I/O resources. It exposes those signals through `/proc/pressure/cpu`, `/proc/pressure/memory`, and `/proc/pressure/io` on supported systems. A practical bottleneck model has four layers: 1. **Impact:** What is slow, failing, or backing up? 2. **Wait:** Where is work spending time instead of progressing? 3. **Cause:** Why is that resource or dependency constrained? 4. **Decision:** Should the team optimize, resize, separate, or scale? **Raff supports 3,000+ customers and 15,000+ VMs, but the correct resize decision still begins with measured workload pressure.** The same model works for an API, database, CI runner, worker queue, self-hosted application, or mixed production VM. ## The diagnostic framework connects symptoms to constrained resources Start from the affected workload, not from a dashboard panel. | Symptom | Evidence to inspect | Likely constraint | Better first decision | |---|---|---|---| | p95/p99 latency rises under load | CPU pressure, run queue, traces, DB time | CPU, lock, or dependency | Find the dominant wait before resizing | | Queue age keeps growing | CPU, worker throughput, downstream latency | Compute or downstream capacity | Add useful concurrency or remove downstream limit | | Processes restart or disappear | Available memory, swap, OOM events | Memory pressure or leak | Reduce demand, fix leak, or add RAM | | Database slows during writes | Query time, locks, I/O latency, checkpoints | Query, lock, memory, or storage | Diagnose the database path first | | Uploads or downloads are slow | RTT, loss, retransmits, throughput | Network path or application limit | Test path before adding compute | | Deployments destabilize the server | CPU, RAM, I/O during deploy window | Missing operating headroom | Resize or change deployment behavior | | Workers hurt web latency | CPU, memory, I/O, queue activity | Role contention | Limit or separate workers | | Performance drops after a release | Version marker, traces, DB queries, errors | Application regression | Roll back or isolate the change | Use at least one workload-impact signal and one resource/dependency signal. Examples: - p99 latency rises **and** CPU PSI rises; - queue age grows **and** worker CPU stays saturated; - service restarts occur **and** OOM events appear; - database time rises **and** storage latency increases; - request duration rises **and** one external API dominates traces. In Raff infrastructure work, this correlation is more useful than a universal CPU or RAM percentage. A fixed threshold can trigger too early for a batch workload and too late for a latency-sensitive service. ### A healthy baseline makes incident data useful Compare equivalent workload periods. A normal weekday, backup window, deployment, campaign, and batch job may have different healthy profiles. Record at least: - request or job latency; - traffic and concurrency; - queue depth or oldest-job age; - CPU activity and pressure; - available memory, swap, and OOM events; - storage latency and throughput; - network latency, throughput, loss, and retransmissions; - database query and lock time; - external dependency duration. Percentiles are usually more useful than averages for user-facing latency because a good average can hide a small group of very slow requests. ## CPU and memory bottlenecks require different fixes CPU and memory are often grouped together as “the VM is too small,” but their failure patterns are different. ### CPU pressure appears when runnable work cannot progress fast enough CPU becomes the constraint when useful compute demand exceeds the processing capacity available within the workload’s timing requirement. Typical signals include: - sustained CPU pressure during the affected period; - runnable work accumulating; - p95/p99 latency rising with CPU demand; - queue or worker backlog growing while CPU remains busy; - builds or tests taking longer under equivalent work; - one thread saturating while machine-wide CPU looks moderate. Short CPU spikes are not enough. A package update, deployment, cache warm-up, or brief traffic burst can consume available CPU without creating a real service problem. Add vCPU when the workload can use more parallel compute and the outcome improves. Optimize code when profiling reveals avoidable CPU work. Evaluate dedicated compute when sustained CPU timing consistency matters more than additional shared-vCPU count. For the narrower core-count decision, use [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms). For CPU allocation, use [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). ### Memory pressure appears when the working set no longer fits safely Linux uses otherwise idle RAM for useful cache, so “used memory” alone is not a reliable sizing verdict. Stronger memory signals include: - low available memory during normal peaks; - repeated swap-in and swap-out activity; - memory PSI or reclaim stalls; - out-of-memory events; - container or process restarts; - growing process memory that does not return after load falls; - database or cache behavior degrading as memory pressure rises. Separate three cases: | Pattern | Meaning | Better response | |---|---|---| | Stable working set is too large | Legitimate capacity demand | Add RAM | | Memory grows without stabilizing | Leak or unbounded behavior | Fix application/configuration | | Several services compete for RAM | Role contention | Add memory or separate services | Sustained swap can turn a memory shortage into a storage-latency problem. More CPU does not solve that chain. Use [HiMem VMs Explained](/learn/guides/himem-vms-explained) when the workload needs more RAM per vCPU. ## Disk I/O and network bottlenecks need path-level evidence Storage and network problems are easy to misdiagnose because both can leave CPU relatively idle while requests remain slow. ### Disk capacity and disk performance are separate constraints A filesystem can have free space and still suffer high I/O latency. It can also provide fast I/O and fail because capacity or inodes are exhausted. Inspect storage across four dimensions: | Dimension | Evidence | |---|---| | Capacity | Free space, inode use, growth rate, retention | | Latency | Read/write completion time | | Throughput | Bytes transferred per second | | Queueing | Outstanding operations and wait time | Databases, write-heavy logs, backups, analytics, file processing, and multi-service VMs can create storage contention. High I/O wait is supporting evidence, not a complete diagnosis. Correlate it with device latency, queueing, database time, or job duration. Red Hat’s performance guidance similarly treats `vmstat` as a starting signal and `iostat` as a tool for identifying the responsible block device when I/O is implicated. Common responses include: - fix inefficient queries or indexes; - reduce unnecessary logging and temporary writes; - move uploads or archives away from the application disk; - change backup timing; - separate application and database storage paths; - add or expand storage when capacity is the actual constraint. ### Network bottlenecks include latency, loss, and dependency behavior Bandwidth is only one network dimension. Inspect: - round-trip time; - packet loss and retransmissions; - achieved throughput; - DNS lookup time; - TLS and connection-establishment time; - proxy or load-balancer timing; - external API duration; - application upload/download limits. Test each relevant path separately: user-to-application, application-to-database, service-to-service, and application-to-external-provider. This distinguishes a slow server from a slow route, remote dependency, or client geography problem. **Raff Cloud Servers include a 3 Gbps public port and unmetered bandwidth, so network diagnosis should still focus on measured path behavior.** Current Raff pricing documentation also lists private networking as included, which can keep internal service traffic off the public path where the architecture requires it. ## Databases and application behavior can imitate infrastructure bottlenecks A larger VM cannot repair every slow application. Database and application behavior frequently create symptoms that look like CPU, memory, disk, or network shortages. | Application or database pattern | Visible infrastructure symptom | |---|---| | Missing database index | High query time and storage activity | | Lock contention | Slow requests with moderate VM utilization | | Synchronous external API | Low CPU with long request latency | | Unbounded worker concurrency | CPU, RAM, and I/O contention together | | Excessive retries | Network and downstream amplification | | Excessive logging | Storage growth and write latency | | Cache miss storm | Database and network pressure | | Memory leak | Rising RAM usage and eventual OOM | | Serial processing path | One busy thread with idle vCPUs | Review database query duration, lock time, connection behavior, cache effectiveness, checkpoint/write activity, and backup traffic beside host metrics. Adding application servers can make a database bottleneck worse by increasing concurrency against the same constrained data layer. Likewise, moving from 2 vCPU to 4 vCPU can expose a downstream bottleneck without improving total request latency. Use [Application Observability for Small Teams](/learn/guides/observability-small-teams-metrics-logs-traces) when metrics, logs, and traces need to be connected across one user request or background job. ## The decision is optimize, resize, separate, or scale Once the bottleneck is identified, choose the smallest architectural change that addresses it. | Evidence | Better move | Why | |---|---|---| | Inefficient code/query dominates | Optimize | Capacity would hide avoidable work | | One VM resource is consistently constrained | Resize vertically | One server still fits the operating model | | App and database compete repeatedly | Separate roles | Independent resource and recovery boundaries help | | Workers harm user-facing traffic | Limit or separate workers | Protect request-path capacity | | Stateless app tier reaches repeatable capacity | Scale horizontally | Traffic can be distributed across nodes | | Short bursts exceed headroom | Buffer, rate-limit, resize, or scale | Burst handling is the actual requirement | | External dependency dominates | Cache, queue, or redesign carefully | Local compute does not remove remote wait | | No clear correlation exists | Improve observability | Architecture changes would be guesswork | Vertical resizing is usually the lowest-complexity move when one VM still provides the right deployment and recovery boundary. Separation becomes useful when roles need different scaling, deployment, security, or recovery behavior. Horizontal scaling becomes useful when the application can distribute traffic and the data layer can support the additional concurrency. Use [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) after diagnosis identifies capacity as the problem rather than an application defect. ### Validate the change against the original symptom Performance work becomes unreliable when several variables change at once. For a controlled change: 1. record the affected workload and healthy baseline; 2. select one bottleneck hypothesis; 3. change one variable where practical; 4. repeat an equivalent workload; 5. compare latency, throughput, errors, queueing, and resource pressure; 6. check whether the bottleneck moved downstream. A successful change improves the workload outcome. A prettier utilization graph by itself is not success. ## Raff supports diagnosis before capacity changes Raff Cloud Servers give teams full server access, NVMe storage, monitoring, shared-vCPU General Purpose options, dedicated-vCPU CPU-Optimized options, and a resize path for CPU, RAM, and storage. Current public pricing documentation lists a **3 Gbps public port**, unmetered bandwidth, private networking, DDoS protection, browser console/SSH, API/Terraform access, and live monitoring as included Cloud Server capabilities. That supports an evidence-first workflow: - inspect operating-system and application behavior; - identify whether CPU, memory, storage, network, database, or another dependency controls the outcome; - optimize application behavior when capacity is not the real problem; - resize when the current VM resource profile is genuinely constrained; - use [Volumes](/products/volumes) when storage needs an independent capacity boundary; - separate workers or databases when resource contention becomes repeatable; - move toward horizontal scaling only after the application and data paths can support it. Raff does not remove the need to measure. A 3 Gbps port does not guarantee an external API will be fast, and NVMe storage does not make an inefficient query cheap. Platform capacity and workload design must be diagnosed separately. For current VM sizes and plan details, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained) and verify the live [pricing page](/pricing) before deployment. ## The bottleneck is the constraint that controls the workload outcome Cloud server performance diagnosis is most reliable when it begins with a real symptom and follows the wait path to its cause. CPU pressure points toward more compute only when runnable work is delayed. Memory pressure points toward more RAM only when the working set cannot remain resident safely. Storage and network require path-level latency, throughput, and queue evidence. Databases and application dependencies must be checked before infrastructure is blamed. The final decision should be proportionate: optimize unnecessary work, resize a constrained VM, separate roles that should no longer compete, or scale a stateless service when one node has reached a repeatable capacity limit. Return to [How to Choose the Right VM Size for Your Workload](/learn/guides/choosing-right-vm-size) for the broader sizing framework, or continue with [Horizontal vs Vertical Scaling](/learn/guides/horizontal-vs-vertical-scaling-cloud) when the diagnosis shows that additional capacity is the correct next move. :::cta Explore Raff VM Choose a VM profile you can measure and resize as CPU, memory, storage, and application requirements become clear. ::: ### Sources - [Linux Kernel: Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) - [Linux Kernel: Memory Management](https://docs.kernel.org/admin-guide/mm/) - [Red Hat Enterprise Linux 9: Monitoring and Managing System Status and Performance](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/monitoring_and_managing_system_status_and_performance/monitoring_and_managing_system_status_and_performance) - [Raff Pricing](/pricing) - [Raff Cloud Servers](/products/raff-vm) --- ### Infrastructure Readiness for Fundraising: Technical Diligence URL: https://rafftechnologies.com/learn/guides/infrastructure-readiness-fundraising-technical-diligence Description: Understand infrastructure readiness for fundraising across architecture, security, recovery, cloud cost, documentation, and technical diligence evidence. Infrastructure readiness for fundraising is the ability to show that a startup’s production systems are understandable, controlled, recoverable, and economically aligned with the company’s next stage of growth. Technical diligence does not require an early-stage company to look like a large enterprise platform team. It requires the founders to know what is running, who owns it, how customer data is protected, what happens when systems fail, and which technical risks could affect growth after the round. Raff Technologies supports more than **15,000 VMs**, and the same principle applies to fundraising-stage infrastructure: a simple system that can be explained and operated is stronger than a complex system nobody can defend. This guide belongs under [SaaS Infrastructure Checklist Before Your First Enterprise Customer](/learn/guides/startup-infrastructure-checklist-enterprise-customer). That pillar covers the wider production-readiness baseline; this guide narrows the lens to investor and technical due diligence before or during a fundraising process. ## Technical diligence evaluates risk, not architecture size A diligence reviewer is rarely asking whether the startup has the most advanced architecture. The real question is whether the current architecture creates hidden business risk. Typical concerns include: - Can the system support the next stage of customer growth? - Does one person hold critical infrastructure knowledge? - Are production access and customer data controlled? - Can the company recover from common failures? - Are cloud costs visible and connected to gross margin? - Is technical debt known and prioritized? - Can the founders explain what they would improve after the round? A startup can be technically credible with one application VM, one database, backups, monitoring, and a documented deployment process. It can also look risky with many services if nobody knows why they exist or what happens when one fails. The strongest diligence answer is usually not “we have no risk.” It is: > We know our current risks, we know which ones matter at this stage, and we have owners and triggers for the next improvements. That distinction is important because investors are evaluating execution quality as much as infrastructure itself. ## The fundraising readiness framework covers eight evidence areas Use this framework before fundraising starts. A startup does not need perfect scores in every area, but it should be able to explain gaps without discovering them for the first time in the diligence meeting. | Area | What reviewers want to understand | Credible early-stage evidence | Red flag | |---|---|---|---| | Architecture | How production actually works | Current diagram and component inventory | Nobody can describe production accurately | | Access | Who can reach production | Named accounts, MFA, limited admin access | Shared credentials or unknown access | | Security | How exposure and secrets are controlled | Firewall rules, patch owner, secret-handling process | Public admin surfaces and secrets in code | | Reliability | What happens when something fails | Monitoring, backups, restore path | No tested recovery route | | Data | Where important data lives | Data map, access boundaries, backup scope | Sensitive data copied without control | | Deployment | How changes reach production | Documented release and rollback path | One-person manual process with no rollback | | Cost | How infrastructure spend grows | Monthly cost view and known drivers | Surprise bills and no usage model | | Ownership | Who operates each critical area | Named owners and escalation path | “Ask the CTO” is the operating model | A useful decision rule is simple: **if a technical risk would be difficult to explain in one clear paragraph, it probably needs documentation or remediation before diligence begins.** This framework should remain proportional to stage. A seed-stage company may not need multi-region failover or a platform engineering team. It should still know who owns production, where data is stored, how backups work, and what the next scaling constraint is. ## Architecture and documentation should tell the same story The first diligence package should make production easy to understand. At minimum, prepare: - a one-page architecture diagram; - production component inventory; - public and private network boundaries; - data storage locations; - major third-party dependencies; - deployment path; - backup and recovery path; - monitoring and alert ownership; - known scaling constraints; - known technical debt. The diagram should reflect the real environment, not the architecture the team hopes to build later. For example, this is a perfectly credible early-stage architecture when it matches the workload: ```text Internet ↓ Reverse proxy / load balancer ↓ Application VM ↓ Database ↓ Backup / recovery layer ``` A reviewer can ask meaningful questions about this system. Who can administer the VM? Is the database public? What is backed up? What breaks first as traffic grows? How does deployment rollback work? Those are better diligence questions than trying to impress reviewers with unnecessary services. Documentation also reduces key-person risk. The company should be able to operate critical systems without relying on one founder’s memory. That does not require a large internal wiki. A small set of accurate documents is more useful than a large set of stale documents. For the wider production baseline, the parent [SaaS Infrastructure Checklist](/learn/guides/startup-infrastructure-checklist-enterprise-customer) covers environment separation, secrets, access, monitoring, and incident ownership in more detail. ## Security and customer data need defensible controls Technical diligence often becomes more detailed when the company stores customer data, sells to larger customers, or operates in a regulated market. The correct goal is not to claim every possible security control. It is to show what is currently implemented and where the responsibility sits. A diligence-ready security summary should answer: | Security area | Evidence to prepare | |---|---| | Production access | Named admins, MFA, SSH/RDP policy, access removal process | | Network exposure | Public ports, firewall rules, private services | | Secrets | Storage method, rotation process, environment separation | | Patching | Owner, review cadence, emergency patch process | | Customer data | Storage location, access boundaries, retention approach | | Logging | Authentication and application events retained where appropriate | | Incident handling | Owner, containment path, communication process | | Vendors | Critical subprocessors and infrastructure dependencies | NIST Cybersecurity Framework 2.0 is useful here because it frames security around **Govern, Identify, Protect, Detect, Respond, and Recover** rather than around buying specific tools. That model is practical for startups because it makes ownership visible. Formal certifications may become commercially important later, but they should never be implied before they exist. If a customer or investor asks about SOC 2, ISO 27001, penetration testing, data residency, or a contractual control, answer with the current state and roadmap rather than a broad “we are compliant” statement. The same principle applies to Raff: provider controls and customer controls are different layers. Infrastructure can supply networking, VM, firewall, IAM, and recovery capabilities; the startup still owns application security, data handling, access decisions, and customer commitments. ## Reliability should be demonstrated with recovery evidence Reliability claims are stronger when they are supported by recovery evidence. A diligence reviewer may ask: - What happens if the application VM fails? - What happens after a bad deployment? - How recent are the backups? - When was restore last tested? - How much data can the business afford to lose? - How long can the service remain unavailable? - Who becomes the incident owner? The important distinction is between **availability** and **recoverability**. High availability reduces interruption during some failures. Disaster recovery provides a path back after a larger failure. Backups protect recoverable state. Application rollback addresses bad releases. These are different controls and should not be described as one generic “backup strategy.” A small startup may reasonably choose backups and tested recovery before paying for a fully redundant architecture. That is a stage-appropriate trade-off if the team understands the business impact. Use explicit RPO and RTO thinking: | Question | Example diligence answer | |---|---| | How much data can we lose? | Up to one hour of transactional data | | How long can we be offline? | Four-hour recovery target | | What is protected? | Database, uploaded files, configuration, critical secrets | | Where is recovery documented? | Runbook owned by infrastructure lead | | When was it tested? | Date and outcome recorded internally | Do not invent a recovery target because it sounds professional. A credible target is one that the architecture and operating process can actually support. For the trade-off between uptime and recovery architecture, see [High Availability vs Disaster Recovery for Small Teams](/learn/guides/high-availability-vs-disaster-recovery-small-teams). ## Cloud cost and team dependency affect the investment story Infrastructure diligence is also financial diligence. A reviewer may not care whether the company spends $500 or $5,000 per month in isolation. They care whether the founders understand why the number changes and whether the cost model supports the business. Prepare a monthly view of: - production compute; - database spend; - storage growth; - backup and snapshot storage; - bandwidth or egress where applicable; - observability; - staging and development environments; - managed services; - support or MSP cost. Then connect those costs to business drivers. For example: ```text More customers ↓ More API traffic + stored data ↓ Higher compute / database / storage usage ↓ Known infrastructure cost per growth stage ``` That is easier to defend than a bill that increases without a clear usage explanation. The same applies to team dependency. A startup becomes operationally risky when one person is the only person who can deploy, recover the database, change DNS, access production, or understand billing. The solution is not necessarily hiring a platform team. It can be: - documented deployment steps; - named backup owner; - shared but controlled administrative access; - infrastructure inventory; - a second person who understands recovery; - simple runbooks for high-impact operations. From a founder-operator perspective, the strongest fundraising posture is not “we built everything.” It is “we can explain what we chose not to build yet, why that is acceptable, and what growth signal will trigger the next investment.” For spend planning, use [Cloud Budget Guardrails for Startups](/learn/guides/cloud-budget-guardrails-startups-vm-spend-drift). ## Technical debt is credible when it has owners and triggers Every startup has technical debt. Diligence becomes uncomfortable when debt is hidden, unowned, or discovered by the reviewer before the founders acknowledge it. A useful technical-debt register is short and specific. | Current constraint | Why it is acceptable now | Trigger for change | |---|---|---| | Single application VM | Current traffic and recovery model fit | Split when CPU, availability, or deployment risk crosses threshold | | Manual deployment approval | Small engineering team | Add automation as deploy frequency increases | | Basic monitoring | Current service count is small | Expand when customer-facing dependencies increase | | No multi-region architecture | Current availability requirement does not justify cost | Revisit when contractual or business continuity needs change | | Founder-owned operations | Early team structure | Add shared ownership before scaling engineering headcount | This format shows three things investors care about: 1. the team knows the constraint; 2. the team knows why it exists; 3. the team knows when the constraint becomes unacceptable. That is more persuasive than a roadmap full of infrastructure projects with no business trigger. ## The diligence packet should reduce uncertainty Before fundraising, prepare one concise technical diligence packet rather than answering the same questions from scratch in every call. A practical packet includes: | Item | Include | |---|---| | Architecture diagram | Traffic flow, app, database, storage, external dependencies | | Infrastructure inventory | Production VMs, databases, storage, environments, regions | | Security summary | Access, secrets, firewall, patching, incident owner | | Data map | Customer data locations, access boundaries, backup scope | | Reliability summary | Monitoring, backups, restore process, RPO/RTO assumptions | | Deployment summary | Release path, approvals, rollback | | Cost summary | Monthly spend, growth drivers, major cost risks | | Technical debt | Known constraints, owners, remediation triggers | | Vendor list | Critical cloud and SaaS dependencies | | Roadmap | Infrastructure improvements tied to business milestones | The packet is not a marketing asset. It is an uncertainty-reduction asset. Keep the language factual. Avoid claims such as “fully secure,” “zero downtime,” “enterprise-grade,” or “compliant with everything.” Those phrases create questions that evidence may not support. A smaller, accurate control set creates more trust than a polished but unverifiable story. ## Raff supports a simple diligence-ready infrastructure model Raff fits startups that want to keep the infrastructure layer understandable while retaining VM-level control. Current Raff VM positioning includes Linux and Windows server options, NVMe storage, unmetered VM bandwidth, 3 Gbps ports, firewall and DDoS protection capabilities, backup and snapshot options, and full administrative access where the product requires it. Linux VM pricing currently starts at **$4.99/month**, and Raff supports **15,000+ VM deployments** across its platform. For fundraising diligence, those capabilities matter only when they map to evidence: | Diligence area | Raff building block | Startup responsibility | |---|---|---| | Compute | Raff VM | OS, runtime, sizing, application configuration | | Network boundary | Firewall and private networking | Public exposure and access policy | | Recovery | Data Protection | Backup scope, retention choice, restore testing | | Access | Platform and server access controls | User lifecycle and least privilege | | Scaling | VM resize or architecture expansion | Capacity thresholds and application design | | Cost | Published infrastructure pricing | Budget model and growth assumptions | This is the useful founder story: the provider supplies infrastructure primitives, while the startup owns the operational decisions investors are evaluating. Raff should not be presented as a shortcut to diligence readiness. A VM provider cannot create documentation, technical ownership, recovery tests, or security processes for the startup. It can make the infrastructure layer easier to understand and price while the team builds those controls around the application. ## Conclusion Infrastructure readiness for fundraising is evidence that the company understands and controls the technical risks behind its growth plan. The goal is not to make an early-stage startup look like a large enterprise. The goal is to show that architecture, access, data, recovery, cloud cost, and technical debt are visible and owned. Prepare the architecture diagram, access summary, recovery evidence, monthly infrastructure cost view, deployment notes, and technical-debt register before diligence begins. If a gap is known but not yet fixed, document why it is acceptable now and what milestone triggers remediation. Use the parent [SaaS Infrastructure Checklist Before Your First Enterprise Customer](/learn/guides/startup-infrastructure-checklist-enterprise-customer) for the wider production-readiness baseline, then review [Cloud Budget Guardrails for Startups](/learn/guides/cloud-budget-guardrails-startups-vm-spend-drift) for the cost side of the diligence story. :::cta Explore Raff VM Review Raff VM options when your fundraising-stage workload needs a clear, predictable infrastructure foundation. ::: ### Sources - [NIST Cybersecurity Framework 2.0](https://www.nist.gov/cyberframework) - [AICPA System and Organization Controls](https://www.aicpa-cima.com/resources/landing/system-and-organization-controls-soc-suite-of-services) - [Raff VM](/products/raff-vm) - [Raff Data Protection](/products/data-protection) - Date verified: 2026-08-08 --- ### Cloud VM Machine Classes Explained: Choosing the Right Fit URL: https://rafftechnologies.com/learn/guides/cloud-vm-machine-classes-explained Description: Understand cloud VM machine classes, compare General Purpose, CPU-Optimized, and high-memory profiles, and choose the right fit for real workloads. Cloud VM machine classes are server categories that group CPU allocation, memory ratio, and storage capacity around different workload patterns. Choosing a class is not the same as choosing a bigger server. A balanced web application, a CPU-bound worker, a memory-heavy database, and a multi-service self-hosted stack can all use similar vCPU counts while needing very different resource profiles. The useful question is therefore not “Which VM class is best?” but “Which resource becomes limiting first, and how predictable does that resource need to be?” Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff customer conversations, a recurring sizing mistake is choosing by vCPU count before identifying whether CPU, memory, storage, or service contention is actually controlling the workload. This guide is the connector for Raff’s **VM Machine Classes** cluster. It explains the decision model first, then links to the deeper guides on [General Purpose VM plans](/learn/guides/raff-general-purpose-vm-plans-explained), [HiMem VMs](/learn/guides/himem-vms-explained), and [shared vs dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). ## Machine classes describe resource allocation and workload shape A VM class is a resource model, not a quality grade. Cloud providers group virtual machines into classes because workloads create pressure in different places. Some applications need a balanced amount of CPU and memory. Others need predictable CPU time for long-running compute. Databases and multi-service applications may need more RAM per vCPU. Storage-sensitive workloads may be limited by capacity or I/O before CPU becomes important. The main dimensions are: - **CPU allocation:** shared or dedicated compute; - **vCPU count:** how much parallel compute the VM can expose; - **memory ratio:** how much RAM is available per vCPU; - **storage capacity:** how much persistent local storage the workload can consume; - **storage behavior:** whether the workload depends on frequent reads, writes, or durable data growth; - **network behavior:** whether throughput, latency, or transfer billing changes the decision; - **operational role:** whether one VM hosts one service or several competing services. Two 4 vCPU machines can therefore be very different choices. One may provide a balanced memory ratio on shared CPU, while another reserves CPU for sustained compute. A third may keep the same core count but provide substantially more RAM. The class name should summarize the resource trade-off. It should not replace workload measurement. **Raff’s 3 Gbps unmetered VM network means machine-class selection can focus on CPU, memory, storage, and workload behavior.** ## The decision framework starts with the first constrained resource The central machine-class decision is to identify what the workload runs out of first during normal pressure. | Workload signal | Likely constraint | Better starting direction | |---|---|---| | CPU rises briefly, then returns to normal | Variable compute | General Purpose | | CPU stays high while latency or job time increases | Sustained compute | CPU-Optimized or more vCPU | | CPU is moderate but memory is near exhaustion | RAM | High-memory shape | | Swap activity or OOM events appear | RAM | High-memory shape or service separation | | App, database, queue, and workers compete on one VM | Mixed resource contention | More memory first, then consider separation | | Builds or workers take too long with sustained CPU pressure | Compute throughput | CPU-Optimized | | Database is slow while CPU remains comfortable | Query, memory, storage, or locks | Diagnose before changing class | | Logs, uploads, database files, or containers consume disk rapidly | Storage growth | More storage or separate storage path | | One VM still meets performance and recovery needs | Simplicity | Stay on one appropriately sized class | | Different services need independent scaling or recovery | Architecture boundary | Split roles instead of buying one larger class | This framework prevents a common mistake: upgrading the resource that is easiest to see rather than the resource that controls the workload. For example, a database-backed application may show 35% CPU and still be unstable because 95% of memory is committed and swap is active. A 4 vCPU upgrade would add compute without solving the real constraint. Conversely, a CI runner may have plenty of free RAM while all available CPU stays busy for long periods. A high-memory class would add the wrong resource. The first decision should therefore be diagnostic: 1. identify the user-visible or operational problem; 2. correlate it with CPU, memory, storage, and workload behavior; 3. choose the class that changes the constrained resource; 4. verify whether the workload outcome actually improves. This is also why production status alone should not determine class. A quiet production application can be a strong General Purpose fit. A temporary build runner can justify CPU-Optimized compute if it stays CPU-bound for every run. ## General Purpose fits balanced and variable workloads General Purpose VMs are the default when no single resource clearly dominates the workload. They fit applications that use CPU in bursts, keep a moderate working set in memory, and do not need reserved compute for long periods. Typical examples include: - websites and content applications; - APIs with modest or variable traffic; - development and staging environments; - internal tools; - early SaaS applications; - small backend services; - lightweight self-hosted applications; - mixed workloads where the bottleneck is not yet clear. The value of General Purpose is not that it works for everything. It is that it is an efficient place to begin when the workload is balanced or still uncertain. A team can start with the smallest configuration that has enough memory and storage headroom, then observe the workload. If CPU becomes the repeatable constraint, the next move may be more vCPU or a CPU-Optimized class. If memory pressure appears first, a higher-memory shape may be the better change. Shared CPU also makes sense for many production workloads. Production responsibility means the service matters; it does not automatically mean the service needs dedicated CPU. If latency remains within target and CPU pressure is brief, moving to reserved compute can increase cost without changing the user experience. The deeper Raff-specific plan ladder is covered in [Raff General Purpose VM Plans Explained](/learn/guides/raff-general-purpose-vm-plans-explained). That guide should be used for current plan-by-plan specifications rather than treating this connector guide as a permanent pricing table. ## CPU-Optimized fits sustained compute and CPU predictability CPU-Optimized VMs make sense when compute is not merely busy but controls the outcome of the workload. Good candidates include: - CI/CD runners with long CPU-bound builds; - queue workers processing continuously; - encoding, compression, compilation, or transformation jobs; - compute-heavy application services; - game or simulation workloads that depend on CPU timing; - analytics jobs with sustained processing; - APIs where tail latency rises with CPU pressure; - database workloads that have been measured and confirmed as CPU-bound. The important distinction is sustained demand. Short CPU spikes are normal on many General Purpose workloads. A deployment, package update, cache warm-up, or traffic burst may briefly use every available vCPU without justifying a class change. CPU-Optimized becomes more defensible when CPU pressure is repeatable under equivalent load and connects to a useful outcome such as: - slower p95 or p99 response time; - longer build duration; - growing queue age; - reduced worker throughput; - missed batch deadlines; - inconsistent completion time. Raff’s CPU-Optimized family is the dedicated-compute side of this decision. The companion guide [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) explains why the real trade-off is cost efficiency versus CPU predictability rather than “basic” versus “powerful” servers. Dedicated CPU does not fix every performance problem. If a workload is slow because of insufficient RAM, database locks, slow storage, external API calls, or inefficient code, changing CPU allocation may not improve it. ## High-memory shapes fit memory pressure without unnecessary CPU A high-memory VM provides more RAM relative to its vCPU count. This is useful when application stability depends on the size of the working set rather than on raw compute throughput. Common candidates include: - PostgreSQL or MySQL databases; - caches and in-memory services; - analytics dashboards; - multi-container applications; - self-hosted platforms with several services; - application runtimes with large heaps; - environments where the app, database, worker, and monitoring stack share one VM. Memory pressure looks different from CPU pressure. Useful signals include: - available memory trending toward zero; - sustained swap activity; - out-of-memory events; - container or service restarts; - database cache pressure; - application pauses caused by memory management; - deployment failures because the existing workload leaves too little headroom. A high-memory shape can be more economical than increasing vCPU just to obtain more RAM. This matters when CPU remains comfortable but the workload needs a larger working set. Memory should still be sized for the whole machine, not only the main application. A VM running an application server, database, queue, cache, monitoring agent, and reverse proxy has several independent consumers. Each may look modest alone while the combined footprint becomes the real constraint. The deeper decision is covered in [HiMem VMs Explained](/learn/guides/himem-vms-explained), which focuses specifically on when more RAM matters more than more CPU. ## Storage and service boundaries can outweigh the VM class A machine-class change is not always the right infrastructure change. Some workloads appear undersized because unrelated services compete on the same VM. Others are limited by local disk growth, database I/O, or application uploads rather than CPU or memory. In those cases, moving to a larger class can postpone the problem without fixing the architecture. Consider the storage path separately: | Symptom | Better question | |---|---| | Disk fills because of uploads | Should user files move to object storage? | | Database files grow rapidly | Does the database need its own storage and recovery boundary? | | Logs consume local disk | Can retention or centralized logging reduce growth? | | Backups compete with production I/O | Should backup timing or recovery design change? | | App and database compete for RAM and CPU | Is it time to separate the database? | | Workers interfere with web latency | Should workers move to another VM? | Service boundaries matter because different roles may need different machine classes. A SaaS application can use a balanced General Purpose VM for the web tier and a CPU-Optimized VM for sustained workers. A database may need more memory than either. There is no requirement that every service in one architecture use the same class. This is often a better growth model than continually enlarging one mixed server. Split only when the independent scaling, deployment, security, or recovery benefit justifies the additional operational complexity. When the bottleneck is unclear, use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) before changing class. If the question is specifically core count, [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms) is the narrower decision guide. ## A practical machine-class framework prevents overbuying The best machine-class strategy is to make the smallest change supported by evidence. ### Start balanced when the workload is uncertain A new application rarely has enough production data to justify a specialized class. General Purpose keeps the first decision simple while providing a baseline for CPU, memory, and storage behavior. ### Specialize only around a visible constraint Move toward CPU-Optimized when sustained compute is controlling latency or completion time. Move toward high-memory when RAM is controlling stability. Do not specialize because of a workload label alone. ### Separate class choice from VM size Class answers **what kind of resource profile** the workload needs. Size answers **how much of that profile** it needs. A workload may need more vCPU without dedicated compute, or more memory without more CPU. ### Keep production headroom tied to recovery and traffic behavior A production VM needs enough capacity for normal variation, deployments, maintenance, and expected peaks. Headroom should come from measured demand and recovery requirements, not a universal utilization percentage. ### Revisit the choice after architecture changes Moving uploads to object storage, separating a database, adding workers, or changing application concurrency can alter the bottleneck. Re-evaluate the class after significant architecture changes instead of assuming the previous choice remains correct. This framework gives small teams a controlled growth path: ```text Balanced starting class ↓ Measure CPU, memory, storage, and workload outcomes ↓ Resize within the class if capacity is the issue ↓ Change class if resource shape or CPU predictability is the issue ↓ Split services when independent boundaries become valuable ``` The purpose is not to predict the final infrastructure at launch. It is to avoid paying for specialization before the workload proves it needs it. ## Raff maps the framework to General Purpose, CPU-Optimized, and memory-forward shapes Raff’s VM lineup uses two primary families and several resource ratios inside them: - **General Purpose:** shared compute for balanced and variable workloads; - **CPU-Optimized:** dedicated compute for sustained or CPU-sensitive workloads; - **memory-forward configurations:** higher RAM-to-vCPU ratios for workloads where memory pressure matters more than additional cores. As of August 10, 2026, the live Raff pricing page lists the General Purpose entry configuration at **2 vCPU, 2 GB RAM, and 40 GB NVMe for $8.49/month**. Because plan tables change, exact pricing should be verified on the live pricing page when selecting a server. Current VM plans also include a **3 Gbps port**, **unmetered bandwidth**, resize support, IPv4 with optional IPv6, private networking, DDoS protection, monitoring, and full server access. **Raff’s current General Purpose entry is 2 vCPU, 2 GB RAM, and 40 GB NVMe at $8.49/month.** These platform defaults do not remove the need to right-size. They make the decision more focused: choose the CPU allocation model, memory ratio, and storage capacity that match the workload, then resize or change class when measurement shows a different constraint. For current shared-class sizes and prices, use [Raff General Purpose VM Plans Explained](/learn/guides/raff-general-purpose-vm-plans-explained) together with the [live Raff pricing page](/pricing). For CPU allocation, continue with [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). For memory-focused workloads, use [HiMem VMs Explained](/learn/guides/himem-vms-explained). ## Choose the smallest class that meets the real requirement Cloud VM machine classes are useful because workloads do not consume infrastructure in the same way. Choose General Purpose when the workload is balanced, variable, or still uncertain. Choose CPU-Optimized when sustained compute or CPU predictability controls an important outcome. Choose a memory-forward shape when RAM pressure appears before CPU pressure. If storage, database behavior, or service contention is the real constraint, change the architecture rather than only the VM class. The safest first decision is usually the smallest class that meets current performance, stability, and recovery requirements with reasonable headroom. Then use production evidence to justify the next change. This guide is the parent for Raff’s VM Machine Classes cluster. Continue with [Raff General Purpose VM Plans Explained](/learn/guides/raff-general-purpose-vm-plans-explained), [HiMem VMs Explained](/learn/guides/himem-vms-explained), or [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) depending on the resource question you need to answer next. :::cta Explore Raff VM Compare current VM classes and choose the resource profile that matches your workload. ::: ### Sources - [Raff Pricing](/pricing) - [Raff VM](/products/raff-vm) --- ### Raff General Purpose VM Plans: Sizes, Pricing & Workload Fit URL: https://rafftechnologies.com/learn/guides/raff-general-purpose-vm-plans-explained Description: Understand Raff General Purpose VM plans, current sizes and pricing, and how to choose CPU, RAM, and NVMe capacity for websites, APIs, and small apps. Raff General Purpose VM plans are shared-vCPU cloud server configurations that balance CPU, memory, and NVMe storage for variable and mixed workloads. The useful choice is not simply “small, medium, or large.” Two plans with the same vCPU count can have very different memory ratios, and two plans with the same RAM can provide very different compute headroom. Raff Technologies supports 3,000+ customers and 15,000+ VMs, and in customer conversations the recurring sizing mistake is choosing by vCPU count before identifying whether memory, CPU, storage, or service contention is actually limiting the application. This guide is the plan-level companion to [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained). Use that parent guide when deciding between General Purpose, CPU-Optimized, and memory-forward resource shapes. Use this page when General Purpose is already the right class and you need to choose a current Raff size without overbuying. ## Raff General Purpose VM plans currently span 12 sizes The current General Purpose lineup ranges from **2 vCPU / 2 GB RAM / 40 GB NVMe** to **16 vCPU / 32 GB RAM / 640 GB NVMe**. Monthly pricing on August 10, 2026 is: | vCPU | Memory | NVMe SSD | Monthly price | Practical role | |---:|---:|---:|---:|---| | 2 | 2 GB | 40 GB | $8.49 | Lightweight sites, dev, test, small services | | 2 | 4 GB | 80 GB | $13.99 | Small apps that need more runtime memory | | 4 | 4 GB | 80 GB | $16.99 | Balanced apps needing more parallel CPU | | 2 | 8 GB | 160 GB | $27.99 | Memory-forward workloads with modest CPU demand | | 4 | 8 GB | 160 GB | $30.99 | Balanced production apps; currently marked Popular | | 8 | 8 GB | 160 GB | $37.99 | CPU-active shared-vCPU workloads | | 4 | 16 GB | 320 GB | $52.99 | Memory-heavy services and multi-service VMs | | 8 | 16 GB | 320 GB | $59.99 | Larger balanced applications | | 16 | 16 GB | 320 GB | $75.99 | High parallelism where shared CPU remains acceptable | | 12 | 24 GB | 480 GB | $90.99 | Larger mixed workloads needing both CPU and memory | | 8 | 32 GB | 640 GB | $115.99 | RAM-heavy workloads with moderate CPU needs | | 16 | 32 GB | 640 GB | $129.99 | Large balanced or consolidated workloads | **Raff General Purpose plans start at $8.49/month for 2 vCPU, 2 GB RAM, and 40 GB NVMe.** The table is a current plan map, not a guarantee that a workload will fit a specific size. Application behavior, concurrency, database activity, container count, cache usage, and storage growth can move the requirement in either direction. The plan ladder also shows why vCPU count alone is a poor sizing method. A 2 vCPU plan is available with 2 GB, 4 GB, or 8 GB RAM. An 8 vCPU plan is available with 8 GB, 16 GB, or 32 GB RAM. The right choice depends on the resource ratio the workload consumes, not only the largest number in the plan name. ## The plan decision starts with CPU-to-memory ratio Once General Purpose is the correct machine class, the next decision is whether the workload needs more CPU, more memory, or a balanced increase in both. | Workload signal | Better direction | Why | |---|---|---| | CPU is comfortable but memory is tight | Increase RAM before vCPU | More CPU does not fix memory pressure | | Memory is comfortable but requests or workers saturate CPU | Increase vCPU | More compute may improve concurrency or throughput | | CPU and memory rise together | Move to a balanced larger plan | Both resources need headroom | | Swap is active or OOM events occur | Choose a higher-memory shape | Stability is constrained by RAM | | CPU spikes briefly and then returns to normal | Stay on General Purpose and observe | Short bursts do not automatically justify dedicated CPU | | CPU stays busy for long periods and timing consistency matters | Evaluate CPU-Optimized | CPU allocation model may matter more than General Purpose size | | Local disk is filling rapidly | Increase storage or change storage architecture | CPU/RAM upgrades do not solve durable data growth | | App, database, and workers compete on one VM | Measure each service separately | Service separation may be better than one larger server | From Raff customer conversations, the cleanest upgrade decisions happen when a team can name the constrained resource before opening the pricing table. “The app feels slow” is not enough. “Memory is consistently near exhaustion while CPU remains moderate” points toward a different plan than “CPU is saturated while half the RAM is unused.” This is why the General Purpose ladder should be read horizontally as well as vertically. A workload can move from 2 vCPU / 4 GB to 4 vCPU / 4 GB when it needs more compute, or to 2 vCPU / 8 GB when it needs more memory. ## Entry and midrange plans cover most small application starting points The first six General Purpose plans cover a useful range for small websites, APIs, SaaS applications, development environments, and self-hosted tools. | Workload pattern | Starting plan to evaluate | Current price | What to verify after launch | |---|---|---:|---| | Lightweight site, dev server, test environment | 2 vCPU / 2 GB / 40 GB | $8.49/mo | Memory headroom, storage growth | | Small API or app needing more runtime memory | 2 vCPU / 4 GB / 80 GB | $13.99/mo | p95 latency, memory, swap | | Balanced app with more active request processing | 4 vCPU / 4 GB / 80 GB | $16.99/mo | CPU saturation, memory pressure | | RAM-sensitive app with modest compute | 2 vCPU / 8 GB / 160 GB | $27.99/mo | Working set, cache behavior | | Small production stack with balanced needs | 4 vCPU / 8 GB / 160 GB | $30.99/mo | CPU, RAM, database and worker contention | | CPU-active app where shared compute is still acceptable | 8 vCPU / 8 GB / 160 GB | $37.99/mo | Sustained CPU and tail latency | The **4 vCPU / 8 GB / 160 GB** configuration is currently marked Popular on the pricing page. That label is useful as a product signal, but it should not replace workload measurement. **Raff's 4 vCPU / 8 GB / 160 GB General Purpose plan is currently $30.99/month.** For a small application, the 2 GB plan can be a sensible entry when the runtime is lightweight and durable data is limited. A container stack, database-backed application, or memory-hungry runtime may need 4 GB or 8 GB even with low traffic. Likewise, moving from 2 vCPU to 4 or 8 vCPU should be driven by CPU behavior. More vCPU can help concurrent request handling, workers, builds, or application processing, but it does not automatically improve a workload waiting on a database, storage, or external service. ## Larger plans fit consolidation and higher resource demand The 16 GB, 24 GB, and 32 GB tiers are useful when a workload has already outgrown the entry and midrange shapes or when several services intentionally share one VM. Common reasons to evaluate these plans include: - larger application heaps or caches; - database-backed services with a bigger memory working set; - several containers sharing the same host; - app + worker + queue combinations that need more aggregate headroom; - higher request concurrency while shared vCPU remains suitable; - local data or package growth requiring 320–640 GB NVMe; - temporary consolidation before services are separated. The larger plans still follow the same ratio logic. **4 vCPU / 16 GB** and **8 vCPU / 16 GB** share the same memory and storage but offer different compute capacity. **8 vCPU / 32 GB** and **16 vCPU / 32 GB** do the same at the top of the current ladder. That makes the decision clearer: - choose the lower-vCPU version when memory is the main need; - choose the higher-vCPU version when both memory and compute are active constraints; - evaluate CPU-Optimized when sustained CPU predictability, not just core count, becomes important; - split services when independent scaling or recovery is more valuable than one larger VM. A large General Purpose VM is not automatically the final architecture. If a database, worker tier, or file workload has a different lifecycle, separation may reduce contention and make future sizing easier. ## General Purpose remains a shared-vCPU decision All General Purpose sizing decisions sit inside one important boundary: the class uses shared compute. That is appropriate for many websites, APIs, development environments, customer applications, and mixed workloads because CPU demand is often variable. Shared compute provides cost efficiency when the workload does not need reserved CPU capacity continuously. The class becomes less attractive when a workload is consistently CPU-bound and execution-time predictability itself has operational value. Examples include long-running CI builds, continuous compute workers, encoding, heavy transformation jobs, or latency-sensitive services where CPU pressure repeatedly aligns with p95 or p99 latency. In that case, the better question is not “Should I buy the 16 vCPU General Purpose plan?” It may be “Should this workload move to dedicated compute?” Use [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu) for that decision. If the issue is simply core count within a shared-vCPU workload, [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms) provides the narrower framework. ## Raff includes the same core network and management defaults across the lineup The current pricing page lists the following platform characteristics across Raff Cloud Server plans: - **3 Gbps** public network port; - **unmetered bandwidth** with no caps or bandwidth billing; - resize support for CPU, RAM, and storage; - one IPv4 with optional IPv6 dual-stack; - free private networking (VPC); - included DDoS protection; - browser console and full root access; - API and Terraform access; - live monitoring. **Every current Raff Cloud Server plan includes a 3 Gbps public port and unmetered bandwidth.** These defaults matter because they remove several variables from the size decision. A team choosing between 2 vCPU / 4 GB and 4 vCPU / 8 GB does not also need to choose a different bandwidth allowance or public port tier. The sizing problem therefore stays focused on the workload: CPU, memory, local storage, and whether shared compute is still the right allocation model. For exact current prices, always verify the [Raff pricing page](/pricing) before deployment. Pricing and plan tables can change faster than long-lived Learn content. ## A measured upgrade path avoids both waste and instability The first VM size is an informed estimate. The next size should be based on evidence. A practical upgrade sequence is: 1. **Start with the smallest plan that safely fits the known workload.** Leave enough memory and storage for the runtime, operating system, logs, deployments, and expected data growth. 2. **Measure CPU, memory, swap, disk usage, latency, and application-specific outcomes.** Do not use one resource graph in isolation. 3. **Change one resource direction at a time when possible.** More RAM and more vCPU solve different problems. 4. **Re-test under comparable load.** Confirm that the upgrade improved latency, throughput, stability, or operational headroom. 5. **Change class when the allocation model becomes the constraint.** Sustained CPU predictability points toward CPU-Optimized rather than endlessly increasing shared-vCPU size. 6. **Change architecture when services need independent boundaries.** Databases, workers, uploads, or other stateful components may eventually deserve separate resources. When the bottleneck is unclear, use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) before upgrading. For memory-specific pressure, continue with [HiMem VMs Explained](/learn/guides/himem-vms-explained). The point is not to run infrastructure as close to failure as possible. It is to keep enough headroom for normal traffic, deployments, maintenance, and expected growth without buying resources that the workload does not use. ## The right Raff General Purpose plan follows the measured bottleneck Raff General Purpose VM plans give small teams a 12-size shared-vCPU ladder from **2 vCPU / 2 GB / 40 GB at $8.49/month** to **16 vCPU / 32 GB / 640 GB at $129.99/month**. Start at the lower end when the workload is lightweight and uncertain. Move toward higher-memory shapes when RAM pressure appears first. Add vCPU when compute is the measurable constraint. If sustained CPU predictability becomes important, evaluate CPU-Optimized rather than treating a larger General Purpose plan as the only upgrade path. For the parent decision, return to [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained). For CPU allocation, continue with [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu), and use the [live Raff pricing page](/pricing) for the latest plan table before deployment. :::cta Explore Raff VM Compare current General Purpose sizes and choose a balanced VM for your workload. ::: ### Sources - [Raff Pricing](/pricing) - [Raff VM](/products/raff-vm) --- ### HiMem VMs Explained: When More RAM Matters Than More CPU URL: https://rafftechnologies.com/learn/guides/himem-vms-explained Description: Understand HiMem VMs, memory pressure signals, RAM vs CPU trade-offs, and when a higher memory-to-vCPU ratio fits databases and multi-service apps. HiMem VMs are memory-forward virtual machines that provide more RAM per vCPU than a balanced VM shape, making them useful when memory pressure appears before compute pressure. The decision is not simply “RAM or CPU.” It is whether the workload is waiting for compute or struggling to keep its active working set in memory. A database can have comfortable CPU usage and still perform poorly under memory pressure. A multi-container application can restart services even when the processors are mostly idle. Conversely, a build worker can have plenty of free RAM while CPU remains the real constraint. Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff infrastructure reviews, the useful signal is not a single high-memory percentage; it is repeated memory pressure combined with swap activity, reclaim stalls, out-of-memory events, container restarts, or application behavior that improves when more RAM is available. This guide is part of the [VM Machine Classes](/learn/guides/cloud-vm-machine-classes-explained) cluster. Use it when the question is specifically whether a workload needs a higher memory-to-vCPU ratio. For current Raff General Purpose sizes and prices, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). ## HiMem VMs change the memory-to-vCPU ratio A HiMem VM is not necessarily a different kind of processor or a separate architecture. It is a resource shape that gives the workload more memory relative to available CPU. That distinction matters because VM size and VM class answer different questions: - **vCPU count** determines how much parallel compute is available to the guest; - **memory capacity** determines how much active data and how many processes can remain resident in RAM; - **CPU allocation model** determines whether compute is shared or dedicated; - **storage capacity and behavior** determine how durable data grows and how the application handles reads and writes. A workload can need more memory without needing more CPU. For example, moving from 2 vCPU / 4 GB RAM to 2 vCPU / 8 GB RAM doubles memory while keeping the same vCPU count. That is a memory-shape change. Moving from 2 vCPU / 4 GB to 4 vCPU / 4 GB changes compute without increasing memory. The machine-class decision should therefore begin with the constrained resource rather than the largest number in the pricing table. ## Memory pressure has different symptoms from CPU pressure CPU saturation and memory pressure can both make an application feel slow, but they leave different evidence. | Signal | More likely memory-related | More likely CPU-related | |---|---|---| | Available RAM | Consistently low | May remain comfortable | | Swap | Active or increasing | Often unrelated | | OOM events | Possible | Not a CPU symptom | | Container restarts | Can follow memory limits or OOM | Can occur for other reasons | | CPU utilization | May be moderate | Often sustained high | | Request latency | Rises during reclaim, swap, or GC pressure | Rises with sustained compute demand | | Worker throughput | May fall when the process is memory constrained | Falls when processing capacity is saturated | | Build duration | Usually not solved by RAM unless memory constrained | Often CPU-sensitive | | Database behavior | Cache pressure, memory spills, connection footprint | CPU-heavy queries or computation | Linux exposes memory pressure separately from raw memory usage. Pressure Stall Information (PSI) can report how much time tasks are stalled because memory is unavailable, and the kernel can invoke the OOM killer when it cannot reclaim enough memory to continue normal operation. This is why a fixed rule such as “upgrade at 80% RAM” is too crude. High memory utilization can be healthy when the operating system is using available RAM for useful cache. The stronger evidence is **pressure plus impact**: reclaim stalls, sustained swap, OOM kills, failed allocations, restarts, or user-visible slowdown. In Raff infrastructure work, we treat memory utilization as context rather than a verdict. The upgrade becomes defensible when the workload repeatedly loses stability or latency headroom because it cannot keep enough active state in RAM. ## Databases often need memory before they need more cores Databases are a common reason to choose a memory-forward VM, but more RAM is not a universal database fix. PostgreSQL, MySQL, and similar systems use memory for buffers, caches, connections, query operations, and supporting processes. The application host may also run a reverse proxy, API process, worker, monitoring agent, and operating-system cache. When several of those components share one VM, the total working set can become the constraint before CPU does. A higher-memory shape is worth evaluating when: - the database and application compete for RAM; - swap activity appears during normal load; - larger queries or maintenance jobs create memory pressure; - connection growth materially increases the memory footprint; - cache effectiveness or working-set size is constrained by available RAM; - OOM events or service restarts occur under otherwise moderate CPU load. Do not move to a HiMem shape merely because the workload contains a database. Slow queries may come from missing indexes, poor query plans, lock contention, storage waits, or inefficient application access patterns. If CPU remains low and memory pressure is absent, more RAM may not change the bottleneck. The clean decision is to separate **database tuning** from **VM sizing**. Fix avoidable query and schema problems first; then add memory when the measured working set and operational headroom justify it. If the application and database now need different recovery, maintenance, or scaling boundaries, [Separate App and Database Server](/learn/guides/separate-app-database-server) may be a better next step than continuing to enlarge one VM. ## Containers and multi-service VMs amplify memory demand A single self-hosted product can represent several running processes. A Docker Compose deployment might contain: - an application service; - PostgreSQL or MySQL; - Redis or another cache; - a queue; - one or more workers; - a reverse proxy; - monitoring or logging agents; - scheduled jobs. Each service can look modest in isolation while the combined host becomes memory-constrained. Runtime heaps, database buffers, caches, container overhead, package updates, and deployment processes all compete for the same physical RAM assigned to the VM. This is why a stack may install successfully on a small VM but become unstable later. Installation tests a narrow moment. Production adds concurrency, larger datasets, background work, logs, deployments, and temporary memory peaks. A memory-forward VM is useful when the services should intentionally remain on one host and additional RAM restores operating headroom. It is less useful when the services have already developed different scaling or recovery requirements. In that case, service separation can be the cleaner architecture. Use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) when CPU, memory, disk I/O, and application dependencies need to be diagnosed together. ## The decision framework separates memory capacity from compute capacity Use the following framework before choosing a HiMem VM. | Evidence | Better first move | Reason | |---|---|---| | Memory pressure, swap, or OOM while CPU has headroom | Add RAM / memory-forward shape | Memory is the active constraint | | CPU is sustained high while memory has headroom | Add vCPU or evaluate CPU-Optimized | Compute is the active constraint | | CPU and RAM rise together | Larger balanced shape | Both resources need capacity | | One service consumes most memory | Tune or isolate that service | Whole-host upgrade may hide a local problem | | Database and app compete for resources | Add memory or separate roles | Decide whether the boundary should remain shared | | Multiple containers need stable resident memory | Memory-forward shape | More RAM can protect the whole stack | | Local disk is the constraint | Increase or separate storage | RAM does not solve capacity growth | | Tail latency varies with sustained CPU pressure | Evaluate dedicated CPU | CPU predictability may matter more than RAM | | Workload is healthy with free headroom | Stay on current size | No evidence supports an upgrade | The decision can be reduced to four questions: 1. **Is the workload actually under memory pressure?** Look beyond percentage-used metrics. 2. **Does memory pressure align with a real outcome?** Check latency, restarts, OOM events, swap, queue behavior, or database symptoms. 3. **Would more RAM solve the constraint without adding unnecessary CPU?** If yes, a memory-forward shape is appropriate. 4. **Should the services still share one VM?** If not, architecture may matter more than a larger memory ratio. A HiMem VM is therefore a targeted upgrade, not a premium default. ## Raff offers several memory-forward General Purpose shapes Raff’s current General Purpose lineup is shared-vCPU compute with multiple CPU-to-memory ratios. The live pricing page does not present “HiMem” as a separate product family; instead, users can choose higher-memory shapes inside the General Purpose ladder. As of August 10, 2026, examples include: | vCPU | RAM | NVMe SSD | Monthly price | Memory per vCPU | |---:|---:|---:|---:|---:| | 2 | 4 GB | 80 GB | $13.99 | 2 GB/vCPU | | 2 | 8 GB | 160 GB | $27.99 | 4 GB/vCPU | | 4 | 8 GB | 160 GB | $30.99 | 2 GB/vCPU | | 4 | 16 GB | 320 GB | $52.99 | 4 GB/vCPU | | 8 | 16 GB | 320 GB | $59.99 | 2 GB/vCPU | | 8 | 32 GB | 640 GB | $115.99 | 4 GB/vCPU | | 16 | 32 GB | 640 GB | $129.99 | 2 GB/vCPU | The **2 vCPU / 8 GB** and **4 vCPU / 16 GB** shapes are useful examples of choosing more memory without proportionally increasing compute. The 4 vCPU / 8 GB configuration is currently marked Popular and costs **$30.99/month**. **Raff offers a 2 vCPU / 8 GB / 160 GB General Purpose VM at $27.99/month for workloads that need a higher memory-to-vCPU ratio.** Every current Raff Cloud Server plan also includes a **3 Gbps public port**, unmetered bandwidth, resize support, private networking, DDoS protection, browser console/root access, API and Terraform access, and monitoring. Pricing changes faster than architecture guidance, so use the [live Raff pricing page](/pricing) to confirm the current plan table before deployment. ## Measure memory pressure before and after resizing A memory upgrade should improve a workload outcome, not only lower a percentage on a dashboard. Useful measurements include: - available memory over time; - swap usage and swap-in/swap-out activity; - memory PSI on Linux where available; - OOM-kill events; - container memory limits and restart counts; - application heap or garbage-collection behavior where relevant; - database memory footprint and connection count; - p95/p99 latency during pressure periods; - queue depth or worker completion time; - disk I/O wait, because swap and memory pressure can surface as storage activity. Compare equivalent workload windows before and after resizing. If more RAM removes swap, OOM events, or pressure stalls but user-facing latency does not improve, another bottleneck may still be present. If memory pressure disappears and the workload becomes stable, the change was justified even if average CPU utilization remains unchanged. Do not treat free RAM as wasted money automatically. Some headroom protects deployments, traffic variation, maintenance jobs, database working sets, and temporary process growth. The objective is not maximum utilization; it is stable operation at a cost the workload justifies. ## More RAM matters when memory is the measured constraint HiMem VMs are useful when the workload needs a higher memory-to-vCPU ratio, not because high-memory plans are inherently better. Choose a memory-forward shape when memory pressure, swap, OOM events, container restarts, database working-set limits, or multi-service contention appear before CPU saturation. Choose more vCPU when compute is the constraint. Evaluate CPU-Optimized when sustained CPU predictability matters. Separate services when independent scaling or recovery is more valuable than a larger single VM. For the parent decision, return to [Cloud VM Machine Classes Explained](/learn/guides/cloud-vm-machine-classes-explained). For current General Purpose sizes and pricing, continue with [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). If the issue is CPU allocation rather than RAM, use [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). :::cta Explore Raff VM Compare current memory ratios and choose a VM shape that matches your measured workload. ::: ### Sources - [Linux Kernel: Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) - [Linux Kernel: Out Of Memory Handling](https://www.kernel.org/doc/html/next/mm/oom.html) - [Raff Pricing](/pricing) - [Raff VM](/products/raff-vm) --- ### 2 vCPU / 2 GB Cloud VM: Workloads, Limits & Upgrade Signs URL: https://rafftechnologies.com/learn/guides/2-vcpu-2gb-cloud-vm-workloads Description: Learn what a 2 vCPU / 2 GB cloud VM can run, where CPU, RAM, and storage limits appear, and when to resize websites, APIs, Docker, and dev workloads. A 2 vCPU / 2 GB cloud VM is an entry virtual server with two virtual processors and 2 GB of memory for focused, lightweight workloads. The right question is not whether 2 GB RAM is "enough" in isolation. It is whether the operating system, application, database or cache, background work, and normal traffic can share that memory without sustained pressure. A small website or API can fit comfortably while an app, database, queue, cache, worker, and monitoring stack can exhaust the same VM before traffic becomes meaningful. Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Aybars's practical Linux and self-hosted deployment work, the recurring lesson is that small VMs stay useful longest when they have one clear job and the team measures pressure before adding more services. For the broader CPU, RAM, storage, and network decision, start with [VM Sizing: How to Choose the Right Size for Your Workload](/learn/guides/choosing-right-vm-size). This guide stays narrow: what fits on a 2 vCPU / 2 GB machine, what usually breaks first, and which upgrade direction follows the evidence. ![Raff cloud VM configuration screen showing a 2 vCPU, 2 GB RAM, 40 GB NVMe entry server plan for lightweight workloads.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_05_31_at_10_22_10_1397fa66c1.png) ## A 2 vCPU / 2 GB VM fits one focused lightweight workload A 2 vCPU / 2 GB VM is a starting shape, not a universal production tier. It is strongest when the machine has one primary responsibility and the supporting services remain modest. Typical examples include a small website or reverse proxy, a lightweight API, a development or test server, a low-traffic internal tool, an early application backend, or one small containerized service. The same configuration becomes a weaker fit when several memory-active services share the host. A reverse proxy, application runtime, PostgreSQL, Redis, two workers, monitoring, and a deployment process may each look small alone while their combined working set leaves too little operating headroom. Project labels are weak sizing inputs. "MVP," "production," and "Docker" do not tell you enough. The useful inputs are the active processes, concurrency, working set, storage growth, and the cost of a slowdown or restart. A production service can remain on 2 vCPU / 2 GB if it meets its latency and reliability requirements. A development machine can need more resources if builds, tests, containers, or local databases create sustained pressure. ## Websites, APIs, development, and small services are the strongest fits Small web workloads are usually the cleanest fit because they can keep the runtime footprint narrow. A static site, documentation site, landing page, portfolio, small company site, or lightweight dynamic application can fit well when traffic and database activity remain modest. A compact Node.js, Python, Go, PHP, Ruby, or .NET service can also fit when request concurrency is controlled and the application does not keep a large working set in memory. Development and staging environments are another strong fit for package testing, deployment validation, Linux learning, QA, and temporary demos. The main exception is performance testing: a smaller staging VM can validate functionality, but it cannot prove production capacity. An early MVP can also start small when the workload is simple and the team has a resize path. The key is to revisit sizing when the project gains more users, customer data, background jobs, or stricter uptime expectations. Starting small is useful only when resizing is planned. Staying small after the workload changes is not cost optimization. ## Containers and databases need more caution on 2 GB RAM Docker does not make a workload lightweight. It packages processes that still consume the host's CPU, memory, disk, and network capacity. A 2 GB host can be reasonable for one small application container, a reverse proxy plus one lightweight app, or a disposable Compose environment. It becomes harder to justify when the same VM runs an application, database, cache, queue, workers, monitoring, and other long-lived services. Container limits can reduce the chance that one process consumes the whole host, but they do not create additional RAM. Measure the combined peak rather than the idle footprint. Deployments, image pulls, imports, backups, and temporary overlap between old and new containers can create pressure even when steady state looks healthy. Databases need similar caution. A small PostgreSQL, MySQL, or MariaDB instance can run on 2 GB for development, testing, or a very small application. Production databases use memory for buffers, caches, connections, query operations, and maintenance. If the app and database share one 2 GB VM, the available working set can disappear quickly. Do not assume the first database upgrade should always be more RAM. Slow queries can also come from indexes, locks, storage waits, or application behavior. Use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network) before resizing when the cause is unclear. ## The decision framework separates memory, CPU, and architecture limits Use this framework when deciding whether the current 2 vCPU / 2 GB VM still fits. | Evidence | Better first decision | Why | |---|---|---| | CPU and memory both have comfortable headroom | Stay on the current VM | No measured constraint justifies a resize | | Available memory falls, swap persists, or OOM events appear | Add RAM or reduce memory demand | Memory is the active constraint | | CPU pressure aligns with latency, queue growth, or longer jobs | Add vCPU or reduce CPU work | Compute is the active constraint | | App and database repeatedly compete for resources | Add capacity or separate roles | One host may no longer be the right boundary | | Disk capacity is running out | Clean up or change storage design | CPU and RAM do not solve storage growth | | High I/O latency controls the workload | Diagnose storage and application I/O | A larger VM may not fix the wait path | | One container or process grows without stabilizing | Fix limits, leak, or configuration | More capacity can hide the root cause | | Several services each need independent scaling or recovery | Separate services | Architecture matters more than a larger single VM | The strongest upgrade signal is **pressure plus workload impact**. A memory graph at a fixed percentage is not enough because Linux can use otherwise idle RAM for useful filesystem cache. Likewise, a brief CPU spike during deployment does not prove that more vCPU is required. For memory-specific sizing, use [How Much RAM Do I Need for a VPS?](/learn/guides/how-much-ram-do-i-need-for-vps). For the narrower CPU decision, use [2 vCPU vs 4 vCPU Cloud VMs](/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms). ## Upgrade signals come from pressure plus workload impact A small VM should be resized when normal workload behavior repeatedly creates a constraint that affects users, jobs, deployments, or stability. Memory-related signals include low available memory during normal peaks, sustained swap activity, OOM events, container or process restarts, database latency rising with memory pressure, and deployment or backup activity repeatedly destabilizing the host. Avoid a universal rule such as "upgrade at 80% RAM." High memory utilization can be healthy, while lower utilization can still hide a leak or an application-specific limit. More vCPU becomes defensible when sustained CPU pressure repeatedly aligns with rising p95 or p99 latency, growing worker backlog, slower builds, or CPU-active background jobs competing with user traffic. If only one thread is busy, or the request spends most of its time waiting on a database or external API, more vCPU may change little. Logs, Docker images, uploads, database files, and package caches can quietly consume a 40 GB disk. Monitor free space and growth rate before capacity becomes urgent. A resize is also not the only answer. If the application, database, and workers have developed different performance or recovery needs, moving one role to another VM can be cleaner than continuously enlarging one server. ## Raff's current 2 vCPU / 2 GB plan starts at $8.49 per month Raff's current General Purpose entry plan is **2 vCPU / 2 GB RAM / 40 GB NVMe SSD at $8.49 per month** on monthly billing. Nearby General Purpose shapes currently include: | vCPU | RAM | NVMe SSD | Monthly price | Useful when | |---:|---:|---:|---:|---| | 2 | 2 GB | 40 GB | $8.49 | One focused lightweight workload | | 2 | 4 GB | 80 GB | $13.99 | Memory is tight but CPU still has headroom | | 4 | 4 GB | 80 GB | $16.99 | More concurrent compute is justified | | 2 | 8 GB | 160 GB | $27.99 | The workload needs a higher memory-to-vCPU ratio | This ladder separates resource decisions. A 2 vCPU workload can move from 2 GB to 4 GB or 8 GB RAM without automatically increasing core count. A 2 vCPU / 4 GB workload can move to 4 vCPU / 4 GB when compute rather than memory is the measured constraint. Current Raff Cloud Server plans also include a **3 Gbps public network port**, unmetered bandwidth, CPU/RAM/storage resize support, one IPv4 with optional IPv6, private networking, DDoS protection, browser console and root access, API and Terraform access, and monitoring. Use the live [Raff pricing page](/pricing) before deployment because plan sizes and prices can change. For the full General Purpose ladder, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). ## Best practices keep a small VM stable longer Keep one clear primary workload. A 2 GB VM lasts longer when every added service has a reason to share the host. Measure available memory and swap, not only percentage used. On Linux, available memory, swap behavior, OOM events, process growth, and application latency provide a better picture than one utilization percentage. Control logs and local file growth. Set log rotation, review Docker image and layer growth, expire temporary artifacts, and move suitable uploads or archives to a storage layer designed for them. Give deployments operating headroom. A server that is stable only while idle can fail during package updates, image pulls, migrations, or backups. Change one resource for one measured reason: add RAM for memory pressure, add vCPU for compute pressure, increase or separate storage for capacity and I/O needs, and separate services when independent scaling or recovery becomes the real requirement. ## A 2 vCPU / 2 GB VM is a measured starting point A 2 vCPU / 2 GB cloud VM fits small websites, focused APIs, development environments, early MVPs, and other lightweight services when the combined working set and compute demand stay modest. The safest approach is to start with one clear workload, watch CPU, available memory, swap, storage growth, application latency, and job behavior, then change the resource that matches the measured constraint. If several services begin competing or need different recovery paths, the next step may be separation rather than a larger single VM. For broader sizing, continue with [VM Sizing: How to Choose the Right Size for Your Workload](/learn/guides/choosing-right-vm-size). For current configurations, compare [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). :::cta Explore Raff VM Compare current VM sizes and choose the smallest safe starting point for your workload. ::: ### Sources - [Linux `/proc` memory information](https://docs.kernel.org/filesystems/proc.html) - [Docker resource constraints](https://docs.docker.com/engine/containers/resource_constraints/) - [Raff Pricing](/pricing) - [Raff Cloud Servers](/products/raff-vm) --- ### 2 vCPU vs 4 vCPU Cloud VMs: What Every Developer Should Know URL: https://rafftechnologies.com/learn/guides/2-vcpu-vs-4-vcpu-cloud-vms Description: Compare 2 vCPU vs 4 vCPU cloud VMs using CPU pressure, concurrency, latency, queues, and workload evidence instead of environment labels. 2 vCPU vs 4 vCPU cloud VM sizing is a decision about how much concurrent compute a workload can use before CPU becomes the limiting resource. Four vCPUs do not automatically make an application twice as fast as two. The extra virtual processors help only when the guest has enough runnable work, application parallelism, request concurrency, workers, builds, or other CPU-active tasks to use them. If the real bottleneck is memory, storage, a database query, or an external dependency, increasing vCPU count may change little. Raff Technologies supports 3,000+ customers and 15,000+ VMs. In Raff infrastructure reviews, the strongest reason to move from 2 vCPU to 4 vCPU is repeatable evidence: CPU pressure rises at the same time as p95/p99 latency, queue age, build duration, worker backlog, or another workload outcome that matters. For the broader CPU, RAM, storage, and network decision, start with [How to Choose the Right VM Size for Your Workload](/learn/guides/choosing-right-vm-size). This guide stays narrow: when 2 vCPU is enough, when 4 vCPU is justified, and when the correct upgrade is not more CPU. ![Raff General Purpose VM plan table showing 2 vCPU and 4 vCPU cloud server options.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_06_01_at_12_49_31_6639240929.png) *The screenshots in this article are retained from the June 2026 version of the guide. Use the current Raff pricing page for live plan sizes and prices.* ## 2 vCPU vs 4 vCPU changes available parallel compute A vCPU is a virtual processor presented to the guest operating system. It is not safe to assume that one vCPU always equals one physical CPU core because the underlying mapping and scheduling model can vary by platform and machine class. What matters to the application is whether additional virtual processors can run useful work concurrently. A workload can benefit from more vCPU when it has: - multiple application workers handling requests at the same time; - background jobs that can run in parallel; - build or test jobs that use several threads or processes; - compression, transformation, indexing, or compilation work; - several CPU-active services sharing one VM; - enough concurrent requests to keep existing vCPUs busy. A workload may gain little from more vCPU when it is primarily waiting on: - database locks or slow queries; - disk reads and writes; - external APIs; - network latency; - a single-threaded code path; - memory pressure or swap; - application-level rate limits. The core-count decision is therefore not “2 is small and 4 is production.” It is “does the workload have more runnable CPU work than 2 vCPU can process within the required latency or completion time?” ## The decision framework starts with CPU pressure and queueing Use workload evidence before changing core count. | Evidence | Better first decision | Why | |---|---|---| | CPU is usually low or moderate | Stay on 2 vCPU | Extra CPU would sit unused most of the time | | Brief CPU spikes during deploys or updates | Stay on 2 vCPU and observe | Short spikes do not prove a sustained constraint | | Sustained CPU pressure aligns with rising p95/p99 latency | Evaluate 4 vCPU | Compute may be limiting request throughput | | Worker queue grows while CPU remains saturated | Evaluate 4 vCPU | More concurrent compute may reduce backlog | | Builds or tests are CPU-bound across repeat runs | Evaluate 4 vCPU | Parallel work can benefit from more schedulable CPU | | Memory is tight, swap is active, or OOM events occur | Add RAM or choose a memory-forward shape | CPU is not the primary constraint | | CPU is low but database latency is high | Diagnose queries, locks, memory, and storage | More vCPU may not touch the bottleneck | | CPU is high but only one thread is busy | Optimize or parallelize the workload | More vCPU cannot accelerate serial work automatically | | CPU timing consistency matters under sustained load | Evaluate dedicated CPU | Allocation model may matter more than core count | The useful signal is **pressure plus impact**. High CPU by itself is not necessarily a problem. A batch worker can run at high utilization and still meet its deadline. An API can show a lower average while missing a tail-latency target during bursts. A move from 2 to 4 vCPU is justified when the workload repeatedly runs out of compute capacity and the additional parallelism improves an outcome that matters. ## 2 vCPU fits focused workloads when CPU has headroom A 2 vCPU VM is a reasonable starting point when the workload does not create sustained concurrent compute demand. Typical fits include: - small websites and content applications; - development and staging environments; - lightweight APIs; - internal tools; - early application backends; - one or two modest application processes; - low-frequency background jobs; - test servers and temporary environments. The important qualifier is **CPU headroom**, not project stage. A production service can stay on 2 vCPU if it meets its latency, throughput, and recovery requirements. A development build machine can justify 4 vCPU if compilation keeps both available vCPUs busy and completion time matters. Raff’s current General Purpose lineup provides several 2 vCPU shapes: | vCPU | RAM | NVMe SSD | Current monthly price | |---:|---:|---:|---:| | 2 | 2 GB | 40 GB | $8.49 | | 2 | 4 GB | 80 GB | $13.99 | | 2 | 8 GB | 160 GB | $27.99 | These sizes show why CPU and memory should be evaluated separately. A workload can stay at 2 vCPU while moving from 2 GB to 4 GB or 8 GB RAM when memory, not compute, is the constraint. ![Raff VM configuration screen showing a 2 vCPU, 2 GB RAM, and 50 GB NVMe cloud server.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_06_01_at_12_49_58_d6d783ffaf.png) *This June 2026 interface screenshot shows a historical 50 GB storage value. The current entry General Purpose plan is 2 vCPU / 2 GB RAM / 40 GB NVMe.* For entry-size workload fit beyond CPU, use [2 vCPU / 2 GB Cloud VM Workloads](/learn/guides/2-vcpu-2gb-cloud-vm-workloads). ## 4 vCPU fits workloads with repeatable concurrent compute A 4 vCPU VM becomes useful when the workload can keep additional virtual processors busy with useful work. Common candidates include: - APIs with more concurrent CPU-active requests; - multiple application workers; - queue consumers processing independent jobs; - CI runners with parallel test or build stages; - application servers sharing CPU with scheduled jobs; - data transformation or compression tasks; - self-hosted services where several processes are CPU-active at the same time. The move is especially defensible when 2 vCPU is already producing a measurable effect such as: - rising p95 or p99 request latency; - growing queue depth or oldest-job age; - builds exceeding an acceptable duration; - worker throughput falling behind arrival rate; - deployment tasks competing with normal application traffic; - repeated CPU saturation during comparable workload windows. Raff’s current General Purpose lineup includes these 4 vCPU shapes: | vCPU | RAM | NVMe SSD | Current monthly price | |---:|---:|---:|---:| | 4 | 4 GB | 80 GB | $16.99 | | 4 | 8 GB | 160 GB | $30.99 | | 4 | 16 GB | 320 GB | $52.99 | The 4 vCPU / 4 GB configuration is the cleanest comparison against a 2 vCPU / 4 GB VM because memory remains the same while compute capacity increases. That makes it easier to ask whether the workload actually needs more CPU. ![Raff VM configuration screen showing a 4 vCPU cloud server option for workloads that need more compute headroom.](https://raff-images.s3.raffusercloud.com/Screenshot_2026_06_01_at_12_56_37_2c813f1ac9.png) Four vCPU is not a reliability tier by itself. A 4 vCPU VM with a memory-constrained database can still be unstable, and a 4 vCPU application server can still wait on one slow downstream dependency. ## Four vCPUs do not make every workload twice as fast Doubling vCPU count increases available schedulable compute, but application performance rarely scales perfectly with core count. Several factors limit scaling: ### Serial code cannot use unlimited parallelism If the critical path executes on one thread, three additional virtual processors may remain mostly idle. More vCPU helps only the work that can actually run concurrently. ### Databases can wait on resources other than CPU A slow query can be limited by indexes, locks, memory, storage, or connection behavior. Adding application vCPUs will not repair the database path. ### External dependencies set their own latency An API that spends most of its time waiting for another service may not become meaningfully faster with more local compute. ### Contention can move instead of disappear A 4 vCPU VM can process more application work and then expose a database, cache, queue, or storage bottleneck that was previously hidden. ### Shared and dedicated CPU are separate decisions More shared vCPU provides more virtual processors, while dedicated CPU changes the predictability of compute allocation. If the problem is sustained execution-time variance rather than insufficient parallel capacity, read [Shared vs Dedicated vCPU](/learn/guides/shared-vs-dedicated-vcpu). The successful upgrade is not “CPU utilization fell.” It is “the workload outcome improved enough to justify the additional resources.” ## Memory, storage, and CPU allocation can matter more than core count Before moving from 2 vCPU to 4 vCPU, rule out the other common constraints. | Symptom | More likely next move | |---|---| | Swap activity, OOM events, container restarts | Add RAM / memory-forward VM | | Database cache pressure or large working set | Add RAM or separate the database | | Disk nearly full | Increase or separate storage | | High I/O wait | Diagnose storage and application I/O | | Slow query with comfortable CPU | Fix query/index/lock behavior | | External API dominates request time | Optimize dependency path or caching | | Sustained CPU with predictable parallel work | Add vCPU | | Sustained CPU with timing variance that matters | Evaluate dedicated CPU | This is the main reason not to choose VM size from vCPU count alone. For memory pressure, use [HiMem VMs Explained](/learn/guides/himem-vms-explained). For all-resource diagnosis, use [Cloud Server Performance Bottlenecks](/learn/guides/cloud-server-performance-bottlenecks-cpu-ram-disk-network). For the current full plan ladder, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). ## Measure before and after moving from 2 vCPU to 4 vCPU Treat a CPU upgrade as a testable infrastructure change. Useful measurements include: - CPU utilization over time; - system load and runnable-task pressure; - Linux CPU Pressure Stall Information (PSI) where available; - request p50, p95, and p99 latency; - queue depth and oldest-job age; - worker throughput; - build and test duration; - error and timeout rate; - memory and swap behavior; - I/O wait; - database latency. Compare equivalent workload windows. Do not compare a busy production period on 2 vCPU with an idle period on 4 vCPU. A simple before-and-after framework is: | Test | 2 vCPU baseline | 4 vCPU result | Keep the upgrade when... | |---|---|---|---| | Same API load | Record p95/p99, CPU pressure, errors | Repeat with same request mix | Tail latency or throughput improves materially | | Same worker batch | Record queue age and completion time | Repeat same job set | Backlog clears faster without moving the bottleneck | | Same CI pipeline | Record duration across several runs | Repeat same pipeline | Build/test time improves consistently | | Same mixed app load | Record CPU, memory, database, I/O | Repeat with 4 vCPU | CPU pressure falls and the user-visible outcome improves | Linux PSI is useful because it measures time tasks lose while waiting for CPU, memory, or I/O resources rather than only reporting percentage utilization. It can help distinguish “busy but healthy” from resource contention that actually stalls work. ## Raff provides 2 vCPU and 4 vCPU paths inside General Purpose Raff’s General Purpose family uses shared compute and currently offers several memory ratios at both 2 vCPU and 4 vCPU. Two useful like-for-like comparisons are: - **2 vCPU / 4 GB / 80 GB at $13.99/month** versus **4 vCPU / 4 GB / 80 GB at $16.99/month** when the question is mainly CPU capacity; - **2 vCPU / 8 GB / 160 GB at $27.99/month** versus **4 vCPU / 8 GB / 160 GB at $30.99/month** when the workload needs the same memory but different compute headroom. **Raff’s current 2 vCPU / 4 GB General Purpose VM is $13.99/month, while the 4 vCPU / 4 GB plan is $16.99/month.** Current Raff Cloud Server plans also include a **3 Gbps public port**, unmetered bandwidth, resize support, private networking, DDoS protection, browser console/root access, API and Terraform access, and monitoring. **Raff Cloud Servers include a 3 Gbps public port and unmetered VM bandwidth across current plans.** The practical path is to start with the smallest safe CPU count, measure the real workload, and resize when compute pressure becomes repeatable. Use the live [Raff pricing page](/pricing) before deployment because plan tables and prices can change. ## The right vCPU count follows the workload, not the environment label Two vCPU is enough when the workload has CPU headroom and meets its latency, throughput, and completion-time targets. Four vCPU becomes useful when repeatable concurrent compute pressure causes queues, builds, workers, or user-facing requests to miss those targets. Do not move to 4 vCPU simply because a server is “production.” A quiet production API can remain a strong 2 vCPU fit. A development or CI machine can need 4 vCPU when parallel builds are the real bottleneck. Before resizing, rule out RAM pressure, storage waits, slow queries, serial code, and external dependencies. If CPU predictability is the issue rather than core count, evaluate dedicated compute instead. For the full sizing framework, continue with [How to Choose the Right VM Size for Your Workload](/learn/guides/choosing-right-vm-size). For current Raff configurations, use [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). :::cta Explore Raff VM Compare current 2 vCPU and 4 vCPU configurations, then choose the smallest size that meets your measured workload requirements. ::: ### Sources - [Linux Kernel: Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) - [Raff Pricing](/pricing) - [Raff VM](/products/raff-vm) --- ### VPS Hosting Decision Guide: Choosing the Right Server URL: https://rafftechnologies.com/learn/guides/virtual-private-server-hosting Description: Learn how to choose VPS hosting by comparing control, management, sizing, operating systems, pricing, security, reliability, recovery, and growth requirements. VPS hosting is a server model that gives a customer an isolated operating environment with allocated compute, memory, storage, networking, and administrative control on shared physical infrastructure. The important decision is not simply whether a VPS is more powerful than shared hosting. It is whether your workload needs server-level control, whether your team can manage that control, and whether the monthly cost remains predictable after backups, licensing, storage, and operational work are included. Raff supports 3,000+ customers choosing VPS hosting and related infrastructure without hyperscaler billing complexity. This guide focuses on choosing VPS hosting rather than explaining virtualization in depth. It compares the main alternatives, provides a decision framework, shows how to size a server, and identifies the operational requirements that separate an inexpensive test server from a production-ready environment. ## VPS Hosting Is a Control and Responsibility Decision VPS hosting sits between limited hosting products and more complex infrastructure platforms. It usually gives you root or administrator access, an independent operating system, allocated resources, and freedom to install the software your workload requires. That control is valuable only when it solves a real constraint. A basic marketing website may not need a VPS. A custom API, Docker stack, database, remote Windows environment, background worker, or internal business application often does because the workload needs software, ports, services, permissions, or resource allocation that basic hosting cannot provide. The same control also transfers responsibility to your team. Unless the service is managed, you are responsible for operating-system updates, access controls, firewall rules, application deployment, monitoring, backups, and incident recovery. A VPS can simplify infrastructure architecture, but it does not remove server administration. A practical decision begins with four questions: - Does the workload require root or administrator access? - Can the team maintain the operating system and installed services? - Is a fixed server size acceptable for the next stage of growth? - What would happen if the server became unavailable or data had to be restored? When the answers are clear, VPS hosting becomes easier to compare with the alternatives. ## Compare VPS Hosting With the Real Alternatives Choosing VPS hosting makes more sense when each option is evaluated by control, operating effort, isolation, scaling model, and cost visibility. ![3. VPS Decision Framework Diagram.png](https://raff-images.s3.raffusercloud.com/3_VPS_Decision_Framework_Diagram_da74214767.png) | Infrastructure option | Best fit | Control | Operating effort | Cost model | Main limitation | | --- | --- | --- | --- | --- | --- | | Shared hosting | Simple websites and standard content management systems | Low | Low | Usually fixed | Limited software, resources, and server access | | Managed app platform | Teams deploying supported application stacks | Medium | Low to medium | Plan or usage based | Less operating-system freedom | | VPS hosting | Custom applications, APIs, databases, Docker, and remote environments | High | Medium | Usually plan based | Server administration remains your responsibility | | Dedicated server | Large fixed workloads or hardware-specific requirements | Very high | High | Fixed monthly | Higher commitment and slower resizing | | Hyperscaler architecture | Distributed systems using many managed services | Very high | High | Detailed usage based | Greater architecture and billing complexity | Shared hosting is appropriate when the provider's standard environment already supports the website. Moving that workload to a VPS may increase cost and maintenance without producing meaningful business value. A managed app platform can be a better choice when a team wants deployment automation and does not need operating-system access. The trade-off is that the team works within the runtimes, deployment model, and service boundaries supported by the platform. A dedicated server becomes relevant when a workload needs a large fixed resource pool, physical isolation, specialized hardware, or performance characteristics that justify renting an entire machine. It is usually a larger operational and financial commitment than a VPS. A broader cloud architecture is useful when the application requires managed queues, event services, multiple availability zones, autoscaling groups, complex identity policies, or a large portfolio of integrated services. Small teams should not adopt that complexity before the workload requires it. The terms VPS, cloud VM, and cloud server are often used differently by providers. The [VPS vs cloud VM vs cloud server guide](/learn/guides/vps-vs-cloud-vm-vs-cloud-server-explained) separates the terminology, while [cloud VPS vs traditional VPS](/learn/guides/cloud-vps-vs-traditional-vps) explains the infrastructure and operational differences. :::cluster ## Use a VPS Decision Framework Before Comparing Providers Provider comparison should begin after the workload requirements are defined. Otherwise, buyers tend to compare entry prices and resource numbers without deciding what the server must actually accomplish. Use the following decision framework to establish the type of VPS service you need. | Decision factor | Choose a VPS when | Consider another option when | | --- | --- | --- | | Administrative control | You need custom packages, services, ports, users, or system settings | A standard website or supported app runtime is enough | | Workload shape | Demand is reasonably stable or can be handled by planned resizing | Demand changes rapidly and needs automatic horizontal scaling | | Team capability | Someone can manage updates, access, monitoring, and recovery | No one owns server operations | | Data importance | You can define backup frequency and a tested restore path | The workload needs a managed data service with tighter recovery requirements | | Architecture | One server or a small number of servers can support the workload | The system already requires distributed services across many nodes | | Budget | A visible monthly plan helps forecasting | Usage-based elasticity is more important than monthly predictability | | Compliance | The team can configure the required controls and document responsibility | The workload requires a managed compliance scope the provider does not offer | ### Choose VPS hosting for controlled, understandable workloads VPS hosting is usually a strong fit when the application can run on one server or a small number of clearly defined servers. Common examples include websites with custom stacks, APIs, SaaS prototypes, development environments, Docker deployments, background processing, small databases, internal tools, and remote Windows workloads. It is also useful when a team wants infrastructure that can be described in simple terms: a defined number of virtual CPUs, a known amount of memory, a storage allocation, an operating system, an IP address, and a monthly price. ### Avoid VPS hosting when the operating model is missing A VPS is a poor choice when nobody is responsible for patching, access, monitoring, and recovery. Server control without operational ownership creates security and availability risk. It may also be the wrong starting point when the workload already requires automatic horizontal scaling, multi-region failover, specialized managed services, or physical hardware control. In those cases, the infrastructure model should match the architecture rather than forcing the architecture onto one server. ### Choose managed or unmanaged service deliberately An unmanaged VPS normally gives the customer responsibility for the operating system and software above the infrastructure layer. This is suitable for teams that already know how to administer Linux or Windows and want maximum configuration freedom. A managed VPS adds provider assistance for some administration tasks. The scope varies widely. Before comparing managed offers, confirm whether management includes patching, monitoring, backups, application support, security response, migration, and after-hours incidents. The word “managed” is not a complete service definition. ### Match Linux or Windows to the software requirement Linux is generally the default for open-source web stacks, containers, APIs, automation, and many database workloads. Windows is appropriate when the application requires Windows Server, Remote Desktop, Microsoft-specific frameworks, or business software built for Windows. The choice should follow software compatibility and team experience. Windows licensing can add a separate monthly cost, while Linux administration may require command-line skills. Teams evaluating Remote Desktop or Windows applications can use the [Windows VPS hosting guide](/learn/guides/windows-vps-hosting-small-teams) for a more specific decision. ## Size the VPS Around the Workload and Failure Margin Server sizing should start with the workload, expected concurrency, operating-system overhead, and the amount of spare capacity required during traffic spikes or maintenance. ![Matrix showing VPS sizing recommendations for websites, applications, databases, Docker stacks, and Windows workloads.](https://raff-images.s3.raffusercloud.com/5_VPS_Use_Case_Grid_807652d8ab.png) The following ranges are evaluation starting points, not performance guarantees. Application design, database behavior, caching, traffic patterns, and software versions can change the requirement significantly. | Workload | Evaluation starting point | Main sizing risk | | --- | --- | --- | | Development or staging server | 1–2 vCPU, 2–4 GB RAM | Running too many test services together | | Small website or API | 2 vCPU, 4 GB RAM | Traffic spikes and background jobs | | Production application or Docker stack | 2–4 vCPU, 4–8 GB RAM | Memory pressure across multiple services | | Small production database | 2–4 vCPU, 8 GB RAM or more | Working set, write activity, and disk latency | | Windows remote workload | 2–4 vCPU, 4–8 GB RAM or more | Concurrent users and application memory | | Build or compute-heavy workload | Dedicated CPU sized to the job | CPU contention and sustained processing time | ### CPU requirements follow workload behavior More virtual CPUs help only when the software can use them. A lightly used website may not benefit from four cores, while parallel builds, encoding, data processing, and busy application servers can become CPU-bound quickly. The distinction between shared and dedicated CPU also matters. Shared CPU plans are cost-effective for general workloads with variable utilization. Dedicated CPU is more appropriate when the application uses sustained processing capacity or needs more consistent compute availability. ### Memory should include operating headroom RAM must cover the operating system, application runtime, database, cache, web server, monitoring agents, and background services. A server that fits exactly during normal traffic has no margin for deployments, temporary spikes, or failed processes. Memory pressure can produce slow responses, process termination, or heavy disk swapping. It is usually safer to leave measurable headroom than to operate continuously near the limit. ### Storage decisions include speed, capacity, and recovery Storage capacity is only one part of the decision. Database-heavy applications and workloads with frequent file operations also depend on latency and throughput. Teams should estimate current data, logs, temporary files, package growth, and backup retention before selecting capacity. Critical data should not exist only on the VPS disk. The sizing plan must include backups, snapshots, or an external data copy that can be restored after deletion, corruption, or a failed change. ### Bandwidth policy affects cost predictability Check whether transfer is metered, capped, or unmetered, and whether the provider applies fair-use or sustained-use restrictions. Public websites, APIs, downloads, media delivery, and backup transfers can consume more bandwidth than a private development server. For a more detailed resource model, use the [guide to choosing the right VM size](/learn/guides/choosing-right-vm-size). ## Price VPS Hosting by Total Operating Cost The lowest plan price is not the same as the lowest operating cost. A useful VPS comparison includes the server, storage, data transfer, IP addresses, operating-system licenses, backups, snapshots, support, administration time, and the cost of resizing or migration. Create a monthly cost model with these categories: | Cost category | What to verify | | --- | --- | | Compute plan | vCPU allocation, shared or dedicated CPU, RAM, included disk | | Additional storage | Price per GB, performance class, attachment limits | | Data transfer | Included transfer, overage, port speed, restrictions | | Operating system | Windows license, Remote Desktop licensing, BYOL rules | | Protection | Backup price, snapshot price, retention, restore process | | Networking | Public IPs, private networking, load balancing, firewall options | | Support | Response scope, migration assistance, managed-service boundaries | | Operations | Staff time for updates, security, monitoring, and incident response | A cheaper server can be a rational choice for experiments, temporary environments, or noncritical workloads. The risk appears when a team buys an undersized or poorly supported plan for production and later pays through downtime, emergency migration, data recovery, or repeated manual work. The [cheap VPS vs reliable VPS guide](/learn/guides/cheap-vps-vs-reliable-vps) examines that trade-off in more depth. This decision guide should not be used to select the lowest price; it should be used to identify the lowest-cost option that still meets the workload and recovery requirements. Predictability also matters. Fixed plans help small teams forecast infrastructure cost, but only when the provider clearly states what is included. A low headline price becomes less useful when bandwidth, backups, storage, licensing, or support are unclear. ## Security, Recovery, and Management Define Production Readiness A server is not production-ready because the application starts successfully. Production readiness depends on how access is controlled, how changes are maintained, how failures are detected, and how data is recovered. ### Access should be restricted before launch Use SSH keys for Linux where practical, strong authentication for Windows, and firewall rules that expose only required services. Administrative interfaces should not be left open broadly when access can be restricted by address, VPN, private network, or another controlled path. Create named user accounts, limit administrative privileges, rotate credentials when responsibilities change, and document who can access the server. ### Updates require clear ownership Operating-system and application updates need an owner and a schedule. Delaying every update creates security risk; applying every change immediately without testing creates availability risk. Small teams need a practical maintenance process with backup verification and a rollback plan. ### Backups must support a defined recovery objective A backup is useful only when the team knows what it contains, how often it runs, how long it is retained, and how to restore it. Define acceptable data loss and recovery time before choosing a backup schedule. Snapshots can support quick rollback before a risky change, but they should not automatically replace an independent backup strategy. Application-consistent database backups may also be necessary. ### Monitoring should reflect the failure modes At minimum, monitor availability, CPU, memory, disk capacity, and the health of the application process. Add database, queue, certificate, and backup checks when those components become important. Alerts should reach someone who can respond. Collecting metrics without response ownership does not reduce downtime. The [cloud security fundamentals guide](/learn/guides/cloud-security-fundamentals) provides a broader control framework for server access, networking, updates, and data protection. ## Raff VPS Hosting Fits Predictable Small-Team Infrastructure ![Overview of Raff VM features for VPS workloads including AMD EPYC processors, NVMe SSD storage, unmetered bandwidth, and Linux or Windows support.](https://raff-images.s3.raffusercloud.com/7_Raff_VM_Context_Graphic_db57ce9a47.png) Raff VM is designed for developers, founders, and small teams that want a clear virtual-machine model without assembling a large cloud architecture first. The product decision is based on making the core variables visible: CPU model, memory, NVMe storage, bandwidth policy, operating-system choice, backup cost, and monthly plan price. From Batuhan's product perspective, a VPS plan should be judged by how easily a team can explain it before deployment and operate it after launch. The useful comparison is not the lowest visible price. It is whether the resources, bandwidth, protection options, licensing, and upgrade path are clear enough to forecast. Raff has deployed 15,000+ VMs across developer, startup, and business workloads. Raff includes a 99.9% uptime SLA for VM workloads. Current Raff VM reference points include: | Raff VM option | Included resources | Monthly price | Suitable evaluation use | | --- | --- | --- | --- | | General Purpose | 2 vCPU, 2 GB RAM, 40 GB NVMe | $8.49 | Development, lightweight services, and small sites | | General Purpose | 2 vCPU, 4 GB RAM, 80 GB NVMe | $13.99 | Small applications, APIs, and general production workloads | | CPU-Optimized | 2 dedicated vCPU, 4 GB RAM, 80 GB NVMe | $27.99 | Sustained compute and workloads needing dedicated CPU | VM plans include a 3 Gbps unmetered public bandwidth policy. Snapshots and backups are priced at $0.06 per GB-month, and each VM includes 3 free backup slots. Windows compute is available with licensing handled separately from the compute plan. These details do not make every workload a VPS workload. A managed application service may still be better when a team does not want server responsibility, and a distributed architecture may be necessary when one VM cannot meet availability or scaling requirements. Raff VM fits the decision when the workload benefits from clear server control, predictable resources, and a direct monthly cost model. ## Use a Final VPS Provider Checklist Use the final comparison only after the workload, management model, and recovery requirements have been documented. ![Decision flowchart helping users choose between shared hosting, VPS hosting, dedicated servers, and hyperscaler cloud.](https://raff-images.s3.raffusercloud.com/2_Which_hosting_option_should_you_choose_7f5dd7b923.png) Confirm each of the following before choosing a provider: - The operating system supports the required application and team skills. - The CPU allocation is clearly described as shared or dedicated. - The plan has enough RAM for the operating system, services, and operating headroom. - Storage type, capacity, expansion options, and pricing are documented. - Bandwidth, port speed, limits, and overage rules are clear. - Public IP, IPv6, firewall, and private-networking requirements are supported. - Backup and snapshot prices, retention, and restore steps are understood. - The server can be resized without an unexpected rebuild or long interruption. - Support scope and managed-service boundaries are written clearly. - The uptime commitment matches the workload's business impact. - Monthly cost includes licenses, storage, protection, and likely growth. - Someone owns patching, monitoring, access, and incident recovery after launch. A provider should be rejected when an important operating assumption cannot be verified. Missing information about backups, bandwidth, CPU allocation, licensing, or support can create more risk than a visible price difference. ## Choose the Simplest VPS That Meets the Requirement VPS hosting is a strong choice when a workload needs server-level control, fits on one VM or a small number of VMs, and has a clear owner for security, maintenance, monitoring, and recovery. It is not automatically the right upgrade from shared hosting, and it is not a substitute for a distributed architecture when the application already requires one. Define the workload first. Then choose the management model, operating system, CPU type, memory, storage, bandwidth, and protection plan. Compare providers only after those requirements are written down, and evaluate total monthly operating cost rather than the entry price alone. The right VPS is usually the simplest server that meets today's requirement with enough capacity and recovery planning for the next stage. Raff VM is one option for teams that prefer transparent resource plans, unmetered bandwidth, and a direct path between shared and dedicated compute. :::cta Explore Raff VM Compare shared and dedicated VM options after defining your workload, management, and recovery requirements. ::: --- ### Cloud VM vs App Platform: What Every Startup Needs to Know URL: https://rafftechnologies.com/learn/guides/cloud-vm-vs-app-platform-startups Description: Learn cloud VM vs app platform trade-offs for startups, including control, deployment speed, cost, scaling, storage, and when each model fits production. Cloud VM vs app platform is a hosting decision that compares server-level infrastructure control with a managed application deployment model for production software. For a startup, the useful question is not only where the code can run. It is **which operational responsibilities the team should own now**. Raff Technologies supports **3,000+ customers and 15,000+ VMs**, and the same pattern appears across early production systems: the cheapest first deploy is not always the easiest system to operate six months later. This guide anchors Raff's app-platform and deployment-workflow coverage. It explains when a managed app platform is the cleaner starting point, when a cloud VM is worth the additional responsibility, how the cost model changes as a stack grows, and when a hybrid architecture is reasonable. If you already know you need server-level control, continue with the [production VPS checklist for SaaS apps](/learn/guides/production-vps-checklist-saas-app). ## Cloud VMs and app platforms split responsibility differently A cloud VM gives the team an operating system, compute, memory, disk, networking, and administrative control. The team decides what packages are installed, how processes start, which ports are open, how traffic is routed, how the server is patched, and how the workload is recovered. An app platform moves part of that operating layer into the platform. The team provides source code or a container, configures environment variables and service settings, and uses a managed deployment workflow for builds, releases, routing, TLS, process lifecycle, and scaling behavior. That difference is the practical boundary between Infrastructure as a Service and Platform as a Service. The exact feature set varies by provider, but the responsibility trade-off remains consistent: a VM gives more control and more operating work; an app platform gives more managed behavior and more platform conventions. A startup should therefore compare **responsibility**, not only features. | Responsibility | Managed app platform | Cloud VM | |---|---|---| | Operating-system maintenance | Mostly abstracted | Team-owned | | Build and deploy workflow | Platform-managed | Team-designed | | Runtime packages | Platform or container boundary | Full OS control | | Reverse proxy and TLS | Usually managed | Team-owned | | Background processes | Platform service model | Any supported process model | | Firewall and server hardening | Shared with platform | Primarily team-owned | | Logs and process inspection | Platform surface | Platform plus OS-level access | | Scaling | Platform controls | Resize, split services, or add servers | | Portability | Depends on packaging and services | High when the server is reproducible | Neither model is more mature by definition. The better choice is the one whose operating boundary matches the workload and the team. ## The decision framework starts with control, speed, and ownership A startup should choose between a cloud VM and an app platform by evaluating deployment speed, runtime control, background work, storage, cost shape, debugging, and recovery ownership. ![Decision matrix comparing cloud VM vs app platform for startup app hosting](https://raff-images.s3.raffusercloud.com/cloud_vm_vs_app_platform_decision_matrix_webp_57612fc6e8.png) | Decision area | Choose an app platform when | Choose a cloud VM when | |---|---|---| | Launch speed | Standard deployment workflow is valuable | Infrastructure customization is required | | Team skill | Server administration should be minimized | Linux and server operations have a clear owner | | Runtime control | Buildpacks or containers cover the runtime | Custom packages, daemons, kernel-facing tools, or OS configuration matter | | Background work | Workers and cron fit platform service types | Process topology needs unrestricted control | | Networking | Managed public/private service patterns are enough | Custom ports, proxies, routes, or host networking matter | | Persistent data | Managed databases and platform volumes fit | Filesystem layout or self-hosted services need direct control | | Debugging | App logs and platform metrics are enough | OS logs, sockets, processes, and network tools are needed | | Scaling | Managed horizontal scaling is preferred | Vertical sizing or custom multi-server architecture is preferred | | Cost model | Paying for managed service boundaries is acceptable | Bundling compatible workloads on one server is useful | | Portability | Platform workflow is acceptable | Reproducible server or container control is a priority | At Raff, one practical review signal is **2+ long-running processes or custom system packages**. When either appears, we treat VM control as a serious candidate instead of assuming a managed platform is still the simplest answer. That is a decision heuristic, not a hard technical limit. A platform can support several processes, and a VM can run one simple web service. The point is to notice when the workload is becoming more operationally specific than the original deployment model. ## App platforms fit standardized deployment workflows An app platform is strongest when the application can fit a managed build-and-run model without repeated exceptions. Good candidates include: - a web app or API deployed from Git; - a containerized service with a clear start command; - a background worker that fits the platform worker model; - scheduled jobs that fit managed cron behavior; - applications that use managed databases rather than self-hosting the database engine; - teams that value preview deployments and release rollback more than OS access; - small engineering teams with no dedicated server-operations owner. The operational advantage is focus. The team can spend less time configuring reverse proxies, certificate renewal, process supervision, base-image maintenance, and deployment plumbing. That advantage is meaningful for a startup. Infrastructure work has an opportunity cost, especially when the application is still changing quickly. A platform that removes routine server work can be economically sensible even when its invoice is higher than raw compute. The limit appears when the team repeatedly works around platform assumptions. Custom system dependencies, unusual network behavior, long-running stateful processes, specialized filesystems, host-level observability, or a growing collection of platform-specific services can turn managed convenience into constraint. For provider-specific app-platform trade-offs, continue with [Render Alternative 2026](/learn/compare/render-alternative), [Vercel Alternative 2026](/learn/compare/vercel-alternative), or [Netlify Alternative 2026](/learn/compare/netlify-alternative). Those comparisons are useful only after the workload itself fits the app-platform model. ## Cloud VMs fit workloads that need operating-system control A cloud VM is the better starting point when the application needs a server rather than only a managed runtime. Typical signals include: - custom Linux packages or native libraries; - several long-running services on one host; - Docker Compose or another multi-process server layout; - a reverse proxy with custom routing behavior; - self-hosted databases during an early stage; - queue workers with specific CPU, memory, or disk requirements; - private services that need custom ports or network rules; - host-level monitoring or security agents; - server-side file processing with explicit filesystem requirements; - a deployment process that must remain portable across infrastructure providers. A VM also gives a startup a gradual architecture path. One production server can later split into an application server, database service, worker tier, object storage, load balancer, or separate internal services as evidence justifies the change. That flexibility is useful only if the server is operated properly. A VM adds responsibilities that an app platform usually hides: patching, firewall review, administrator access, backup policy, monitoring, disk growth, service supervision, and restore testing. A badly operated VM is not more professional than a managed platform. It is simply a larger failure surface. If a startup chooses the VM path, use [Single VM vs Multi-VM Architecture for SaaS Apps](/learn/guides/single-vm-vs-multi-vm-saas-architecture) before splitting services prematurely. The first architecture should be understandable before it becomes distributed. ## Cost changes when the full production stack is counted Cloud VM vs app platform pricing should be compared as a production system, not as one line item. A managed app service can begin with a small compute tier, but production cost may later include web services, workers, databases, persistent storage, preview environments, logs, and additional instances. A VM may combine several compatible processes on one server, but the startup pays in operating time and must size enough headroom for the combined workload. Use the full cost model: | Cost area | App platform | Cloud VM | |---|---|---| | Web runtime | Per service or instance | Included in selected VM capacity | | Worker runtime | Often a separate service | Can share a VM when safe | | Database | Usually a separate managed service | Self-hosted or separate managed database | | Persistent files | Platform volume or object storage | VM disk, volume, or object storage | | Public transfer | Provider-specific | Provider-specific | | Backups | Platform/service-specific | VM and workload backup plan | | Scaling | More instances or larger service tiers | Resize or split architecture | | Engineering time | Lower OS burden | Higher server-operations burden | Current Raff pricing illustrates why the units must not be treated as equivalent. **Raff Apps starts at $3/month, while Raff Cloud Server starts at $8.49/month.** Raff Apps Starter is $6.99/month for 0.5 vCPU and 1 GB RAM. A Raff General Purpose VM with 2 vCPU, 4 GB RAM, and 80 GB NVMe storage is $13.99/month. Those numbers do **not** prove that one model is cheaper for every workload. An app tier and a VM plan include different responsibilities and different resource boundaries. The useful comparison is the complete stack at the capacity and operating model the application actually needs. A startup should also put engineering time into the model. If a managed platform consistently saves several hours of operational work, the higher infrastructure bill may still be the lower business cost. If the platform requires several always-on services and the team already has strong server operations, a VM can become the simpler cost structure. ## Data, background work, and networking expose the real platform fit The hosting decision often becomes clear when the team maps stateful data, background work, and internal traffic. ### Persistent data needs its own lifecycle User uploads, database files, generated reports, and backups should not be treated as generic application disk. For many production systems: - relational data belongs in a managed database or a deliberately operated database server; - user uploads and shared files fit object storage; - mounted persistent filesystems fit a volume when filesystem semantics are required; - backups need an independent recovery policy. Read [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) before choosing storage only because it is convenient inside the first deployment. ### Background work changes the process model A simple web service can become a different workload after the product adds queues, email processing, media conversion, imports, scheduled reports, or data synchronization. An app platform is still a good fit if workers and cron jobs are first-class platform services and the cost remains clear. A VM becomes more attractive when several processes need custom supervision, local coordination, specialized packages, or a shared host-level environment. ### Networking exposes hidden assumptions A managed platform should make normal service-to-service connectivity easy. A VM gives more freedom when the workload needs custom public ports, specific reverse-proxy behavior, private subnets, unusual routing, or direct packet-level troubleshooting. The principle is not to choose the most configurable option. It is to avoid paying for flexibility the team does not need while preserving the controls the workload actually requires. ## Hybrid architectures work when ownership stays clear Cloud VM vs app platform does not need to be a permanent binary choice. ![Startup hosting path diagram showing app platform first, cloud VM first, and hybrid production setup](https://raff-images.s3.raffusercloud.com/startup_hosting_path_cloud_vm_app_platform_webp_3956241e78.png) | Pattern | When it fits | Main risk | |---|---|---| | App platform first | Standard web app, API, demo, or early production service | Platform constraints appear as workload complexity grows | | Cloud VM first | Custom runtime, several processes, server-specific networking, or controlled filesystem | Server operations are neglected | | Hybrid | Managed app plus database, object storage, or a specialized VM | Ownership and cost become fragmented | A hybrid design is healthy when each boundary is explicit. The application can run on a managed platform while a managed database and object storage hold durable state. A VM can run a specialized worker while the public app remains on a platform. A VM-hosted application can use managed data services to reduce database operations. The test is operational clarity. The team should be able to answer: 1. Where does each process run? 2. Where does durable data live? 3. Which component is public? 4. Who owns deployments and patches? 5. Where are logs and alerts reviewed? 6. How does rollback work? 7. What is restored after a failure? If those answers are unclear, adding another hosting model is more likely to add risk than flexibility. A useful startup architecture should also have an exit condition. The team should know what signal would trigger a move from platform to VM, from one VM to multiple services, or from self-hosted state to managed data products. That keeps architecture tied to workload evidence rather than preference. ## Raff Apps and Raff VM map to different responsibility models Raff now supports both sides of this decision. [Raff Apps](/products/app-platform) is the managed application path. It supports GitHub deployments, Dockerfiles, buildpacks, full Docker Compose imports, public and private services, workers, cron jobs, one-off jobs, persistent volumes, preview environments, immutable revisions, one-click rollback, managed database connections, and scale-to-zero behavior. Current plans start at **$3/month**, public application egress is priced at **$0**, team seats are not billed, and a spend cap is enabled by default. [Raff VM](/products/raff-vm) is the server-control path. Current General Purpose VM pricing starts at **$8.49/month**. VM plans include NVMe storage, **3 Gbps** public network ports, unmetered bandwidth, private networking, DDoS protection, console and root access, and resize controls. These are not competing products inside the Raff architecture. They are different operating boundaries. Choose Raff Apps when the application fits managed service types and the team wants the platform to own more deployment and runtime operations. Choose a Raff VM when the workload needs unrestricted server configuration, custom packages, broader process control, or host-level troubleshooting. The platforms can also connect to the same wider data and infrastructure services. That makes a gradual path possible: start with the operating model that fits today, then add or separate components when the workload provides a reason. The first-hand rule from earlier in this guide remains useful: **at Raff, 2+ long-running processes is a signal to evaluate VM control rather than assume a platform default.** It is not a requirement to migrate; it is a prompt to review responsibility, cost, and debugging needs before complexity becomes expensive. :::cluster ## The better model is the one your team can operate Cloud VM vs app platform comes down to operational ownership. App platforms are strong when standard deployment workflows remove work the startup should not be doing. Cloud VMs are strong when control over the operating system, process topology, storage, networking, and debugging is worth the additional responsibility. Choose for the next stage, not for an imagined final architecture. A managed platform can be the correct production choice for years. A single VM can also be a clean early production architecture when the team can secure, monitor, back up, and recover it properly. If the managed-platform path fits, compare the current [Render](/learn/compare/render-alternative), [Vercel](/learn/compare/vercel-alternative), and [Netlify](/learn/compare/netlify-alternative) alternatives. If the VM path fits, review the [production VPS checklist](/learn/guides/production-vps-checklist-saas-app) before launch. :::cta View Pricing Compare current Raff Apps and Raff VM pricing before choosing your first production size. ::: ### Sources - [Google Cloud: PaaS vs IaaS vs SaaS](https://cloud.google.com/learn/paas-vs-iaas-vs-saas) - [Raff Apps](/products/app-platform) - [Raff VM](/products/raff-vm) - [Raff Pricing](/pricing) - Product and pricing facts verified: 2026-08-08 --- ### App Uploads: VM Disk vs Object Storage for SaaS Teams URL: https://rafftechnologies.com/learn/guides/app-uploads-vm-disk-vs-object-storage Description: Learn when SaaS app uploads should stay on VM disk or move to object storage, with guidance on durability, security, scaling, migration, and Raff pricing. App upload storage is the architecture choice that determines whether user files stay tied to one application server or live in a separate durable storage layer. Once customers depend on uploaded files, the decision becomes part of production reliability rather than simple file handling. Raff Technologies supports **3,000+ customers and 15,000+ VMs**, and one pattern matters repeatedly for small teams: application compute should be replaceable without putting customer files at risk. This guide focuses on that narrow decision. Use [S3-Compatible Object Storage Use Cases for Developers](/learn/guides/s3-compatible-object-storage-use-cases-for-developers) for the wider object-storage model, and [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) when you are comparing all three storage layers. ## App uploads become production data once users depend on them App uploads are files a product receives, generates, stores, serves, or processes on behalf of users. Common examples include profile images, PDFs, invoices, CSV imports, product media, attachments, reports, exports, audio, video, and design assets. These files behave differently from app code and database records. App code should be reproducible from source or build artifacts. Database records are structured application state. Uploads are usually binary objects with their own growth, retention, access, recovery, and migration requirements. A small application often begins with a local path: ```text App VM ↓ /var/www/app/uploads ``` That is a reasonable starting point when files are temporary or low-risk. The architecture changes when the same directory becomes the source of truth for customer data. At that point, a server rebuild is no longer only a compute event; it can become a file-recovery event. At Raff, the practical design principle is simple: **durable customer files should not depend on infrastructure the team expects to rebuild, resize, replace, or scale independently.** ## The decision framework separates temporary files from durable files The right storage choice depends on file value, lifetime, access pattern, growth, and recovery needs. ![Decision matrix showing VM disk, database metadata, and object storage for app uploads](https://raff-images.s3.raffusercloud.com/app_upload_storage_decision_matrix_webp_cc02491cf8.png) | Situation | Better default | Why | |---|---|---| | Prototype or demo | VM disk | Lowest operational overhead | | Temporary processing file | VM disk | Local scratch space is appropriate | | Regenerable thumbnail or cache | VM disk or object storage | Choose from processing and delivery needs | | Internal tool with a few low-risk files | VM disk can work | Simplicity may outweigh separation | | Customer uploads are part of the product | Object storage | Files should survive app-server changes | | Upload growth is unpredictable | Object storage | Capacity grows separately from compute | | Two or more app servers need the same files | Object storage | Shared object access avoids per-server copies | | Private downloads need temporary access | Object storage | Presigned URL workflows fit controlled delivery | | Reports, exports, media, or attachments must be retained | Object storage | These are durable file objects | | App VM is being resized mainly for disk capacity | Object storage | Compute and file capacity should scale separately | | File relationships and ownership matter | Database metadata + object storage | Structured state and file bodies stay separate | A useful production rule is: > Store ownership, status, and object keys in the database. Store durable file bodies in object storage. This rule is not absolute. Tiny files with strong transactional requirements can belong in a database, and a single VM can safely host modest low-risk files. The point is to separate data when separation reduces a real operational risk. ## VM disk is acceptable while the server can remain the file owner VM disk is still the simplest choice for prototypes, temporary files, staging workflows, build artifacts that can be recreated, and small internal applications. It works well when: - the application has one server; - files are small and predictable; - uploads can be regenerated or lost without serious impact; - backup and restore are already tested; - the VM has enough storage headroom; - no other service needs shared access to the files; - file retention is short and simple. The advantage is direct filesystem access. The application can read and write normal paths without an object-storage SDK or API. The disadvantage is coupling. Uploads share the server lifecycle with application code, logs, temporary files, package caches, and possibly database files. A full disk can affect the whole product. A second app server creates a file-synchronization problem. A server replacement can require a separate file migration. VM disk becomes the wrong default when the team starts buying a larger server only because uploads are growing. That is a storage-capacity problem, not necessarily a CPU or RAM problem. Define the exit condition before local uploads become difficult to move. Good triggers include customer dependency on file retention, unpredictable storage growth, multi-server deployment, slow VM backups, or a requirement that uploads survive a full server rebuild. ## Object storage is the safer production boundary for durable uploads Object storage separates durable file data from application compute. The app stores each file as an object in a bucket and keeps the corresponding business metadata in a database. A production pattern looks like this: ```text User uploads file ↓ Application validates request ↓ Object storage receives file ↓ Database stores owner, object key, type, size, and status ``` This boundary changes several operational properties at once. **Compute becomes easier to replace.** The app server can be rebuilt, resized, or duplicated without copying the entire upload directory first. **Storage can grow for storage reasons.** File growth no longer forces the team to buy additional CPU or RAM. **Multiple application instances can share the same objects.** A second web server or worker does not need a synchronized local upload tree. **Controlled access becomes easier to model.** AWS documents presigned URLs as a method for granting time-limited object access without making the object public: [AWS S3 presigned URL documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html). Raff supports the same S3-style presigned URL workflow. Object storage is therefore a strong fit for: - user images and attachments; - PDFs and documents; - generated reports and exports; - product media; - large downloads; - files processed by workers or functions; - retained backup artifacts; - static assets that should outlive one VM. It is not a replacement for every filesystem use case. Temporary working files, software that requires normal mounted-disk semantics, and active database data belong on disk or block storage rather than in an object bucket. ## Metadata, security, and access controls belong in the application design Moving uploads to object storage does not remove application responsibility. It gives the team a clearer place to enforce that responsibility. A typical upload record should keep structured state such as: | Field | Purpose | |---|---| | `id` | Internal file identifier | | `account_id` or `user_id` | Ownership boundary | | `object_key` | Bucket object path | | `original_filename` | User-facing name | | `content_type` | MIME type | | `size_bytes` | File size | | `visibility` | Private, public, or controlled | | `checksum` | Integrity or deduplication signal | | `status` | Uploaded, processing, ready, failed, deleted | | `created_at` | Upload timestamp | | `deleted_at` | Deletion workflow state | The database answers business questions: who owns the file, which record it belongs to, whether the user can access it, and whether processing succeeded. Object storage answers file-storage questions: which object exists, how large it is, and how it is retrieved. Upload security should also cover file validation, size limits, malware scanning where appropriate, authorization, private-by-default access, credential scope, deletion rules, and logging. The [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html) highlights risks including malicious content, unrestricted retrieval, parser vulnerabilities, and storage exhaustion. A safer access flow is: ```text User requests upload or download ↓ App checks account, permission, and file rules ↓ App issues controlled S3 operation or presigned URL ↓ Object storage handles file transfer ``` Avoid treating an unguessable object key as authorization. The application should still verify tenant and user permissions before granting access. ## Cost and product limits should be part of the storage decision Current Raff Object Storage pricing is designed around one predictable base plan: | Pricing item | Current Raff Object Storage | |---|---:| | Base price | $7/month | | Included storage | 100 GB | | Included egress | 1 TB/month | | API requests | Unlimited, no request charge | | Additional storage | $0.07/GB-month | | Additional egress | $0.01/GB | | Inbound transfer | $0 | The S3-compatible endpoint is `s3.raffusercloud.com`. Traffic from Raff VMs to buckets in the same region is not charged as public egress. This cost shape is useful for upload-heavy SaaS products because storage capacity can grow without resizing application compute. It also makes transfer cost explicit once the included 1 TB of monthly egress is exceeded. Product limits matter just as much as price. Raff currently supports objects up to **5 TiB** through multipart upload. The platform supports presigned URLs, bucket policies, ACLs, and scoped access keys. **Versioning, lifecycle rules, and object lock are not currently supported**, so applications that need automatic retention transitions, immutable object retention, or built-in version history must design those requirements separately. That limitation affects deletion and retention design. If the product must retain customer files for 30, 90, or 365 days, the application or an external workflow should enforce that policy rather than assuming bucket lifecycle automation exists. The economic decision should still include engineering time. Object storage introduces SDK/API integration and a separate data layer, but it can remove the recurring operational cost of synchronizing files across servers, expanding VM disks for uploads, and moving customer files during compute changes. ## Migration should make object storage the source of truth The safest migration from VM disk to object storage is staged around one clear end state: after the migration, durable uploads no longer depend on the old local directory. A practical migration sequence is: 1. **Clean up the file metadata model.** Store file ownership, current local path, target object key, type, size, and status in a structured record. 2. **Create the bucket and access model.** Decide which application component can upload, read, and delete objects. 3. **Move existing files.** Copy the current upload set to object storage and verify object counts, sizes, checksums where practical, and representative downloads. 4. **Switch new writes.** New durable uploads should go to object storage rather than local disk. 5. **Support a temporary read fallback if needed.** During migration, the app can read from object storage first and fall back to the old path until the old set is complete. 6. **Verify production behavior.** Test upload, download, delete, permissions, file processing, exports, and backup/recovery assumptions. 7. **Remove the local dependency.** Delete old local files only after the object copy and application flows are proven. Monitor upload failures, object-storage usage, permission errors, database-to-object consistency, failed processing jobs, and download errors during the transition. The biggest migration mistake is dual ownership with no end date. If some durable files remain authoritative on VM disk while others are authoritative in object storage, recovery and debugging become harder. Pick one source of truth and complete the move. ## Raff maps uploads, metadata, and compute to separate layers Raff supports the common production separation directly. ![Architecture diagram showing Raff VM, database metadata, and Object Storage for SaaS app uploads](https://raff-images.s3.raffusercloud.com/raff_saas_upload_object_storage_architecture_webp_38396f27e3.png) A typical stack is: ```text Users ↓ Raff VM or Raff Apps = application runtime ↓ Raff Managed Database or database VM = metadata and ownership ↓ Raff Object Storage = durable uploads and generated files ``` Use VM disk for the operating system, app runtime, package cache, temporary processing workspace, and short-lived local files. Use object storage for customer uploads, media, reports, exports, attachments, large application files, and retained backup objects. This division keeps the responsibilities clear. Compute can change for performance or deployment reasons. Database capacity can change for structured-data reasons. File storage can change because customers are uploading more content. The first-hand architecture principle is the same one used earlier in this guide: **if a server must remain alive because it contains customer uploads, the file layer is controlling the compute lifecycle.** Moving durable uploads into object storage removes that dependency and gives the team more freedom to rebuild or scale the application layer. ## App uploads belong outside replaceable compute when they matter VM disk is a good tool for prototypes, temporary processing, caches, and small low-risk workloads. It stops being the cleanest default when customer files become durable product data, when multiple application instances need the same files, or when storage growth starts driving compute decisions. Object storage gives durable uploads their own capacity, access, cost, and recovery boundary. Keep file metadata and authorization in the database, keep the file body in object storage, and keep the application server replaceable. Continue with [S3-Compatible Object Storage Use Cases for Developers](/learn/guides/s3-compatible-object-storage-use-cases-for-developers) for broader S3 patterns or [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) for the wider storage decision. :::cta Explore Object Storage Store durable uploads separately from application compute and review the current 100 GB + 1 TB egress plan. ::: ### Sources - [Raff Object Storage](/products/object-storage) - [Raff Pricing](/pricing) - [AWS S3 presigned URL documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) - [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html) - Raff pricing and product limits verified: 2026-08-08 --- ### Database Backup Strategy for SaaS Apps: Recovery Framework URL: https://rafftechnologies.com/learn/guides/database-backup-strategy-saas-apps Description: Learn database backup strategy for SaaS apps using RPO, RTO, point-in-time recovery, restore testing, retention, and separate recovery layers for production. Database backup strategy is a recovery plan that defines how production data is captured, retained, restored, and tested against a SaaS application's acceptable data-loss and downtime limits. For a small SaaS team, this is a product reliability decision, not a checkbox. Raff Technologies supports **3,000+ customers and 15,000+ VMs**, and the recurring recovery gap is usually not whether a backup job exists. It is whether the team knows which recovery point to use, who owns the restore, and whether the full application can return within the required time. This guide explains the decision framework for RPO, RTO, point-in-time recovery, snapshots, database-aware backups, retention, isolation, and restore testing. For the wider production model, start with [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps). ## Database backups protect recovery history, not uptime A database backup is a recoverable copy or recovery chain that lets a team return data to an earlier valid state. That is different from availability. Replication, high availability, and failover are designed to keep a database service running through certain infrastructure failures. Backups preserve history so the team can recover from failures that a healthy replica may reproduce, including accidental deletion, a bad migration, destructive application writes, or corruption discovered later. ![Diagram showing production database backup, object storage retention, and restore testing workflow](https://raff-images.s3.raffusercloud.com/database_backup_restore_strategy_flow_webp_bce33ae672.png) A production recovery design should therefore answer four separate questions: 1. **Availability:** How does the database stay reachable after a node or host failure? 2. **History:** Which earlier states can the team recover? 3. **Isolation:** Can one incident, credential, or host failure remove every recovery copy? 4. **Evidence:** Has the restore path been tested end to end? PostgreSQL separates logical dumps, filesystem-level backups, and continuous archiving with point-in-time recovery in its official backup documentation. MySQL similarly distinguishes logical and physical backup methods and supports binary-log-based point-in-time recovery. Those database-aware mechanisms solve a different problem from a VM snapshot. A snapshot can help restore infrastructure quickly. A database backup or PITR chain helps restore database state correctly. Production systems often need both layers. ## RPO and RTO define the backup strategy Recovery Point Objective and Recovery Time Objective should be chosen before backup frequency, retention, or tooling. ![RPO and RTO explainer showing data loss window and recovery time for SaaS database backups](https://raff-images.s3.raffusercloud.com/database_backup_rpo_rto_explainer_webp_62e7d1b9f3.png) | Objective | Business question | Example | |---|---|---| | RPO | How much recent data can we lose? | At most 15 minutes of writes | | RTO | How long can the database or app remain unavailable? | Service restored within 1 hour | The two targets create different requirements. | Recovery target | Practical implication | |---|---| | RPO near 24 hours | A verified daily backup may be enough for low-change data | | RPO near 1 hour | More frequent recovery points or log-based recovery are needed | | RPO measured in minutes | Continuous WAL/binlog archiving or managed PITR becomes important | | RTO of several hours | Manual restore may be acceptable if documented and tested | | RTO near 1 hour | Restoration, validation, credentials, and traffic cutover need rehearsed steps | | RTO measured in minutes | Availability architecture may be needed in addition to backups | The key distinction is that **backup frequency does not equal RPO**. A backup job can fail, a recovery point can be inconsistent, or the required logs can be missing. The newest *usable* recovery point must satisfy the target. RTO is also wider than restore speed. It includes detection, decision, replacement infrastructure, data restoration, application validation, and returning traffic to service. Use [RPO vs RTO for Cloud Backups](/learn/guides/cloud-server-backup-rpo-rto-snapshots) when the business targets themselves are still unclear. ## Recovery design needs more than one protection layer One mechanism rarely protects a SaaS database from every failure mode. | Failure scenario | Better protection layer | Why | |---|---|---| | Primary host failure | HA or replication | Restores service continuity faster | | Accidental row deletion | PITR or database backup | Replicas may reproduce the deletion | | Bad schema migration | Pre-change recovery point + database backup | Gives a known rollback state | | Database corruption | Independent database-aware recovery | Current replicas may not preserve a clean past | | VM or disk failure | Database backup plus infrastructure recovery | Data and host recovery are separate concerns | | Credential compromise | Isolated retention and narrow backup credentials | One identity should not delete every recovery copy | | Delayed bug discovered days later | Multi-point retention | The newest backup may already contain the problem | | App server loss | Rebuild or VM recovery | The app runtime is not the database backup | | User-file loss | Object-storage recovery policy | File bodies and database records are different data sets | A useful production model is: ```text Database availability ↓ HA / replication where required Database recovery history ↓ Backups + PITR where required Infrastructure rollback ↓ VM / volume snapshots and backups Retained backup artifacts ↓ Separate storage where appropriate Recovery confidence ↓ Restore testing ``` This is why replication is not a backup and snapshots are not a complete database strategy. Each layer should have one defined job. For PostgreSQL specifically, [PostgreSQL Replication vs Backups vs Snapshots](/learn/guides/postgresql-replication-vs-backups-vs-snapshots) covers those failure boundaries in more detail. ## Managed and self-hosted databases have different recovery responsibilities The operating model changes who builds and maintains the recovery system. A managed database can remove much of the host-level backup and recovery work, but the application team still owns RPO/RTO decisions, safe restore-point selection, validation, schema behavior, migrations, credentials, and the application cutover after recovery. A self-hosted database gives the team complete control, including complete responsibility for the recovery chain. | Responsibility | Managed database | Self-hosted database | |---|---|---| | Backup platform | Provider operates within service scope | Team designs and operates it | | Database host patching | Provider scope | Team scope | | Recovery tooling | Service-defined workflow | Team-defined tooling and runbook | | Backup monitoring | Provider baseline + customer oversight | Team owns it | | PITR capability | Depends on engine/service | Team configures WAL/binlog/archive chain | | Restore validation | Customer responsibility | Customer responsibility | | Schema and migration safety | Customer responsibility | Customer responsibility | | Retention requirements | Customer decides within product capabilities | Customer designs and enforces them | | Business cutover | Customer responsibility | Customer responsibility | For self-hosted PostgreSQL, logical dumps may be useful for portability and selected restore scenarios, while physical base backups plus continuous WAL archiving support point-in-time recovery. For MySQL, logical or physical backup methods can be combined with binary logs when point-in-time recovery is required. The important question is not which method sounds more advanced. It is whether the chosen method can meet the required RPO and RTO at the current database size. Read [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) for the broader ownership decision. ## Retention and isolation protect against delayed failures Keeping only the latest backup is not enough for incidents discovered late. A bug may have overwritten data three days ago. A destructive migration may not be noticed until a customer opens an old record. A compromised credential may have been used repeatedly. In those cases, the newest backup can already contain the damaged state. Retention should therefore preserve more than one recovery point. A small team might combine: - frequent recent recovery points for short RPO; - daily points for recent history; - weekly or monthly points where longer rollback is justified; - explicit pre-migration recovery points before risky changes; - separate retention requirements for production and non-production data. The exact schedule should come from business risk, not a copied template. Isolation matters as much as age. A backup stored only on the database host shares the same failure boundary. A recovery copy deletable by the same broad production credential can also share the same security failure boundary. For self-hosted databases, a separate object-storage destination can provide a useful retention boundary for dumps or backup artifacts when the database tooling supports it. Raff Object Storage currently costs **$7/month**, including **100 GB storage and 1 TB monthly egress**, with unlimited API requests; additional storage is **$0.07/GB-month** and additional egress is **$0.01/GB**. That pricing is useful for planning retained artifacts, but storing a file in object storage does not prove database recoverability. The backup still needs integrity checks and a tested restore procedure. ## Restore testing proves the recovery target A backup that has never been restored is an unverified recovery option. Restore testing should prove the complete path: ```text Choose recovery point ↓ Restore into isolated target ↓ Start database ↓ Validate schemas and known records ↓ Connect application safely ↓ Run critical read/write checks ↓ Measure recovered data age and total recovery time ↓ Document gaps ``` The recovered data age validates RPO. The time until the application can complete critical workflows validates RTO. A database service starting successfully is not enough. The test should answer: - Is the expected schema present? - Are recent known records present for that recovery point? - Can application credentials connect? - Are migrations in the expected state? - Can a safe write complete in the isolated environment? - Can related object-storage files still be resolved where the app depends on them? - How long did the complete recovery take? - Which manual steps delayed the process? Run the restore away from production when possible. A temporary recovery environment should not send production email, payment events, webhooks, scheduled jobs, or other customer-facing side effects. The practical first-hand lesson from Raff deployment work is consistent: **backup creation is rarely the hardest part; restore ownership and application validation are where uncertainty appears.** A named recovery owner and a timed restore test reduce that uncertainty more than another untested backup copy. Use [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms) for the wider server-level verification path. ## Database migrations need an explicit recovery point Database migrations combine application change with data change, so they deserve a dedicated recovery decision. Before a destructive or high-risk migration, the team should know: - which recovery point will be used if rollback is required; - whether the backup or PITR chain is current; - how long restoration is expected to take; - whether the application can run against the restored schema; - what happens to writes created after the recovery point; - who decides to continue or roll back. A pre-migration snapshot can provide useful infrastructure rollback around a self-hosted database, but it should not replace the database-aware recovery path. Likewise, an application rollback may not reverse a schema or data migration safely. For managed databases, create the recovery point or confirm PITR coverage before the change. For self-hosted databases, confirm that the required backup and transaction logs exist outside the host and that the restore procedure has been exercised. The migration is not low-risk merely because the migration command is reversible on paper. Recovery readiness depends on the real production data shape and the ability to restore it. ## Raff maps database recovery to managed and self-hosted paths Raff supports two different responsibility models for SaaS databases. ![Architecture diagram showing Raff VM, Managed Database, Object Storage, and restore testing for SaaS backups](https://raff-images.s3.raffusercloud.com/raff_saas_database_backup_architecture_webp_b8feecccae.png) For managed PostgreSQL and MySQL, current Raff plans start at **$7.99/month**. Managed PostgreSQL includes nightly base backups plus continuous WAL archiving for point-in-time recovery to any minute. Managed MySQL includes nightly XtraBackup plus continuous binary-log upload for point-in-time recovery to any minute. Backups, private networking, and monitoring are included in the plan model. A managed path looks like: ```text Raff VM or Raff Apps ↓ private or restricted connection Raff Managed Database ↓ Managed backup + PITR workflow ↓ Customer validates restored data and app cutover ``` A self-hosted path looks like: ```text Raff VM for app ↓ private network Raff VM for database ↓ Customer-operated database-aware backups ↓ Separate retained recovery storage ↓ Restore test environment ``` Use [Raff Managed Databases](/products/managed-databases) when the team wants database backup, monitoring, patching, networking, and recovery tooling operated within a managed service boundary. Use [Raff VM](/products/raff-vm) when the team needs full database-host control and can own backup monitoring, PITR configuration, retention, restoration, patching, and incident response. For self-hosted backup artifacts, [Raff Object Storage](/products/object-storage) can provide S3-compatible retention outside the database VM. For infrastructure-level VM protection, [Raff Data Protection](/products/data-protection) provides snapshots and scheduled backups. Keep those infrastructure recovery points distinct from the database-native backup strategy. ## Database recovery works when targets are tested A SaaS database backup strategy should begin with the failure the business needs to survive. Define RPO and RTO, then select database-aware backups, PITR, retention, availability controls, infrastructure recovery points, and isolated copies that meet those targets. Managed services reduce operational work, but they do not remove customer responsibility for safe migrations, restore-point selection, data validation, credentials, and application cutover. Self-hosting gives more control, but the team must own the entire recovery chain. The most important evidence is a successful restore with measured data age and recovery time. Continue with [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps) for the full production model and [Restore Testing Checklist for Production VMs](/learn/guides/restore-testing-checklist-production-vms) for recovery validation. :::cta Explore Managed Databases Review Raff database backup, PITR, monitoring, and recovery options before choosing the operating model. ::: ### Sources - [PostgreSQL: Backup and Restore](https://www.postgresql.org/docs/current/backup.html) - [PostgreSQL: Continuous Archiving and Point-in-Time Recovery](https://www.postgresql.org/docs/current/continuous-archiving.html) - [MySQL: Backup and Recovery](https://dev.mysql.com/doc/refman/8.4/en/backup-and-recovery.html) - [NIST SP 800-34 Rev. 1](https://csrc.nist.gov/pubs/sp/800/34/r1/final) - [Raff Managed Databases](/products/managed-databases) - [Raff Object Storage](/products/object-storage) - Product and pricing details verified: 2026-08-08 --- ### Block Storage Volumes for Databases, Containers, and App Data URL: https://rafftechnologies.com/learn/guides/block-storage-volumes-databases-containers-app-data Description: Understand when block storage volumes fit databases, containers, and application data, including sizing, backups, recovery, and when object storage is better. A block storage volume is persistent disk-like storage that attaches to a virtual machine independently from its system disk. **Use one when application data needs a separate lifecycle from compute: it must survive VM replacement, grow independently, or follow its own backup and recovery plan.** For small teams, that separation matters more than adding storage for its own sake. A database may need more capacity before it needs more CPU. A container can be disposable while its state is not. A processing workload may need temporary working space without making the VM permanently larger. Raff Technologies supports 3,000+ customers and 15,000+ VMs. Our storage decision rule is to add a separate volume only when it creates a clear lifecycle or recovery boundary. If the data can be recreated with the VM, the system disk may remain the simpler choice. This guide explains where block storage volumes fit databases, containers, and application data, when object storage is better, and how sizing, backups, and recovery should affect the decision. For the broader model, read [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps). ## Block storage volumes separate persistent data from compute A VM system disk and a block storage volume can both expose a filesystem to Linux or Windows, but they serve different operational roles. The system disk normally holds the operating system, packages, application runtime, and other data coupled to that VM. A block volume is a separate storage resource that can hold persistent application data without making the boot disk the only data boundary. That separation is useful when: - storage grows faster than CPU or RAM; - the VM should be replaceable without replacing the data; - a database or application expects filesystem semantics; - a container workload needs persistent state outside its container layer; - backup and recovery policies should apply to a specific data area; - the team wants clearer ownership of persistent data. The separation does not make the data self-protecting. A volume can preserve deleted, corrupted, or incorrectly migrated data just as faithfully as valid data. Persistence and recoverability are different requirements. **A volume should create a separate lifecycle or recovery boundary; otherwise, the VM system disk may be simpler.** ## The decision framework starts with storage behavior and lifecycle Choose storage by how the workload accesses data and how that data should survive infrastructure changes. | Storage need | Better starting point | Reason | |---|---|---| | Operating system and packages | VM system disk | Coupled to the server runtime | | Re-creatable cache or scratch data | VM disk | Simple and disposable | | Self-hosted database files | Block volume | Persistent filesystem semantics | | Docker or container state | Block volume | Survives container recreation | | User uploads and shared files | Object storage | Independent from one VM and API-accessible | | Backup archives and exports | Object storage | Durable retained objects | | Managed relational data | Managed database | Reduces database operations work | | Temporary processing workspace | VM disk or volume | Depends on size and lifetime | The decision can be reduced to four questions: 1. **Does the workload require a mounted filesystem?** If no, object storage may be a better fit. 2. **Should the data survive VM replacement?** If yes, separate it from the system disk. 3. **Does storage need to grow independently from compute?** If yes, a separate volume avoids resizing the whole VM only for disk capacity. 4. **Who owns recovery?** Persistent storage still needs snapshots, backups, retention, and restore testing. Use [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) when the main question is which storage model fits the data rather than how to use a volume. ## Databases and containers benefit from clear storage boundaries Databases are a common block-storage workload because they expect persistent disk behavior, filesystem access, and predictable ownership of their data directory. A simple self-hosted database layout is: ```text Raff VM ↓ Database service ↓ Attached volume ↓ Database data directory ``` A separate volume can make capacity growth and data ownership clearer, but it does not remove database responsibilities. Production databases still need database-aware backups, restore testing, monitoring, upgrade planning, access controls, and enough free space for maintenance operations. Storage snapshots can be useful recovery points, but a database may require application-aware backup procedures to guarantee the recovery state the team expects. Treat snapshots as one layer of protection, not as a substitute for a tested database recovery process. Containers create a similar lifecycle problem. Containers are meant to be recreated; important state should not depend on a container writable layer that disappears with the container. Block storage can fit container workloads that require persistent filesystem data such as: - self-hosted database directories; - application state; - search indexes that are expensive to rebuild; - plugin or service data; - processing workspaces that need more capacity than the VM disk provides. Use object storage instead when the application stores user uploads, media, generated reports, exports, or other file objects that should be shared independently from one application node. ## Application files do not all belong on a volume “Application data” is too broad to map to one storage product. Classify each data type before choosing its location: | Data type | Typical storage choice | |---|---| | Application code | VM image, system disk, or deployment artifact | | Database records | Managed database or database volume | | User uploads | Object storage | | Static assets | Object storage or deployment artifact | | Container state | Block volume when persistent filesystem access is required | | Temporary files | VM disk or temporary volume | | Logs | Logging service, VM disk, or volume depending on retention | | Processing workspace | VM disk or volume | | Backup archive | Object storage or documented backup target | This classification prevents a block volume from becoming a catch-all disk for every file the application creates. For horizontally scaled applications, shared uploads should normally move outside individual app VMs. A block device attached to one server is not automatically shared storage for every application node. Object storage is usually the cleaner boundary when multiple servers need the same durable files. ## Growth, backup, and restore planning determine volume size Volume sizing should include more than the current dataset. Plan for: - normal data growth; - indexes and database overhead; - temporary migration or import space; - logs and retained files; - filesystem overhead; - maintenance operations; - restore testing space; - alert thresholds and growth headroom. A database that uses 80 GiB today should not automatically receive an 80 GiB volume. If it grows every month and needs temporary workspace for imports or migrations, the operational requirement is larger than the current dataset. Monitor both percentage used and expected time to exhaustion. A steadily growing disk can become an incident even when current usage still looks comfortable. Backups should be planned separately from active capacity. A volume protects the active data path; backups and snapshots create recovery points. A practical model is: ```text Volume = active persistent data Snapshot = point-in-time recovery aid Backup = scheduled recovery copy with retention Object storage = durable files or exported backup artifacts where appropriate ``` Before a risky migration or application change, a snapshot can provide an additional recovery point. For important databases, combine storage-level protection with database-aware backup procedures and verify that the restore process works. ## Security and access need deliberate boundaries Persistent volumes can hold customer records, database files, exports, logs, and other sensitive data. Treat them as part of the production security boundary. Useful controls include: - attach the volume only to workloads that need it; - restrict administrative access to the VM; - use operating-system permissions for mounted data; - keep secrets out of general-purpose data directories; - define who owns the volume and its recovery plan; - monitor unexpected capacity growth; - remove unused volumes deliberately rather than leaving them orphaned; - protect snapshots and backups with appropriate access controls. Do not treat a separate volume as an isolation boundary by itself. The operating system and application still control access to the mounted filesystem. A second operational risk is mount state. After a reboot, the application should not silently write into an empty directory on the system disk because the expected volume failed to mount. Document the mount point, test reboot behavior, and monitor the filesystem that actually contains the application data. ## Raff Volumes fit workloads that need persistent disk semantics Raff Volumes provide persistent NVMe block storage for VM workloads that need a disk-like filesystem outside the system disk. As verified on August 7, 2026, Raff Volumes are available from **10 GiB to 1 TB** at **$0.08/GiB-month**. A 100 GiB volume therefore costs **$8.00 per month** at the current rate. The live product page is the source of truth for current pricing and limits. Raff Volumes can grow online without rebooting the VM, and a volume can remain after the VM is deleted so its lifecycle does not have to match the server lifecycle. Volume data is encrypted at rest, and traffic between a VM and its attached volume is unmetered. Linux workloads use the VM disk as `/dev/vda`, with additional volumes appearing as devices such as `/dev/vdb`. **Raff Volumes currently cost $0.08/GiB-month and can grow from 10 GiB to 1 TB.** A practical Raff storage model is: ```text Raff VM system disk ├─ operating system ├─ application runtime └─ disposable local data Raff Volume └─ persistent filesystem data Raff Object Storage └─ uploads, media, exports, and shared objects Raff Data Protection └─ snapshots, backups, retention, and recovery workflows ``` Use [Block Storage vs Local Disk](/learn/guides/block-storage-vs-local-disk) when the primary decision is whether durable data belongs on the VM system disk or a separate volume. ## Common block storage mistakes create avoidable recovery risk ### Using the VM disk for every type of data A simple single-disk server is reasonable early on. Separate storage only when the data needs a distinct lifecycle, growth path, or recovery boundary. ### Treating a volume as a backup Persistence does not protect against deletion, corruption, bad migrations, or compromised credentials. Keep independent recovery points. ### Putting shared uploads on one application node If several app servers need the same durable files, object storage is usually a better architectural boundary than a filesystem attached to one VM. ### Resizing only after the disk is nearly full Track growth before capacity becomes urgent. Leave enough space for maintenance and recovery operations. ### Skipping restore tests A snapshot or backup is useful only when the team knows how to recover from it. ### Leaving mount behavior undocumented Document the device, filesystem, mount point, application path, owner, alerting, and recovery procedure. :::cluster ## Conclusion Block storage volumes are most useful when persistent filesystem data needs a lifecycle separate from the VM. Use a volume for self-hosted databases, container state, or application data that requires disk semantics and independent capacity growth. Keep user uploads and shared file objects in object storage when filesystem access is unnecessary. Treat the volume as active storage, then add snapshots, backups, retention, monitoring, and restore testing according to the workload’s recovery requirements. Continue with [Storage and Recovery Architecture for Production Apps](/learn/guides/storage-recovery-architecture-production-apps) for the wider storage model or [Object Storage vs Block Storage vs VM Disk](/learn/guides/object-storage-vs-block-storage-vs-vm-disk) for the storage-type decision. :::cta Explore Volumes Add persistent storage when application data needs a lifecycle separate from the VM. ::: ## Sources - [Raff Volumes](/products/volumes) - [Raff Object Storage](/products/object-storage) - [Raff Data Protection](/products/data-protection) - Product facts verified: 2026-08-07 --- ## Comparisons ### Amazon RDS Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/amazon-rds-alternative Description: Considering Amazon RDS? Raff starts at $7.99/mo for 1 vCPU, 1 GB RAM and 25 GB NVMe with simpler PostgreSQL pricing. Raff wins on predictable PostgreSQL plan pricing, explicit high-availability pricing, built-in pooling and private connectivity, and a smaller billing surface. Amazon RDS wins on six database engines, AWS's 39-region footprint, mature Multi-AZ and read-replica options, IAM and VPC integration, and enterprise tooling. Choose Amazon RDS when the database belongs inside a broader AWS architecture or requires multiple engines, regions, or advanced governance. Choose Raff when PostgreSQL is the requirement and the team wants published resources from $7.99/month with simpler operational cost planning. Amazon RDS is the broader managed-database platform; Raff Managed PostgreSQL is the narrower PostgreSQL service. AWS lets teams combine database classes, storage types, Multi-AZ topologies, replicas, IAM, monitoring, and regional placement. Raff keeps the buying model explicit: select a PostgreSQL tier, then add storage, HA, or replicas only when the workload requires them. ## Amazon RDS vs Raff: which is right for you? Choose Amazon RDS when database infrastructure is already part of an AWS operating model. Choose Raff when the team mainly needs managed PostgreSQL and wants the monthly database architecture to be easy to explain before deployment. | Decision factor | Choose Raff | Choose Amazon RDS | |---|---|---| | Primary database need | Managed PostgreSQL with published capacity | Broad managed relational database platform | | Paid entry | $7.99/month for 1 vCPU / 1 GB / 25 GB NVMe | Usage-based by engine, DB class, storage, topology, and Region | | High availability | Optional synchronous standby at +70% | Multi-AZ DB instance or Multi-AZ DB cluster options | | Database engines | PostgreSQL plus separate Raff managed MySQL, Valkey, ClickHouse, and Kafka products | Db2, MariaDB, SQL Server, MySQL, Oracle, PostgreSQL | | Regions | `us-east` | AWS global footprint across 39 geographic Regions | | Networking | Raff private connectivity and built-in pooling | VPC, security groups, IAM integrations, PrivateLink-related architecture | | Billing preference | Fewer explicit modifiers | Granular AWS resource and transfer billing | From our pricing and customer conversations at Raff, the useful rule is to compare the **monthly database architecture**, not the smallest instance card. High availability, replicas, storage, backup retention, cross-AZ traffic, and operational ownership usually matter more than the nominal entry price. For the broader ownership decision, read [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) and [PostgreSQL for SaaS Apps](/learn/guides/postgresql-for-saas-apps). ## Amazon RDS overview Amazon RDS is AWS's managed relational database service. AWS currently documents six supported RDS engines: IBM Db2, MariaDB, Microsoft SQL Server, MySQL, Oracle Database, and PostgreSQL. Amazon Aurora is covered separately from the core RDS engine list. RDS manages infrastructure tasks such as backups, software patching, automatic failure detection, recovery, and supported high-availability configurations. Customers still own schema design, query tuning, index strategy, connection behavior, application compatibility, and recovery validation. The service supports multiple DB instance families, including burstable, general-purpose, memory-optimized, and compute-optimized classes. For example, `db.t4g.micro` currently provides 2 vCPU and 1 GiB RAM on a burstable Graviton2 class, while larger general-purpose and memory-optimized families scale far beyond that size. RDS is strongest when teams benefit from the rest of AWS. VPC networking, IAM, CloudWatch, EventBridge, APIs, CLI tooling, reserved-instance options, cross-Region replicas, and enterprise governance can all become part of the database operating model. The trade-off is that RDS pricing is not one monthly database price. On-demand cost can include DB instance time, storage, I/O, backup storage above allowances, replicas, Multi-AZ resources, transfer, monitoring or adjacent AWS services, and engine-specific charges. ## Raff overview [Raff Managed PostgreSQL](/products/managed-databases/postgresql) provides managed PostgreSQL with published vCPU, RAM, and NVMe allocations, built-in connection pooling, monitoring, private connectivity, managed backups, point-in-time recovery for supported production workflows, storage expansion, and optional high availability. Raff offers a permanent PostgreSQL free tier with 1 vCPU, 1 GB RAM, and 2 GB storage. Current paid reference tiers include: | Raff PostgreSQL tier | Monthly price | Resources | |---|---:|---| | Entry | $7.99 | 1 vCPU / 1 GB RAM / 25 GB NVMe | | Production | $39.99 | 2 vCPU / 4 GB RAM / 80 GB NVMe | | Scale | $127.99 | 8 vCPU / 16 GB RAM / 180 GB NVMe | Raff Managed PostgreSQL starts at $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. Additional managed-database storage is $0.12/GB-month. PostgreSQL high availability adds 70% to the selected plan, and a PostgreSQL read replica is $29.99/month. Raff PostgreSQL HA adds 70% to the selected plan, making the $39.99 tier $67.98/month. Raff currently supports PostgreSQL 14, 15, and 16. The service is intentionally narrower than RDS: teams that require Oracle, SQL Server, Db2, MariaDB, or a multi-Region AWS database architecture should treat that as a real Amazon RDS advantage. Raff supports 3,000+ customers and 15,000+ production VMs under a 99.9% platform SLA. On August 17, 2026, Raff's Trustpilot profile displayed 4.5/5; G2 displays 4.6/5. ## Amazon RDS pricing vs Raff pricing Amazon RDS and Raff use different pricing models. Raff publishes PostgreSQL plans with explicit monthly prices. Amazon RDS uses pay-as-you-go resource pricing that changes with engine, Region, instance family, deployment topology, storage, and additional features. For new AWS customers under the current AWS Free Tier model, AWS offers $100 in sign-up credits and the ability to earn up to another $100. RDS Free Plan eligibility includes `db.t3.micro` and `db.t4g.micro` for PostgreSQL, MySQL, MariaDB, and eligible SQL Server Express configurations. The current AWS Free Plan is an evaluation path rather than a permanent production database tier. | Buying position | Raff Managed PostgreSQL | Amazon RDS | Practical difference | |---|---:|---|---| | Free development | $0 permanent tier — 1 vCPU / 1 GB / 2 GB | New-customer AWS credits; eligible micro RDS classes | Raff is permanent; AWS uses account credits and eligibility rules | | Entry paid | $7.99/month — 1 vCPU / 1 GB / 25 GB NVMe | On-demand DB class + storage + other usage | AWS total depends on selected configuration | | Small production | $39.99/month — 2 vCPU / 4 GB / 80 GB NVMe | Instance class + storage + I/O/backup/transfer as applicable | Raff exposes one plan ceiling; AWS exposes more tuning dimensions | | HA position | $67.98/month — $39.99 tier with +70% HA | Multi-AZ adds standby infrastructure; AWS notes cost can approach roughly 2× Single-AZ | Availability models differ; compare failover design and total resources | | Read scaling | $29.99/month PostgreSQL read replica | Read replica billed as a standard DB instance of its selected class | AWS offers broader replica topology and Region choice | **Comparison class:** these are buying positions, not matched performance tiers. Amazon RDS DB classes and Raff PostgreSQL tiers use different CPU scheduling, storage, network, and operational models. Amazon RDS for PostgreSQL on-demand usage is billed in one-second increments with a 10-minute minimum following a billable status change. AWS Reserved DB Instances can reduce long-running compute cost with one- or three-year commitments, but that adds a commitment decision that does not exist in Raff's published monthly PostgreSQL tiers. ### Automated backups and recovery cost Amazon RDS DB instances can use automated-backup retention from 0 to 35 days; setting retention to 0 disables automated backups. Multi-AZ DB clusters use a 1-to-35-day retention range. Backup storage beyond included allowances and retained backups can create additional charges. Raff includes managed backups and supports point-in-time recovery for supported production PostgreSQL workflows. Optional HA is priced separately because failover availability and historical recovery are different controls. ### Multi-AZ and replica cost AWS documents Multi-AZ DB instances as maintaining a synchronous standby in another Availability Zone. Compute is billed for both primary and standby, and storage is provisioned for both, so the topology can cost approximately twice a comparable Single-AZ instance before other differences. RDS for PostgreSQL read replicas are billed as standard DB instances. AWS currently supports up to 15 same-Region PostgreSQL read replicas from one source and up to three levels of cascading replicas on supported versions. :::cta Deploy a Database Now Deploy managed PostgreSQL with published resources, backups, pooling, private connectivity, and optional high availability. ::: ## Bandwidth and transfer policy Amazon RDS transfer cost depends on where traffic moves. AWS currently prices data between RDS and EC2 in the same Availability Zone at $0. Replication traffic for Multi-AZ deployments is also not charged as data transfer. Cross-AZ application traffic changes the picture. When EC2 and RDS communicate across Availability Zones in the same Region, AWS applies standard EC2 regional transfer charges of $0.01/GB in each direction on the EC2 side; there is no additional RDS-side transfer charge for that path. Same-Region read-replica replication is also free of data-transfer charges, while cross-Region replicas, snapshot copies, and cross-Region automated backups can incur regional transfer costs. Raff private VPC traffic is unmetered. For managed-database traffic that leaves Raff over a public path, verify the current billing for that route rather than assuming the VM-specific public bandwidth policy applies to databases. Amazon RDS is stronger when database placement across multiple AWS Regions or Availability Zones is a hard requirement. Raff is easier to model when the application and database stay inside Raff private networking in `us-east`. ## Feature comparison: Amazon RDS vs Raff | Feature | Raff Managed PostgreSQL | Amazon RDS | |---|---|---| | Core database focus | Managed PostgreSQL | Broad managed relational database service | | Supported core engines | PostgreSQL; other Raff engines are separate products | Db2, MariaDB, SQL Server, MySQL, Oracle, PostgreSQL | | Permanent free database tier | 1 vCPU / 1 GB / 2 GB | No equivalent permanent RDS production tier; current AWS Free Tier uses credits/eligibility | | Paid entry | $7.99/month | Configuration-dependent pay-as-you-go | | PostgreSQL versions | 14–16 | Broader RDS PostgreSQL version catalog varies by Region | | Connection pooling | Built in | Application/proxy architecture selected separately | | Automated backups | Managed | Automated backups configurable | | Backup retention | Product workflow | 0–35 days DB instances; 1–35 days Multi-AZ DB clusters | | High availability | Optional synchronous standby +70% | Multi-AZ DB instance and Multi-AZ DB cluster models | | Read replicas | $29.99/month PostgreSQL replica | Standard DB-instance pricing; same- and cross-Region options | | Private networking | Raff private connectivity | Amazon VPC | | IAM integration | Raff account/access model | Deep AWS IAM integration | | Monitoring | Included database monitoring | CloudWatch, RDS monitoring, Performance Insights-related tooling | | Public region model | 1 region: `us-east` | AWS global infrastructure across 39 geographic Regions | Amazon RDS wins on database-engine breadth, geography, AWS governance, instance-family choice, and replica/topology flexibility. Raff wins on published PostgreSQL capacity, explicit HA pricing, built-in pooling, and a smaller database billing surface. ## Features and reliability: Raff vs Amazon RDS This is a managed-database comparison, so feature coverage, recovery design, networking, and operating model are more useful than synthetic VM benchmarks. Raff and Amazon RDS have **0 controlled head-to-head PostgreSQL benchmarks** in this comparison, and neither is declared faster. ### Database-engine breadth Amazon RDS supports six core database engines: Db2, MariaDB, Microsoft SQL Server, MySQL, Oracle, and PostgreSQL. This is one of its strongest advantages for organizations that want one AWS control plane across several relational technologies. Raff separates managed engines into distinct products: PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka. That catalog serves common SaaS data workloads but does not replace RDS Oracle, SQL Server, Db2, or MariaDB coverage. ### High availability Amazon RDS offers both Multi-AZ DB instance and Multi-AZ DB cluster architectures. A traditional Multi-AZ DB instance maintains a synchronous standby for failover; a Multi-AZ DB cluster uses a writer and two readable instances across three Availability Zones. Raff PostgreSQL offers an optional synchronous standby and automatic-failover model priced at +70% of the selected plan. This exposes the HA modifier before deployment but provides fewer topology choices than RDS. ### Backups and recovery Amazon RDS manages automated backups, snapshots, and restore workflows with configurable retention. Cross-Region backup and snapshot options can support disaster-recovery architectures but can add storage and transfer charges. Raff includes managed backups and supports PITR for supported production workflows. On both providers, application teams still need to define recovery objectives, test restores, and validate application consistency after recovery. ### Networking and monitoring Amazon RDS integrates with Amazon VPC, security groups, IAM-related workflows, CloudWatch, EventBridge, and AWS APIs. Those integrations are valuable when the rest of the application already runs inside AWS. Raff provides private connectivity, TLS, allowlist controls, built-in pooling, and database monitoring inside a smaller cloud operating model. The trade-off is less ecosystem depth and one public region. ### Geographic reach and trust AWS currently lists 39 geographic Regions and 123 Availability Zones in its global infrastructure. Raff exposes one public region, `us-east`, so Amazon RDS is the clear choice when database placement must span several countries or continents. Raff publishes a 99.9% platform SLA and currently reports 3,000+ customers and 15,000+ production VMs. Raff's Trustpilot profile showed **4.5/5** on August 17, 2026, and G2 showed **4.6/5**. ## When you should choose Amazon RDS over Raff Choose Amazon RDS when: - **You need more database engines.** RDS supports 6 core relational engines, including Oracle, SQL Server, Db2, and MariaDB. - **Global placement matters.** AWS currently operates 39 geographic Regions; Raff exposes 1 public region. - **AWS-native governance is required.** IAM, VPC, CloudWatch, APIs, account controls, and adjacent AWS services can be part of the database architecture. - **You need broader HA topology choices.** RDS supports Multi-AZ DB instances, Multi-AZ DB clusters, and extensive replica patterns. - **Cross-Region read scaling or DR is required.** RDS PostgreSQL supports same- and cross-Region read replicas. - **Reserved pricing is acceptable.** Long-running databases can use one- or three-year Reserved DB Instance commitments. - **A large enterprise operating history matters.** RDS has a much longer production history and deeper ecosystem than Raff. ## When you should choose Raff over Amazon RDS Choose Raff when: - **PostgreSQL is the required engine.** Raff avoids the larger RDS product surface when one managed relational engine is enough. - **A fixed paid entry matters.** Raff starts at $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. - **HA pricing should be explicit.** PostgreSQL HA adds 70%; the $39.99 Production tier becomes $67.98/month. - **Built-in pooling matters.** Raff includes connection pooling rather than making it another architecture decision. - **Private Raff application paths matter.** Private VPC traffic is unmetered for Raff-hosted workloads. - **The team wants fewer billing dimensions.** Raff avoids RDS instance-family, reservation, cross-AZ, and storage/I/O combinations for ordinary PostgreSQL buying. - **`us-east` is sufficient.** AWS's global region advantage adds little when one eastern-U.S. deployment already satisfies the workload. ## Migrating from Amazon RDS to Raff A clean Amazon RDS-to-Raff migration starts by confirming that the source database is PostgreSQL. Oracle, SQL Server, Db2, MariaDB, and MySQL require an engine migration or a different Raff target rather than a direct PostgreSQL lift-and-shift. 1. **Inventory the RDS PostgreSQL instance.** Record PostgreSQL major version, extensions, DB class, storage type, parameter groups, users, roles, databases, Multi-AZ status, read replicas, backup retention, networking, IAM dependencies, and monitoring. 2. **Confirm Raff compatibility and provision the target.** Select the Raff PostgreSQL tier, verify the required PostgreSQL major version and extensions, then configure pooling, TLS, access rules, private connectivity, backups, storage, and optional HA. 3. **Move PostgreSQL data.** Use `pg_dump`/`pg_restore` for suitable databases or logical replication for an active low-downtime migration where source and target configuration permit it. 4. **Replace AWS-specific dependencies.** Update Secrets Manager or IAM database-auth assumptions, CloudWatch alarms, RDS Proxy dependencies, VPC-specific endpoints, security-group rules, Route 53 references, and cross-service automation. 5. **Verify the target.** Compare row counts, sequences, extensions, indexes, query plans, pooled and direct connections, application writes, backup behavior, restore expectations, and latency from the target application path. 6. **Cut over with rollback retained.** Coordinate final writes or replication lag, switch connection strings and allowlists, verify production traffic, and keep the RDS source available through a defined rollback window. Operational gotchas: - An RDS PostgreSQL major version or extension that Raff does not support must be resolved before migration. - RDS parameter groups do not map one-for-one to Raff managed PostgreSQL settings. - IAM database authentication, RDS Proxy, CloudWatch alarms, and AWS-native event automation need explicit replacements where used. - Multi-AZ and read-replica topology should be redesigned around Raff's HA and replica model rather than copied by name. For a production migration, keep the source database available until application behavior, database consistency, backups, and rollback have been verified end to end. ## About Amazon RDS [Amazon Relational Database Service](https://aws.amazon.com/rds/) is AWS's managed relational database service. It supports Db2, MariaDB, Microsoft SQL Server, MySQL, Oracle Database, and PostgreSQL, with managed backups, patching, monitoring integrations, Multi-AZ options, read replicas, VPC networking, APIs, CLI tooling, and Region-specific deployment choices. Amazon RDS is operated by Amazon Web Services and is designed to integrate deeply with the wider AWS cloud rather than function as a standalone PostgreSQL-only service. ## Conclusion: Amazon RDS or Raff? The Amazon-RDS-versus-Raff decision resolves across four measured axes: - **Scope** — Amazon RDS supports 6 core relational engines and extensive AWS integration; Raff keeps the comparison focused on managed PostgreSQL. - **Pricing model** — Raff paid PostgreSQL starts at $7.99/month with published resources; RDS uses configuration-dependent pay-as-you-go pricing and optional commitments. - **Availability and geography** — RDS offers multiple Multi-AZ and cross-Region patterns across AWS's 39 Regions; Raff offers a simpler +70% PostgreSQL HA model in `us-east`. - **Operational surface** — AWS exposes more instance, storage, network, IAM, monitoring, and reservation choices; Raff exposes fewer decisions and clearer modifiers. Choose Amazon RDS when multi-engine support, AWS-native governance, global placement, or advanced topology choices are requirements. Choose Raff when PostgreSQL is the requirement and the team values published capacity, explicit HA pricing, built-in pooling, private Raff connectivity, and a smaller billing surface. Raff supports **3,000+ customers and 15,000+ production VMs** under a **99.9% platform SLA** and was verified at **4.5/5** on August 17, 2026. --- ### Google Cloud Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-google-cloud Description: Considering Google Cloud? Compare Raff at $30.99/mo for 4 vCPU, 8 GB and 160 GB NVMe with Google Cloud pricing, bandwidth and tradeoffs. Raff is a practical Google Cloud alternative when a workload fits `us-east` and the priorities are lower VM list pricing, included NVMe capacity, unmetered bandwidth, and a smaller operating surface. Google Cloud is stronger when the architecture needs global regions, advanced IAM and governance, accelerators, global networking, or specialized services such as BigQuery and Vertex AI. For a current **spec-level** comparison, Raff General Purpose provides **4 vCPU / 8 GB / 160 GB NVMe for $30.99/month**, while Google Cloud lists `c4-highcpu-4` at **$0.170104/hour**, or about **$124.18 for 730 hours of compute before disk, external IPv4, egress, snapshots, support, or other services**. The May 16, 2026 benchmark on this page is preserved only as historical evidence from the configurations tested then; it is not a benchmark of Raff's current $30.99 General Purpose tier. Among Google Cloud alternatives and competitors, Raff is best evaluated as a **Compute Engine and Google Cloud VPS alternative** rather than as a replacement for every Google Cloud service. It fits buyers comparing cloud VM pricing, included storage, bandwidth, and operational simplicity; Google Cloud remains stronger when the architecture depends on its global or specialized products. For the wider location decision, review [how to choose a U.S. cloud server for latency and compliance](/learn/guides/choose-us-cloud-server-latency-compliance). ## Google Cloud vs Raff: which is right for you? The decision is less about provider size and more about operating model. Raff packages conventional cloud-server resources into a simpler monthly price, while Google Cloud provides a much broader global infrastructure and managed-service catalog. For teams comparing Google Cloud alternatives, the most useful filter is whether the workload needs a simpler VM-centric platform or the full Google Cloud service catalog. | Decision factor | Choose Raff | Choose Google Cloud | |---|---|---| | Geography | Your users and systems fit `us-east` | You require deployment across multiple Google Cloud regions or zones | | VM economics | You want RAM, listed NVMe capacity and unmetered bandwidth in one published plan price | You prefer granular resource pricing and can model separate compute, disk, IP and transfer charges | | CPU model | Shared-vCPU General Purpose plans fit the workload, or you select a Raff CPU-Optimized tier separately | You need specific Google machine families, commitments, Spot capacity, GPUs, TPUs or custom shapes | | Application platform | You need VMs, managed databases, Kubernetes, Apps, Functions and storage in a compact platform | You need GKE, Cloud SQL, AlloyDB, Spanner, BigQuery, Cloud Run, Vertex AI or other Google-native services | | Operations | A smaller product surface and direct support are valuable | Enterprise identity, policy, observability, procurement and multi-project governance are central | Raff is not a replacement for every Google Cloud service. It is most relevant as a Compute Engine alternative for conventional Linux and Windows application infrastructure where predictable monthly economics matter more than hyperscaler breadth. ## Google Cloud overview Google Cloud is a global hyperscale platform whose infrastructure products include Compute Engine, Google Kubernetes Engine, Cloud Storage, Cloud SQL, Virtual Private Cloud, load balancing, Cloud CDN and security services. Its broader catalog extends into analytics, AI, serverless computing, data engineering, databases, identity, observability and hybrid cloud. If your team uses **Google Cloud VPS** as shorthand for a Google-hosted virtual server, Compute Engine is the relevant product family for the VM-level comparison on this page. Google Cloud continues to operate across dozens of regions and more than one hundred zones. That geographic breadth remains one of its clearest advantages over Raff: teams can place workloads closer to users, spread systems across failure domains and build multi-region architectures. For a 4 vCPU / 8 GiB C4 high-CPU configuration, Google Cloud currently lists `c4-highcpu-4` at **$0.170104/hour**. At 730 hours, that is approximately **$124.18/month for compute alone**. Persistent storage, external IPv4 where used, internet egress, snapshots and support are separate billing dimensions. Google Cloud also offers committed-use discounts and Spot VMs. These can reduce compute cost, but they change the commercial assumptions through commitment length or interruption risk. ## Raff overview Raff serves customers worldwide from one public region named `us-east`. Current General Purpose cloud-server plans include: - **2 vCPU / 4 GB / 80 GB NVMe — $13.99/month** - **4 vCPU / 4 GB / 80 GB NVMe — $16.99/month** - **4 vCPU / 8 GB / 160 GB NVMe — $30.99/month** - **8 vCPU / 8 GB / 160 GB NVMe — $37.99/month** - **8 vCPU / 16 GB / 320 GB NVMe — $59.99/month** General Purpose uses shared vCPU. Raff also offers CPU-Optimized plans for workloads that need dedicated vCPU allocation; those tiers should be compared separately rather than treating the $30.99 General Purpose plan as a dedicated-CPU equivalent. Every current cloud-server plan includes unmetered bandwidth on a standard 3 Gbps public port, IPv4/IPv6 options, private networking, firewall controls, DDoS protection, root access, resize workflows, API/Terraform tooling and NVMe storage according to the selected plan. Raff also offers Managed Kubernetes, Managed Databases, Apps, Functions, Object Storage and additional block storage. Raff reports **3,000+ customers and 15,000+ VMs**, publishes a **99.9% uptime SLA**, and currently shows **4.5/5 on Trustpilot**. Google Cloud has far greater geographic scale and service breadth; Raff's advantage is a smaller operating surface and simpler pricing for conventional application infrastructure. ## Google Cloud pricing vs Raff pricing The current pricing comparison below uses **General Purpose Raff plans** against Google Cloud C4 high-CPU configurations with the same published vCPU and memory counts where available. This is a **spec-level buying comparison, not a claim of equal CPU allocation or equal performance**: Raff General Purpose uses shared vCPU, while Google Cloud C4 is a different compute architecture. | Published vCPU / memory | Raff General Purpose | Google Cloud C4 high-CPU compute only | What is excluded from Google price | |---|---:|---:|---| | 2 vCPU / 4 GB | **$13.99** with 80 GB NVMe | `c4-highcpu-2` ≈ **$62.09/mo** | Disk, external IPv4 where used, egress, snapshots, support | | 4 vCPU / 8 GB | **$30.99** with 160 GB NVMe | `c4-highcpu-4` ≈ **$124.18/mo** | Disk, external IPv4 where used, egress, snapshots, support | | 8 vCPU / 16 GB | **$59.99** with 320 GB NVMe | `c4-highcpu-8` ≈ **$248.35/mo** | Disk, external IPv4 where used, egress, snapshots, support | The 4 vCPU / 8 GB row is the clearest current buying anchor. Raff includes **160 GB NVMe and unmetered VM bandwidth for $30.99/month**. Google Cloud's approximately **$124.18/month** figure is compute only, so the final bill depends on the disk, IP, transfer and other services selected. For teams looking for a cheaper Google Cloud alternative for conventional VM hosting, this is the most useful current pricing comparison on the page. Raff also has a **4 vCPU / 4 GB / 80 GB plan at $16.99/month**. Google C4 high-CPU does not provide a directly matching 4 vCPU / 4 GiB shape, so this page does not force an artificial one-to-one comparison for that tier. Google Cloud discounts can materially reduce eligible compute pricing through one-year or three-year commitments, while Spot VMs can reduce cost for interruption-tolerant workloads. Those options can be attractive when their operating constraints fit the workload. :::cta Deploy Your Server Compare current Raff VM tiers with unmetered bandwidth and included NVMe storage. ::: ## Bandwidth and transfer policy Raff cloud-server bandwidth is unmetered on a standard 3 Gbps public port, so ordinary VM internet traffic does not create a per-GB egress line item. Google Cloud uses a more granular network-pricing model. Internet data transfer, inter-region traffic, Cloud NAT, load balancing, CDN and other paths can each have separate pricing rules. This gives architects more control but also creates more billing dimensions. For public APIs, SaaS responses, downloads, media delivery, backup replication and traffic spikes, Raff's unmetered model can be easier to forecast. Google Cloud can be stronger when workloads benefit from its global network, regional placement, CDN, private service access or broader networking products. ## Feature comparison: Google Cloud vs Raff | Area | Raff | Google Cloud | |---|---|---| | VM model | General Purpose shared vCPU plus CPU-Optimized dedicated vCPU tiers | Multiple machine families, custom shapes, Spot and specialized compute | | Current 4 vCPU / 8 GB buying anchor | $30.99 with 160 GB NVMe, shared vCPU | `c4-highcpu-4` ≈ $124.18 compute-only at 730 hours | | VM internet transfer | Unmetered, standard 3 Gbps port | Metered according to route, destination and service | | VM storage | Listed NVMe capacity included | Persistent Disk or Hyperdisk billed separately | | Managed Kubernetes | Available | GKE Standard and Autopilot | | Managed databases | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | Cloud SQL, AlloyDB, Spanner, Memorystore and more | | Application platform | Raff Apps | Cloud Run, App Engine and GKE-based options | | Functions | Raff Functions | Cloud Run functions and event services | | AI and analytics | Focused application platform | Vertex AI, BigQuery, GPUs and TPUs | | Geography | One public region, `us-east` | Global multi-region and multi-zone footprint | | Governance | Focused platform controls | Organization, folders, projects, IAM, policy and audit ecosystem | Google Cloud clearly wins on global reach, specialized infrastructure, enterprise governance, accelerators and managed-service breadth. Raff is more compelling when the workload is conventional, fits `us-east`, and benefits from a simpler server price with storage and unmetered bandwidth included. ## Performance benchmarks: Raff vs Google Cloud **The benchmark below is historical and is not used as proof of current $30.99 General Purpose performance.** It was run on **May 16, 2026** against different configurations and should be read only as a snapshot of that test window. The Raff test used a **4 vCPU / 8 GB CPU-Optimized VM with 120 GB storage under the earlier catalog**. The Google Cloud test used `c4-standard-4` with **4 vCPU / 15 GiB RAM** and Hyperdisk Balanced. The memory sizes, storage architecture and regions were not identical. ### Historical methodology | Parameter | Raff | Google Cloud | |---|---|---| | Test date | May 16, 2026 | May 16, 2026 | | Instance | Earlier CPU-Optimized 4 vCPU / 8 GB | `c4-standard-4`, 4 vCPU / 15 GiB | | Storage | 120 GB plan storage | Hyperdisk Balanced | | Region | Raff `us-east` | `us-central1` | | Tools | fio 3.36, iperf3 3.16, Geekbench 6 | Same tools | | Run count | One test window | One test window | ### Historical results | Benchmark | Raff | Google Cloud | Observed result in that test window | |---|---:|---:|---| | fio 4K total read/write | 108 MiB/s / 27.6k IOPS | 16 MB/s / 3.99k IOPS | Raff higher | | fio 64K total read/write | 1,048 MiB/s / 16.8k IOPS | 244 MB/s / ≈3.9k IOPS | Raff higher | | fio 512K total read/write | 2,135 MiB/s / 4.3k IOPS | 794 MB/s | Raff higher | | fio 1M total read/write | 2,251 MiB/s / 2.25k IOPS | 794 MB/s | Raff higher | | Geekbench 6 single-core | 2,266 | 2,001 | Raff higher | | Geekbench 6 multi-core | 6,840 | 4,450 | Raff higher | | Amsterdam iperf3 | 1.89 / 2.72 Gbps | 1.26 / 8.98 Gbps | Mixed | | Los Angeles iperf3 | Partial Raff result | 2.12 / 3.00 Gbps | Incomplete direct comparison | These results should not be generalized to current Raff General Purpose plans, all Google Cloud machine families, or future hardware. A future performance refresh should use matched memory, clearly recorded storage settings, at least three runs per test and an application-level benchmark. ## When you should choose Google Cloud over Raff Choose Google Cloud when: - You need deployment across multiple regions or zones. - Enterprise IAM, organization policy, audit and governance are mandatory. - The architecture depends on GKE, Cloud SQL, AlloyDB, Spanner, BigQuery, Cloud Run, Pub/Sub, Dataflow or Vertex AI. - You need GPUs, TPUs, Spot VMs, custom machine types or other specialized compute. - You need Google's global load balancing, CDN, Cloud Armor, Cloud NAT, Interconnect or hybrid-networking portfolio. - Commitments or Spot pricing fit your workload economics. - Multi-region residency, compliance or latency requirements cannot be met from `us-east`. ## When you should choose Raff over Google Cloud Choose Raff when: - You want a **Google Cloud VPS or Compute Engine alternative** for conventional Linux or Windows workloads rather than a replacement for every Google Cloud service. - A **4 vCPU / 8 GB / 160 GB** shared-vCPU VM at **$30.99/month** fits the workload. - You want unmetered VM bandwidth rather than a route- and destination-based egress model. - You prefer included plan storage rather than separately sizing and pricing VM disk capacity. - Your stack uses conventional VMs, managed databases, Kubernetes, Functions, Apps and object storage rather than specialized hyperscaler services. - Your users and compliance requirements fit `us-east`. - A smaller product surface and direct support reduce operational overhead for your team. Compare nearby decisions with [Raff versus AWS Lightsail](/learn/compare/raff-vs-aws-lightsail), [Raff versus DigitalOcean](/learn/compare/raff-vs-digitalocean), and [Raff versus Vultr](/learn/compare/raff-vs-vultr). :::cluster ## Migrating from Google Cloud to Raff 1. **Inventory the Google Cloud estate.** Record Compute Engine instances, machine families, disks, snapshots, images, static IPs, VPCs, firewall policies, load balancers, Cloud NAT, DNS, service accounts, secrets, monitoring and managed-service dependencies. 2. **Classify portable and non-portable components.** Linux VMs, application files, containers and common databases are usually portable. BigQuery, Spanner, Vertex AI, Google-specific IAM integrations and private Google service paths need replacement or a hybrid design. 3. **Choose the Raff target tier.** Use General Purpose for shared-vCPU workloads and CPU-Optimized where dedicated vCPU allocation is required. Do not select a target solely from the old May benchmark. 4. **Move application and data layers.** Redeploy stateless applications from source control, transfer files with rsync or equivalent tools, and migrate databases with native dump/restore or replication workflows. 5. **Validate before cutover.** Test TLS, application health, database consistency, storage mounts, outbound services, firewall rules, backups, monitoring and third-party allowlists. 6. **Cut over with rollback.** Lower DNS TTL, perform the final sync, update records, monitor production and retain the Google Cloud environment until the rollback window closes. 7. **Remove residual Google Cloud charges.** Review VMs, disks, reserved IP addresses, snapshots, images, load balancers, NAT and logging resources after verification. ## About Google Cloud [Google Cloud Compute Engine](https://cloud.google.com/compute) is Google's infrastructure-as-a-service VM platform. It connects to a global portfolio that includes Google Kubernetes Engine, Cloud Storage, Cloud SQL, Cloud Run, BigQuery, Vertex AI and extensive networking and security services. ## Conclusion: Google Cloud or Raff? For buyers comparing **Google Cloud alternatives and competitors at the VM layer**, Raff is strongest when the workload fits `us-east` and simpler monthly economics matter more than hyperscaler breadth. The current **4 vCPU / 8 GB / 160 GB Raff General Purpose plan is $30.99/month** and includes its listed NVMe capacity plus unmetered VM bandwidth. Google Cloud's `c4-highcpu-4` is approximately **$124.18/month for 730 hours of compute alone**, before storage and other separately billed resources. This is a current **pricing/spec comparison**, not a claim that the two CPU allocation models perform identically. Google Cloud remains the stronger choice for global placement, enterprise governance, accelerators, analytics, AI and specialized managed services. Raff is better aligned with teams that want a Google Cloud VPS or Compute Engine alternative for conventional cloud infrastructure, fewer billing dimensions and a compact managed application stack. The May 16, 2026 benchmark remains on this page only as historical test evidence. It should not be treated as a benchmark of the current $30.99 General Purpose tier. Continue with [the U.S. cloud server decision guide](/learn/guides/choose-us-cloud-server-latency-compliance) or review [Raff VM plans](/products/raff-vm). --- ### Bluehost Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-bluehost-vps Description: Considering Bluehost? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe with no 24-month prepay and no renewal price jump. Bluehost is a long-established web hosting company, best known for shared and WordPress hosting, that also sells a four-plan VPS line. Raff Technologies is a US cloud provider where the virtual machine is one product among several, alongside managed databases, object storage, Functions and Kubernetes on the same account. The two are not really the same kind of purchase: a Bluehost account bundles a domain, email and a hosting panel, while a Raff account is infrastructure an application runs on. At the matched entry shape, Bluehost NVMe 2 renews at $5.69/month for 1 vCPU and 2 GB, and the identical Raff shape is $6.99/month. ## Bluehost VPS and Raff at a glance **Bluehost** sells four self-managed VPS plans, from NVMe 2 at 1 vCPU core, 2 GB DDR5 RAM and 50 GB NVMe, up to NVMe 16 at 8 vCPU cores, 16 GB DDR5 and 450 GB NVMe. Every tier lists unmetered bandwidth and multiple data centers, and Bluehost states that all VPS tiers include root SSH and API access. Two things are excluded from VPS plans by Bluehost's own note: **cPanel and 24/7 priority support**. Bluehost's VPS positioning has moved toward developers — it describes the recommended NVMe 4 plan as suited to Docker, AI agents and growing applications. Pricing is promotional: each advertised rate applies to a 24-month term paid upfront, and each plan then renews higher. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from its us-east region, with a 99.9% uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Past the VM, Raff sells S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Bluehost VPS pricing vs Raff pricing Bluehost VPS plans use shared vCPU cores, so the like-for-like Raff line is General Purpose. | Shape | Bluehost promo (24-mo term) | Bluehost renewal | Bluehost upfront for 24 months | Raff General Purpose | |---|---|---|---|---| | 1 vCPU / 2 GB | $4.69 — NVMe 2, 50 GB NVMe | **$5.69** | $112.56 | **$6.99** — 1 vCPU / 2 GB / 50 GB NVMe | | 2 vCPU / 4 GB | $9.49 — NVMe 4, 100 GB NVMe | **$11.99** | $227.76 | **$13.99** — 2 vCPU / 4 GB / 80 GB NVMe | | 4 vCPU / 8 GB | $12.99 — NVMe 8, 200 GB NVMe | **$28.99** | $311.76 | **$30.99** — 4 vCPU / 8 GB / 160 GB NVMe | | 8 vCPU / 16 GB | $25.99 — NVMe 16, 450 GB NVMe | **$49.99** | $623.76 | **$59.99** — 8 vCPU / 16 GB / 320 GB NVMe | *Raff General Purpose against Bluehost's self-managed VPS — both shared vCPU. Bluehost publishes no dedicated-vCPU VPS line, so every row above is shared against shared. Bluehost pricing read from Bluehost's live VPS pricing page on 2026-08-18; all figures monthly USD.* Which Bluehost number you compare against changes the answer completely. Against the **promotional** rate, Raff is 47% to 139% more expensive. Against the **renewal** rate — the price you actually pay from month 25 onward, and the fair comparison since Raff runs no promotion — the gap collapses: | Shape | Raff | Bluehost renewal | Difference | |---|---|---|---| | 1 vCPU / 2 GB | $6.99 | $5.69 | Raff +23% | | 2 vCPU / 4 GB | $13.99 | $11.99 | Raff +17% | | 4 vCPU / 8 GB | $30.99 | $28.99 | Raff +7% | | 8 vCPU / 16 GB | $59.99 | $49.99 | Raff +20% | NVMe 8 is the clearest example: $12.99/month promotional, $28.99/month at renewal — a **123% increase on the same hardware**. Budgeting from the advertised number will understate the two-year cost of that plan by more than half. The commitment differs too. Bluehost's advertised rate needs a 24-month term paid upfront, up to $623.76 at the top tier. Raff bills monthly with no term and carries a 14-day money-back guarantee, so evaluating it does not require a two-year decision. ### Automated backups Bluehost's VPS plan cards do not list backup or snapshot pricing, so treat data protection as a separate line item to confirm before committing to a 24-month term. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure and uncapped snapshots. Storage above the pool is billed at $0.06/GB-month. ### Bandwidth Neither provider meters standard outbound transfer, so there is no overage table to build. Bluehost lists unmetered bandwidth on all four VPS tiers; Raff includes unmetered transfer on a 3 Gbps standard port. Bluehost does not publish a port speed for its VPS plans. ## Bluehost VPS performance vs Raff **Raff has not run a head-to-head benchmark against Bluehost VPS, and this page will not estimate one.** Where numbers are not measured, they are not claimed. What follows is what can be stated from published specifications and architecture. **Plan ceiling.** Bluehost's VPS line stops at NVMe 16 — 8 vCPU and 16 GB RAM. Raff General Purpose scales to 16 vCPU and 32 GB, and CPU-Optimized offers dedicated vCPU from $9.99/month. Outgrowing NVMe 16 means leaving the product; outgrowing a Raff plan means selecting a larger one. **Resize behaviour.** Raff plans change size on demand: stop the VM, switch plan, restart, with the price difference settled to your account balance. Disk grows the same way, and there is a `resize` API endpoint for both. Bluehost does not document an equivalent in-place resize for VPS plans. **Storage architecture.** Both use NVMe, but differently. Local NVMe attached to a host answers a small write without a network round trip, which favours small-block random I/O. Raff runs distributed block storage across an NVMe cluster, so a write crosses the network and is replicated before it is acknowledged — slower for small synchronous writes, and the reason data is replicated rather than pinned to one machine, snapshots and backups are taken at the storage layer, and a VM can change plan without being rebuilt. **Reliability commitments.** Raff commits to a 99.9% uptime SLA with service credits, documented in the service level agreement, running 15,000+ VMs from us-east on AMD EPYC with DDR5 ECC memory. ECC matters for long-running database and application workloads because it corrects single-bit errors rather than passing them into your data. If you need a measured comparison rather than a specification one, the honest advice is to run your own workload on both for a week. ## Bluehost vs Raff: features and reliability ### Compute Bluehost offers four shared-vCPU shapes with 2 GB to 16 GB DDR5 RAM and root SSH plus API access on every tier, ending at 8 vCPU and 16 GB. Raff offers General Purpose from $4.99/month and CPU-Optimized dedicated vCPU from $9.99/month, on AMD EPYC with DDR5 ECC memory, scaling to 16 vCPU and 32 GB, with on-demand resize through the API. ### Networking Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. Bluehost lists unmetered bandwidth and multiple data centers; private networking is not presented as part of the VPS product. ### Storage Bluehost includes more local NVMe at every tier — 100 GB against Raff's 80 GB at 2 vCPU / 4 GB, and 450 GB against 320 GB at 8 vCPU / 16 GB. Raff separates storage into VM disk, block volumes at $0.08/GiB-month that resize independently of the VM, and S3-compatible object storage at $7/month for 100 GB and 1 TB of egress. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines, through the same queue. Bluehost states that 24/7 priority support is **not** included with VPS plans, so support level is a difference to price in rather than assume. ### What Raff does not replace Bluehost is a hosting company. Raff is a cloud provider. That distinction is worth making concrete, because a Bluehost account bundles things a cloud account does not. Raff does not offer mailboxes or email hosting, domain registration, cPanel, a one-click WordPress installer, or bundled SSL certificates. Moving a site from Bluehost means leaving email and domains where they are or moving them to a specialist provider, and installing your own certificates on the VM. What replaces them is infrastructure: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month for 100 GB and 1 TB of egress, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds per month, Raff Apps from $3/month, and managed Kubernetes with a free control plane — all on one account, connected over private networking, on one bill. If what you need is a website, a mailbox and a domain on one bill, Bluehost is the right shape. If what you need is infrastructure for an application to run on, Raff is. ## When you should choose Bluehost over Raff - **A website with email and a domain on one bill** — Bluehost bundles mailboxes, domain registration and hosting; Raff offers none of the three - **WordPress and agency sites** — a hosting-account workflow rather than infrastructure to assemble ([VPS for web hosting](/learn/guides/vps-for-web-hosting)) - **Lowest monthly cost** — $9.49 promotional and $11.99 at renewal against Raff's $13.99 at 2 vCPU / 4 GB - **Storage-heavy single servers** — 450 GB NVMe at 8 vCPU / 16 GB against Raff's 320 GB - **Users outside the United States** — multiple data centers against Raff's single us-east region ## When you should choose Raff over Bluehost - **Applications that outgrow a hosting account** — Raff scales to 16 vCPU and 32 GB; Bluehost's VPS line ends at 8 vCPU and 16 GB, so outgrowing NVMe 16 means leaving the product - **APIs, containers and background jobs** — resize on demand through a `resize` API endpoint, plus Raff Apps from $3/month and managed Kubernetes with a free control plane ([VPS for Docker containers](/learn/guides/vps-for-docker-containers)) - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month over private networking, instead of running your own on the VPS ([VPS for databases](/learn/guides/vps-for-databases)) - **Workloads that must recover cleanly** — Daily and Weekly backup schedules on a free storage pool, uncapped snapshots, 1–365 day retention, and block volumes at $0.08/GiB-month, all API-driven - **Teams that cannot prepay two years** — monthly billing with a 14-day money-back guarantee; $13.99 at 2 vCPU / 4 GB is the same in month 25, against $227.76 upfront - **24/7 human support** — live chat to the same engineers at any account size, first response typically under 10 minutes; Bluehost excludes 24/7 priority support from VPS plans ## Migrating from Bluehost to Raff 1. **Inventory the account, not just the server** — record the OS version, runtimes, database engines, cron jobs, and separately: which domains, mailboxes and certificates live in the Bluehost account. Those need a new home. 2. **Decide where email and domains go first** — Raff does not host either. Settle that before touching the server, because it is the step people discover too late. 3. **Size the Raff VM by workload, not by matching disk** — Bluehost includes more local NVMe, so decide what belongs on VM disk and what moves to block volumes or object storage. 4. **Provision and harden** — create the Raff VM with the same distribution, apply firewall rules, attach private networking before moving data. 5. **Move data in order, then test before DNS** — files with rsync or SCP, then database dumps, then uploads to object storage. Run the application against the Raff VM by hostname, check logs, take a snapshot once verified. 6. **Cut over and watch the term** — lower DNS TTL beforehand, switch, then confirm your Bluehost billing term. A 24-month prepaid term does not stop when you migrate. ## About Bluehost Bluehost is a US web hosting provider offering shared hosting, WordPress hosting, domains, email and a four-plan self-managed VPS line, aimed largely at website owners and agencies. Its VPS tiers run from 1 to 8 vCPU cores with unmetered bandwidth and multiple data centers. See [Bluehost VPS hosting](https://www.bluehost.com/hosting/vps) for current plans and terms. ## Conclusion: Bluehost or Raff? The comparison resolves across four measured axes: - **Price** — Bluehost is cheaper at every tier: $9.49 promotional and $11.99 renewal against Raff's $13.99 at 2 vCPU / 4 GB - **Price stability** — Raff charges the same rate indefinitely with no prepayment; Bluehost's NVMe 8 goes from $12.99 to $28.99 at renewal, a 123% step-up on $311.76 paid upfront - **Headroom** — Raff scales to 16 vCPU and 32 GB with on-demand resize; Bluehost's VPS line ends at 8 vCPU and 16 GB - **What surrounds the server** — Raff adds managed databases, object storage, Functions, Apps and Kubernetes on one account; Bluehost adds a domain, mailboxes and a hosting panel If you want the cheapest server to run a website that will look the same in two years, and you want email and a domain on the same bill, choose Bluehost. If the workload has to grow — resize without rebuilding, pass 16 GB of RAM, or sit next to a managed database or Kubernetes cluster — choose Raff. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.9% uptime SLA in writing. --- ### Vultr Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-vultr Description: Considering Vultr? Compare Raff at $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe with Vultr VPS pricing, bandwidth, backups and 2026 tradeoffs. Raff is a Vultr alternative for teams comparing VPS and cloud hosting on price, bandwidth, storage, and operating simplicity. Raff currently lists **2 vCPU / 4 GB / 80 GB NVMe at $13.99/month** and **4 vCPU / 8 GB / 160 GB NVMe at $30.99/month**, with unmetered VM bandwidth on a standard 3 Gbps port. Vultr is stronger for global placement, GPU infrastructure, bare metal, file storage, CDN, Direct Connect, load balancing, and specialized AI services. The May 11, 2026 benchmark on this page is preserved only as a historical test snapshot and is **not** used to claim a current performance winner. For buyers searching for a **Vultr VPS alternative, Vultr cloud hosting alternative, or a cheaper Vultr alternative**, the practical question is whether you need Vultr's global infrastructure breadth or a simpler `us-east` VM platform with lower published shared-VM prices and unmetered transfer. For the broader location decision, review [how to choose a U.S. cloud server for latency and compliance](/learn/guides/choose-us-cloud-server-latency-compliance). ## Vultr vs Raff: which is right for you? The choice comes down to global infrastructure breadth versus simpler VM economics. | Decision factor | Choose Raff | Choose Vultr | |---|---|---| | Geography | Your workload fits `us-east` | You need deployment across 33 cloud data center regions | | Shared VM pricing | You want published monthly pricing with NVMe capacity and unmetered transfer included | You want multiple shared-compute families and global region choice | | Bandwidth | High or unpredictable outbound traffic makes per-GB overage undesirable | Your transfer fits Vultr's plan allocation and account bandwidth model | | Storage | Included plan NVMe plus separately available block storage fits the workload | Local-NVMe behavior, Vultr Block Storage, File System, or broader storage options matter | | Specialized infrastructure | VMs, managed databases, Kubernetes, Apps, Functions, and object storage cover the stack | You need GPU, bare metal, CDN, Direct Connect, global load balancing, or Serverless Inference | | Operational model | A smaller product surface and direct support are valuable | A larger global infrastructure catalog is more important | Vultr is not simply a more expensive VPS provider. Its geographic reach and specialized infrastructure are real advantages. Raff is more relevant when the workload can run in `us-east` and the buyer values lower published shared-VM pricing, unmetered transfer, and a compact application-infrastructure stack. ## Vultr overview Vultr is a global cloud infrastructure provider founded in 2014. Its platform includes shared Cloud Compute, dedicated compute families, VX1, Cloud GPU, Bare Metal, managed Kubernetes, managed databases, block and object storage, file storage, CDN, load balancers, Direct Connect, container registry, VPC networking, Serverless Inference, API, CLI, and Terraform support. Vultr announced Milan in May 2026 as its **33rd cloud data center region**. That geographic footprint remains one of its clearest advantages over Raff. Vultr Cloud Compute is shared-CPU infrastructure, while Optimized Cloud Compute and VX1 provide dedicated CPU options for workloads that need more predictable allocation. Pricing and plan availability can vary by region, so Vultr's order screen remains the authority for a specific deployment. ## Raff overview Raff serves customers from one public region named `us-east`. Current General Purpose monthly plans include: - **2 vCPU / 2 GB / 40 GB NVMe — $8.49** - **2 vCPU / 4 GB / 80 GB NVMe — $13.99** - **4 vCPU / 4 GB / 80 GB NVMe — $16.99** - **2 vCPU / 8 GB / 160 GB NVMe — $27.99** - **4 vCPU / 8 GB / 160 GB NVMe — $30.99** - **8 vCPU / 8 GB / 160 GB NVMe — $37.99** - **8 vCPU / 16 GB / 320 GB NVMe — $59.99** Every current Cloud Server plan includes unmetered bandwidth on a standard 3 Gbps public port, private networking, DDoS protection, root access, API/Terraform tooling, monitoring, and NVMe storage according to the selected plan. Raff's current pricing page also advertises a **free backup-and-snapshot pool up to 50 GB** that grows with the VM fleet. Raff reports **3,000+ customers and 15,000+ VMs** with a **99.9% uptime SLA**. Trustpilot showed **4.5/5** when checked on August 18, 2026. Vultr has a much longer operating history and a much larger public deployment footprint, so review scores should be read alongside the very different review-base sizes. ## Vultr pricing vs Raff pricing For shared VPS-style workloads, Raff General Purpose is the most useful starting point. The Vultr High Performance references below were last verified for this comparison on **August 10, 2026**; Vultr notes that exact pricing can vary by region, so buyers should confirm the selected location before purchase. | Shared class | Raff General Purpose | Vultr High Performance reference | Buying takeaway | |---|---:|---:|---| | 2 vCPU / 2 GB | **$8.49** — 40 GB NVMe | **$18** — 60 GB NVMe / 4 TB | Raff lower; Vultr includes more disk and transfer allowance | | 2 vCPU / 4 GB | **$13.99** — 80 GB NVMe | **$24** — 100 GB NVMe / 5 TB | Raff about 42% lower; Vultr includes 20 GB more disk | | 4 vCPU / 8 GB | **$30.99** — 160 GB NVMe | **$48** — 180 GB NVMe / 6 TB | Raff about 35% lower; Vultr includes 20 GB more disk | | 8 vCPU / 16 GB | **$59.99** — 320 GB NVMe | **$96** — 350 GB NVMe / 8 TB | Raff about 38% lower; Vultr includes more disk and transfer allowance | Raff now also has a **4 vCPU / 4 GB / 80 GB plan at $16.99/month** and a **2 vCPU / 8 GB / 160 GB plan at $27.99/month**. These shapes give buyers additional CPU-first and memory-first options without forcing an artificial one-to-one Vultr match. ### Backup pricing Vultr automatic backups add **20%** to the instance's base hourly or monthly price. Raff's current public pricing instead advertises a free backup-and-snapshot storage pool up to **50 GB** across the VM fleet; additional protection should be sized separately when the free pool is not enough. ### Billing model Vultr bills standard server products hourly with a **672-hour monthly cap**. A stopped server continues billing because the resources remain reserved; billing ends when the server is destroyed. Raff offers published subscription pricing plus hourly PAYG options, so always-on monthly comparisons are straightforward while short-lived workloads can still use hourly billing. :::cta Deploy Your Server Compare current Raff VM sizes with unmetered bandwidth and included NVMe storage. ::: ## Bandwidth and transfer policy Vultr counts outbound transfer against account bandwidth limits and charges **$0.01 per GB** when the allocated quota is exceeded. Inbound transfer is not metered. Vultr's account calculation includes a monthly free-bandwidth allocation plus bandwidth accrued by running instances. Raff VM bandwidth is unmetered on a standard 3 Gbps public port. That makes the cost model easier to forecast for public APIs, downloads, SaaS traffic, replication, media delivery, and other workloads whose outbound traffic can change sharply from month to month. The tradeoff is geographic reach. Vultr lets a team choose from many more deployment regions, while Raff currently uses one public `us-east` region. ## Feature comparison: Vultr vs Raff | Area | Raff | Vultr | |---|---|---| | Shared compute | General Purpose | Regular Performance, High Performance, High Frequency | | Dedicated compute | CPU-Optimized | Optimized Cloud Compute and VX1 | | Current 2 vCPU / 4 GB shared anchor | $13.99 / 80 GB NVMe | $24 / 100 GB NVMe / 5 TB, last verified Aug. 10 | | VM internet transfer | Unmetered, standard 3 Gbps port | Plan/account allowance, then $0.01/GB | | Backups | Free backup-and-snapshot pool up to 50 GB advertised on current pricing page | Automatic backups add 20% | | Managed Kubernetes | Available | Vultr Kubernetes Engine | | Managed databases | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | PostgreSQL, MySQL, Valkey, Kafka | | Application platform | Raff Apps | Marketplace and one-click applications | | General-purpose functions | Raff Functions | No directly equivalent general-purpose function product identified | | AI inference | Not positioned as a separate inference product | Serverless Inference | | GPU / bare metal | Not offered in the current Raff VM catalog | Available | | CDN / Direct Connect / file storage | Not part of the current Raff comparison scope | Available | | Public regions | 1 (`us-east`) | 33 | Vultr wins on geographic reach, GPU and bare-metal infrastructure, global networking products, file storage, CDN, and specialized AI inference. Raff is more focused on conventional VM and application infrastructure with fewer billing dimensions. ## Performance benchmarks: Raff vs Vultr **Historical benchmark — May 11, 2026. This section is not a current performance claim.** The preserved test compared a Raff 2 vCPU / 4 GB benchmark VM with a Vultr High Performance 2 vCPU / 4 GB shared-CPU VM. It was a single test window, the regions differed, and Raff's commercial catalog has changed since then. The results therefore should not be used to declare a present-day performance winner. ### Historical methodology | Field | Test detail | |---|---| | Test date | May 11, 2026 | | Raff VM | 2 vCPU / 4 GB / 80 GB benchmark instance in `us-east` | | Vultr VM | High Performance 2 vCPU shared / 4 GB / 100 GB local NVMe in Chicago | | Operating system | Ubuntu 24.04 LTS | | Tools | sysbench 1.0.20, fio 3.36, iperf3 3.16, redis-benchmark 7.x, SQLite benchmark | | Runs | Single pass | | Test cost | Paid at standard rates by Raff; no Vultr sponsorship or rebate | ### Historical results | Benchmark | Raff | Vultr | Observed result in that test window | |---|---:|---:|---| | Redis SET | 157,356 req/s | 70,596 req/s | Raff higher | | Redis GET | 157,356 req/s | 70,596 req/s | Raff higher | | Memory random write | 6,099 MiB/s | 2,790 MiB/s | Raff higher | | Memory random read | 5,541 MiB/s | 5,259 MiB/s | Raff slightly higher | | Memory sequential read | 131 GB/s | 127 GB/s | Raff slightly higher | | CPU single-thread | 1,662 events/s | 1,824 events/s | Vultr higher | | Disk QD1 random-read P99 | 807 µs | 53 µs | Vultr lower latency | | Disk QD32 random read | ≈75,000 IOPS | ≈210,000 IOPS | Vultr higher | | Disk sequential read | 2.4 GB/s | 4.6 GB/s | Vultr higher | | SQLite inserts | 331,000 inserts/s | 424,000 inserts/s | Vultr higher | The useful lesson from the old test is workload sensitivity: Raff led the Redis and memory-heavy measurements in that window, while Vultr led several CPU and local-disk measurements. A fresh comparison would need matched regions where practical, matched memory/storage assumptions, at least three runs, and application-level testing before making new performance claims. ## When you should choose Vultr over Raff Choose Vultr when: - You need deployment across 33 cloud data center regions. - You need GPU, bare metal, VX1, or other specialized compute families. - CDN, Direct Connect, file storage, or Vultr's load-balancing products are requirements. - Your architecture depends on global placement rather than one `us-east` region. - You want a broader infrastructure catalog under one provider. - Serverless Inference is relevant to your AI workload. - The larger operating history and deployment footprint matter to procurement. ## When you should choose Raff over Vultr Choose Raff when: - A **2 vCPU / 4 GB / 80 GB VM at $13.99/month** fits your workload. - A **4 vCPU / 8 GB / 160 GB VM at $30.99/month** fits your growth path. - Unmetered VM bandwidth is more useful than a fixed transfer allowance plus overage. - Included plan NVMe capacity and fewer pricing dimensions make budgeting easier. - Your users and compliance requirements fit `us-east`. - You need VMs, managed databases, Kubernetes, Apps, Functions, and object storage without a hyperscale service catalog. - A smaller provider relationship with direct human support is valuable to your team. Compare nearby decisions with [Raff versus DigitalOcean](/learn/compare/raff-vs-digitalocean), [Raff versus Hetzner](/learn/compare/raff-vs-hetzner), and [Raff versus AWS Lightsail](/learn/compare/raff-vs-aws-lightsail). :::cluster ## Migrating from Vultr to Raff 1. **Inventory the Vultr estate.** Record instances, plan families, regions, operating systems, disks, block storage, VPCs, firewall groups, IPs, load balancers, DNS, backups, snapshots, managed databases, and object-storage dependencies. 2. **Classify portable services.** Standard Linux/Windows VMs, files, containers, and common databases are usually portable. CDN, Direct Connect, file storage, load-balancer behavior, or Serverless Inference integrations need replacement planning. 3. **Choose the Raff target size.** Select General Purpose for shared-vCPU workloads and CPU-Optimized where dedicated CPU allocation is required. Do not size a new workload from the May benchmark alone. 4. **Move application and data layers.** Redeploy stateless services from source control, transfer files with rsync or equivalent tools, and use native database dump/restore or replication workflows. 5. **Recreate networking and security.** Build VPC/private networking, firewall rules, IP configuration, monitoring, credentials, and backup policy before cutover. 6. **Validate the full workload.** Test TLS, application health, database consistency, storage mounts, jobs, outbound integrations, third-party allowlists, and restore procedures. 7. **Cut over with rollback.** Lower DNS TTL, perform the final sync, update records, monitor production, and keep the Vultr environment until the rollback window closes. Vultr reserved IPs do not move between providers, and local-NVMe data should be treated differently from durable attached storage. Document those dependencies before migration. ## About Vultr [Vultr](https://www.vultr.com/) is a global cloud infrastructure provider offering shared and dedicated compute, VX1, GPU, bare metal, Kubernetes, managed databases, storage, CDN, load balancing, Direct Connect, networking, and Serverless Inference across 33 cloud data center regions. ## Conclusion: Vultr or Raff? For buyers comparing **Vultr alternatives, Vultr VPS pricing, and Vultr cloud hosting options**, Raff is strongest when the workload fits `us-east` and predictable VM economics matter more than global infrastructure breadth. Raff currently lists **2 vCPU / 4 GB / 80 GB at $13.99/month** and **4 vCPU / 8 GB / 160 GB at $30.99/month**, with unmetered VM bandwidth. Vultr remains stronger for global regions, GPU, bare metal, file storage, CDN, Direct Connect, load balancing, and specialized AI infrastructure. The May 11 benchmark remains on this page as historical evidence only. It is not used to claim that Raff or Vultr is faster today. Continue with [the U.S. cloud server decision guide](/learn/guides/choose-us-cloud-server-latency-compliance) or review [Raff VM plans](/products/raff-vm). --- ### AWS Lambda Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/aws-lambda-alternative Description: Considering AWS Lambda? Raff Functions has free requests and egress, active-CPU billing, and standard jobs up to 24 hours. Raff wins on free requests, free function egress, active-CPU pricing, portable handlers, and execution windows beyond Lambda's 15-minute limit. AWS Lambda wins on AWS-native integrations, a 99.95% regional SLA, global infrastructure, mature governance, Durable Functions, Managed Instances, and more than a decade of production history. Lambda's larger monthly free tier can be cheaper for small workloads, while Raff can become easier to forecast as request volume, outbound traffic, or execution length grows. Choose AWS Lambda when AWS integration is the architectural advantage; choose Raff when simpler billing, longer jobs, and portability matter more. The practical decision is workload shape rather than a single unit price. AWS Lambda includes 1 million requests and 400,000 GB-seconds each month, while Raff Functions includes 100,000 GB-seconds and 10,000 active vCPU-seconds and charges $0 for requests. Standard Lambda invocations stop at 15 minutes; Raff supports 1 hour by default and up to 24 hours on request. AWS also offers capabilities Raff does not currently match, including Durable Functions, Managed Instances, and a much broader event and governance ecosystem. ## AWS Lambda vs Raff: which is right for you? AWS Lambda is the safer default when the surrounding application is already AWS-native. Raff Functions is the clearer alternative when the function can remain a portable HTTP, cron, webhook, storage-event, or bounded background workload. | Decision factor | Choose Raff | Choose AWS Lambda | |---|---|---| | Existing platform | You want Functions with Raff compute, databases, object storage, Apps, and direct support | Your workload already depends on IAM, S3, DynamoDB, SQS, Kinesis, EventBridge, API Gateway, or CloudWatch | | Billing shape | Free requests and egress plus memory and active-CPU meters are easier to model | Lambda's 1M-request and 400k-GB-s free tier covers much of the workload | | Execution length | Jobs may exceed 15 minutes | Each standard invocation fits inside 900 seconds | | Portability | Standard application-style handlers and a Dockerfile path matter | AWS event models and service-specific integration are acceptable | | Geography | One `us-east` public region fits | You need AWS's broad regional footprint | | Governance | A smaller operating surface and direct support fit the team | IAM, Organizations, CloudTrail, Config, partner tooling, and enterprise controls are requirements | From an infrastructure-design perspective, our preference is to keep business logic portable and treat triggers as adapters wherever the application does not genuinely need provider-specific behavior. That makes it easier to move a function into a container, VM, or another execution model when duration, concurrency, or dependency requirements change. For the broader architecture decision, read [Serverless Functions vs VMs for Small Teams](/learn/guides/serverless-functions-vs-vms-small-teams) and [Portable Serverless Handlers: Avoiding Lambda Lock-In](/learn/guides/portable-serverless-handlers-avoid-lock-in). ## AWS Lambda overview [AWS Lambda](https://aws.amazon.com/lambda/) is Amazon Web Services' event-driven serverless compute service. Standard Lambda Functions are billed by request and execution duration, with a monthly free tier of 1 million requests and 400,000 GB-seconds. Lambda's core advantage is its surrounding platform. It integrates with Amazon S3, SQS, SNS, DynamoDB, Kinesis, EventBridge, API Gateway, Step Functions, CloudWatch, IAM, Secrets Manager, and many other AWS services. For an application already standardized on AWS, keeping event processing inside that architecture can reduce integration work and avoid unnecessary cross-provider data movement. Standard Lambda Functions support managed runtimes, custom runtimes, zip packages, and compatible Linux container images. A standard invocation can run for up to 900 seconds, and the default account concurrency quota is 1,000 concurrent executions per Region, with quota increases available. AWS has also expanded Lambda beyond the original short-lived function model. **Lambda Durable Functions** add checkpointed steps and waits for long-running multi-step applications; waiting can suspend compute billing while the workflow is paused. **Lambda Managed Instances** run Lambda functions on fully managed EC2 capacity, with request charges, EC2 instance charges, and a 15% management fee on the EC2 on-demand instance price. These are genuine AWS advantages for teams that want to stay inside the Lambda programming model while extending it to workflow or steady-state compute patterns. ## Raff overview [Raff Functions](/products/serverless-functions) is event-driven compute for HTTP handlers, webhooks, cron schedules, one-off future tasks, object-storage events, AI jobs, ETL, imports, exports, and batch workloads. Raff bills memory at **$0.0000035 per GB-second** and active CPU at **$0.000020 per vCPU-second**. Requests are free, function egress is free, and a spend cap is enabled by default. The monthly free tier includes **100,000 GB-seconds and 10,000 active vCPU-seconds** after the one-time account top-up requirement. Raff supports standard application-style handlers including Python FastAPI/ASGI, Node.js standard `http`, TypeScript, JavaScript Web Fetch, Go `net/http`, and a Dockerfile path for other languages or custom runtimes. The goal is to keep application logic close to ordinary web or worker code rather than require a Raff-specific handler contract. Execution windows are materially longer than standard Lambda Functions: **1 hour by default and up to 24 hours on request**. Raff currently serves Functions from one public region, `us-east`, so it does not match AWS's geographic reach or integration catalog. Raff supports **3,000+ customers and 15,000+ production VMs** under a **99.9% platform SLA**. Raff Technologies was verified at **4.5/5** on August 16, 2026, and G2 is 4.6/5. ## AWS Lambda pricing vs Raff pricing The pricing comparison changes with workload shape. AWS Lambda can cost less for small functions that remain inside its larger free tier; Raff can cost less when requests, active duration, or function egress become meaningful. AWS standard on-demand Lambda Functions in US East use a request rate of **$0.20 per 1 million requests** after the free tier and an x86 duration example rate of **$0.0000166667 per GB-second**. Raff has no request charge and meters memory plus active CPU separately. The examples below apply both monthly free tiers. AWS estimates model standard x86 Lambda Functions in US East. Raff estimates use the stated active vCPU seconds rather than assuming CPU remains active for the full wall-clock duration. Connected services, logs, databases, queues, gateways, storage, and network products are excluded. | Monthly workload | Raff Functions | AWS Lambda | Decision signal | |---|---:|---:|---| | 1M requests, 128 MB, 100 ms, 10k active vCPU-s | $0.00 | $0.00 | Both fit their free tiers | | 3M requests, 256 MB, 200 ms, 60k active vCPU-s | About $1.18 | About $0.40 | Lambda's larger free tier wins | | 10M requests, 512 MB, 300 ms, 500k active vCPU-s | About $14.70 | About $20.13 | Raff's request model starts to matter | | 5M requests, 1 GB, 1 s, 1M active vCPU-s | About $36.95 | About $77.47 | Raff is lower in this workload model | | 1M requests, 2 GB, 5 s, 1M active vCPU-s | About $54.45 | About $160.00 | Duration dominates the Lambda example | **Comparison class:** these are planning models for standard on-demand functions, not performance-equivalent benchmarks. They do not compare Lambda Durable Functions, Managed Instances, Provisioned Concurrency, Lambda@Edge, or connected AWS services. ### Additional AWS Lambda billing lines Lambda can add charges for Provisioned Concurrency, extra ephemeral storage above the included amount, response streaming beyond the included allowance, data transfer, CloudWatch, API Gateway, event-source services, ECR, VPC components, Durable Functions operations/data retention, or Managed Instances. That flexibility is a genuine AWS strength because teams can choose more specialized execution models. It also means the full architecture bill can contain more line items than the Lambda function duration alone. ### Automated backups and recovery Neither standard AWS Lambda Functions nor Raff Functions automatically backs up external application databases or arbitrary durable state. Functions should be treated as reproducible compute, with durable application data stored in databases or object storage that has its own recovery policy. AWS Lambda versioning can preserve function code and configuration, while Durable Functions checkpoint workflow progress. Those mechanisms are useful for function and workflow recovery, but they are not substitutes for database backups. On Raff, VM snapshots/backups are handled separately through [Raff Data Protection](/products/data-protection), while database and object-storage recovery should be designed around the relevant product. :::cta Deploy a Function Now Deploy HTTP, cron, webhook, storage-event, or long-running workloads on Raff Functions. ::: ## Bandwidth and transfer policy Raff Functions charges **$0 for function egress**. AWS Lambda applies Amazon EC2 data-transfer pricing when data moves into or out of the Region where the function executes, while several same-Region AWS service paths are free. For a US East internet-egress planning example, AWS provides **100 GB/month free data transfer out** aggregated across eligible AWS services and Regions. After that allowance, the standard schedule begins at $0.09/GB for the first 10 TB, $0.085/GB for the next 40 TB, $0.07/GB for the next 100 TB, and $0.05/GB above 150 TB. Using 1 TB = 1,024 GB and assuming the 100 GB shared AWS free allowance is available to this workload: | Monthly internet egress | Raff Functions | AWS transfer charge | |---:|---:|---:| | 1 TB | $0 | About $83.16 | | 5 TB | $0 | About $451.80 | | 10 TB | $0 | About $912.60 | | 50 TB | $0 | About $4,394.70 | The AWS figures are not universal Lambda bills. Data transfer between Lambda and services such as S3, DynamoDB, SQS, Kinesis, ECR, SNS, EFS, and several others is free when the traffic remains in the same AWS Region. VPC, NAT, API Gateway, CloudFront, inter-Region, or other service paths can change the total. For large files, the better pattern on either platform is usually to write the file to object storage and return a signed or controlled download path rather than proxy every byte through a function response. ## Feature comparison: AWS Lambda vs Raff | Feature | Raff Functions | AWS Lambda | |---|---|---| | Standard function timeout | 1 hour default; up to 24 hours on request | 15 minutes | | Requests | $0 | 1M free/month, then $0.20/M | | Function egress | $0 | AWS transfer rules depend on path | | Free compute | 100k GB-s + 10k active vCPU-s | 400k GB-s | | Handler model | Standard application-style handlers | Lambda handler/event model plus frameworks/adapters | | Container path | Dockerfile | Compatible Linux images through ECR | | HTTP endpoints | Included live URLs | Function URLs or API Gateway | | Schedules | Timezone-aware cron + one-off future runs | EventBridge Scheduler / rules | | Object events | Raff Object Storage | Amazon S3 | | Queue/stream integrations | Narrower | Extensive SQS, SNS, Kinesis, DynamoDB, Kafka, EventBridge integrations | | Durable workflow model | Long timeout for bounded jobs | Durable Functions with steps, waits, replay, and retention | | Managed instance model | Separate Raff VM/App products | Lambda Managed Instances | | Region footprint | 1 public region: `us-east` | Broad AWS regional availability | | Governance | Simpler Raff account model | IAM, Organizations, CloudTrail, Config, enterprise tooling | AWS wins on service integrations, regional reach, governance, durable workflow primitives, and Managed Instances. Raff wins on free requests/egress, longer standard execution windows, active-CPU billing, and a narrower portability-oriented handler model. ## Features and reliability: Raff vs AWS Lambda This page has **0 controlled Raff-vs-Lambda performance benchmarks**, so it does not declare either platform faster. Serverless performance depends on runtime, package size, architecture, configured memory, cold starts, warm capacity, downstream services, network path, and application code. ### Availability commitments AWS Lambda's current service commitment is **99.95% Monthly Uptime Percentage per AWS Region**. Raff publishes a **99.9% platform SLA**. AWS therefore has the stronger published Lambda-specific availability commitment. ### Regional footprint AWS currently operates **39 geographic Regions and 123 Availability Zones** across its global infrastructure, and Lambda is broadly available across commercial AWS Regions. Raff Functions currently exposes **1 public region, `us-east`**. AWS is the clear choice when multi-region placement, regional failover, or data-residency choice is required. ### Execution model breadth AWS Lambda now spans standard Functions, Durable Functions, and Managed Instances, with additional variants such as Provisioned Concurrency and Lambda@Edge. That gives AWS more ways to keep a workload inside the Lambda programming model as its execution pattern changes. Raff uses a simpler boundary: standard Functions for event-driven workloads, then Raff Apps or VMs when persistent compute is the better fit. This keeps the product surface smaller but does not match AWS's breadth. ### Operational trust AWS Lambda has more than a decade of production history and is embedded in AWS's mature identity, audit, support, and event ecosystem. Raff is a newer platform with **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. The correct reliability comparison is architectural. A highly available function does not compensate for a single-point-of-failure database, non-idempotent retries, weak secret handling, or an untested recovery path. ## When you should choose AWS Lambda over Raff - **AWS-native events** — S3, SQS, SNS, DynamoDB, Kinesis, EventBridge, API Gateway, and other AWS services integrate directly. - **Stronger published SLA** — Lambda commits to 99.95% Monthly Uptime Percentage per Region versus Raff's 99.9% platform SLA. - **Global placement** — AWS operates 39 geographic Regions and 123 Availability Zones; Raff Functions exposes 1 public region. - **Enterprise governance** — IAM, Organizations, CloudTrail, Config, account policies, partner tooling, and mature procurement workflows are deeper. - **Durable workflows** — Lambda Durable Functions add checkpointed steps, waits, replay, and configurable retention for multi-step workloads. - **Steady-state Lambda workloads** — Lambda Managed Instances combine the Lambda programming model with managed EC2 capacity. - **Small free-tier workloads** — 1 million requests and 400,000 GB-seconds can cover more small applications before billing begins. ## When you should choose Raff over AWS Lambda - **Long standard executions** — Raff supports 1 hour by default and up to 24 hours on request; standard Lambda Functions stop at 15 minutes. - **Request-heavy APIs** — Raff charges $0 for requests instead of a per-request line after the Lambda free tier. - **Outbound traffic** — Raff charges $0 for function egress, while AWS transfer cost depends on destination and architecture. - **I/O-heavy handlers** — Raff bills active CPU separately from memory, so waiting time is not modeled exactly like CPU-active time. - **Portable application code** — standard HTTP-style handlers make it easier to move logic toward containers or VMs later. - **Smaller operating surface** — HTTP, cron, one-off tasks, and object-storage events can be deployed without assembling as many adjacent services. ## Migrating from AWS Lambda to Raff 1. **Inventory every Lambda dependency.** Record runtimes, memory, timeout, environment variables, layers, images, IAM roles, triggers, destinations, dead-letter queues, concurrency, VPC access, CloudWatch alarms, Durable Functions, and connected services. 2. **Map each trigger to Raff.** Convert Function URLs/API Gateway to HTTP handlers, suitable EventBridge schedules to Raff cron or one-off runs, and S3 events to Raff Object Storage events. **Gotcha:** SQS, SNS, Kinesis, DynamoDB Streams, Step Functions, and many EventBridge integrations do not have direct one-to-one Raff equivalents. 3. **Extract portable business logic.** Move validation, transformations, database calls, and application rules out of Lambda-specific `event` and `context` handling. Keep AWS event parsing in a thin adapter until cutover. **Gotcha:** IAM role assumptions and AWS service credentials must be replaced with scoped Raff credentials or bindings. 4. **Create and configure the Raff function.** Choose a standard handler or Dockerfile, set memory and timeout, add environment variables/secrets, and connect required databases or object storage. 5. **Test production-shaped events.** Verify responses, retries, idempotency, logs, memory, active CPU, database connections, external APIs, presigned URLs, scheduled work, and failure behavior before production traffic moves. 6. **Cut over gradually and retain rollback.** Route a small share of HTTP traffic or switch one schedule/event source at a time, monitor both sides, keep Lambda available through the rollback window, then remove AWS triggers and permissions after verification. Lambda layers, ECR images, API Gateway authorizers, VPC-only services, CloudWatch dashboards, Durable Functions state, and provider-specific retry semantics can all increase migration effort. Do not collapse a multi-step AWS workflow into one long Raff invocation unless failure visibility and idempotency remain explicit. ## About AWS Lambda [AWS Lambda](https://aws.amazon.com/lambda/) is Amazon Web Services' serverless compute service for event-driven applications and backend workloads. It supports managed and custom runtimes, container images, numerous AWS event sources, Provisioned Concurrency, Durable Functions, and Managed Instances. Standard Functions are billed by request and duration, while specialized Lambda execution models introduce their own pricing components. ## Conclusion: AWS Lambda or Raff? AWS Lambda is the stronger choice when AWS-native integration, global placement, a 99.95% regional SLA, enterprise governance, Durable Functions, or Managed Instances are part of the requirement. Raff is the stronger alternative when the workload fits `us-east` and the priorities are free requests, free function egress, active-CPU billing, portable handlers, and standard executions beyond 15 minutes. The pricing evidence is workload-specific rather than one-sided: Lambda can be cheaper inside its larger free tier, while Raff becomes lower in several request- or duration-heavy planning examples. The architecture should decide the provider before a single unit rate does. For next-step design, read [Long-Running Serverless Functions for AI, ETL, and Batch Jobs](/learn/guides/long-running-serverless-functions-ai-etl-batch) or [Serverless Function Pricing: CPU, Memory, Requests, and Egress](/learn/guides/serverless-function-pricing-cpu-memory-egress). --- ### Neon Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/neon-alternative Description: Considering Neon? Raff is a Neon alternative from $7.99/mo for 1 vCPU, 1 GB RAM and 25 GB, with fixed pricing and managed backups. Neon and Raff solve the same managed PostgreSQL problem with different operating models. Neon treats the database as elastic developer infrastructure: Launch bills active compute at $0.106 per CU-hour, can scale to zero after 5 idle minutes, and paid plans include 500 GB of public transfer each month. Raff instead offers provisioned plans, with the first paid PostgreSQL tier at $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. Neon fits branching, previews, and intermittent demand; Raff fits continuously active production databases where published capacity and predictable plan pricing matter. ## Neon vs Raff: which is right for you? Neon and Raff both provide managed PostgreSQL, but the buyer is choosing between serverless elasticity and provisioned capacity. | Decision factor | Choose Raff | Choose Neon | |---|---|---| | Production cost model | You want a published monthly plan with listed vCPU, RAM, and storage | You want compute and storage billed by actual usage | | Development workflow | Conventional dev, staging, and production databases are enough | You need copy-on-write branches for pull requests, previews, or tests | | Idle databases | The database is expected to stay available continuously | Scale-to-zero after 5 idle minutes can materially reduce compute usage | | PostgreSQL versions | PostgreSQL 14–16 covers the application | You need PostgreSQL 17 or 18 | | Availability model | You want an optional HA add-on priced at +70% | You want Neon's Scale/Business compute-endpoint SLA and serverless architecture | | Geography | `us-east` fits the application and data-placement requirement | You need a choice across multiple AWS and Azure regions | | Billing detail | Fewer usage meters are preferable | CU-hours, database storage, history, branches, and transfer are acceptable | Choose Neon when database environments are frequently created, cloned, suspended, and discarded. Choose Raff when the database is a steady production dependency and the team wants capacity, recovery, and cost decisions to be explicit before deployment. For the broader operating-model decision, read [PostgreSQL for SaaS Apps](/learn/guides/postgresql-for-saas-apps) and [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases). ## Neon overview Neon is a serverless PostgreSQL service built around separated compute and storage. Projects can contain branches, compute endpoints, databases, roles, and read replicas while remaining compatible with PostgreSQL clients and drivers. Its defining workflow is database branching. A child branch can be created without immediately copying the full parent database, which makes branches useful for pull-request previews, migration tests, CI jobs, developer sandboxes, and other short-lived environments. Neon also supports autoscaling and scale-to-zero. Free and Launch computes suspend after 5 minutes of inactivity by default; paid plans can keep a compute always active. Current public pricing positions include: - **Free — $0:** 100 projects, 100 CU-hours per project each month, 0.5 GB storage per project, compute up to 2 CU, and up to 6 hours of restore history. - **Launch — usage-based:** $0.106 per CU-hour, $0.35 per GB-month of database storage, up to 16 CU, and up to 7 days of restore history. - **Scale — usage-based:** $0.222 per CU-hour, $0.35 per GB-month, up to 56 CU, up to 30 days of restore history, private networking, IP allow rules, and an SLA for covered compute endpoints. Paid plans include 500 GB of public transfer each month from June 1, 2026. Neon also charges $0.002 per branch-hour above included allowances and $0.20 per GB-month for restore-history data on paid plans. Neon supports PostgreSQL 14, 15, 16, 17, and 18. Its February 2026 version update listed 14.21, 15.16, 16.12, 17.8, and 18.2. Neon became a Databricks company in May 2025. ## Raff overview [Raff Managed PostgreSQL](/products/managed-databases/postgresql) uses provisioned database plans with published vCPU, RAM, and NVMe allocations. Raff currently supports PostgreSQL 14, 15, and 16 with managed backups, point-in-time recovery for supported production workflows, monitoring, built-in connection pooling, private connectivity, storage expansion, and optional high availability. Raff has both a permanent free tier and paid plans: - **Free — $0/month:** 1 vCPU, 1 GB RAM, 2 GB storage, up to 60 direct connections and 200 pooled connections. - **Paid entry — $7.99/month:** 1 vCPU, 1 GB RAM, and 25 GB NVMe. - **Production — $39.99/month:** 2 vCPU, 4 GB RAM, and 80 GB NVMe. - **Scale — $127.99/month:** 8 vCPU, 16 GB RAM, and 180 GB NVMe. Additional managed-database storage is $0.12/GB-month. PostgreSQL high availability adds 70% to the selected plan price, and a PostgreSQL read replica is $29.99/month. A recurring Raff operations rule is to size PostgreSQL in this order: **workload → recovery target → connection model → ownership model → capacity**. That keeps a larger plan from becoming the default answer to connection storms, poor queries, or an undefined recovery target. Raff supports 3,000+ customers and 15,000+ production VMs and publishes a 99.9% uptime SLA. On August 16, 2026, Raff's Trustpilot profile showed 4.5/5; G2 is 4.6/5. ## Neon pricing vs Raff pricing The pricing models are different enough that a forced "same-size plan" would be misleading. Raff sells provisioned tiers; Neon bills active compute in CU-hours plus database storage and other usage dimensions. The table therefore compares buying positions rather than claiming equal performance. | Buying position | Raff Managed PostgreSQL | Neon | What it means | |---|---|---|---| | Free development | $0 — 1 vCPU / 1 GB / 2 GB; 60 direct / 200 pooled connections | $0 — 100 CU-hours/project, 0.5 GB/project, up to 2 CU | Both have permanent free tiers with different ceilings | | Entry paid | $7.99/month — 1 vCPU / 1 GB / 25 GB | Launch — $0.106/CU-hour + $0.35/GB-month | Raff fixes the base monthly plan; Neon follows active usage | | Always-active example | $7.99/month within the paid entry allocation | 0.25 CU for 730 h + 5 GB storage ≈ $21.10/month | Neon example is usage math, not a matched resource tier | | Production position | $39.99/month — 2 vCPU / 4 GB / 80 GB | Launch formula; 1 CU for 730 h + 25 GB storage ≈ $86.13/month | The architectures are not equivalent; test the real workload | | HA / SLA position | Production +70% HA = $67.98/month | Scale — $0.222/CU-hour + $0.35/GB-month; 99.95% compute-endpoint SLA threshold | Different availability models; compare RTO/RPO, not labels | The Neon arithmetic uses 730 hours only to show how continuous runtime changes usage-based cost. A database that sleeps for long periods can cost much less on Neon because suspended compute stops consuming CU-hours. A fair production estimate should include active compute time, database size, restore-history retention, branches, read replicas, public or private transfer, and availability requirements. Raff's paid plan price already includes the listed compute and storage allocation; extra storage, HA, and replicas are explicit modifiers. :::cta Deploy a Database Now Deploy managed PostgreSQL with published plans, backups, pooling, private connectivity, and optional high availability. ::: ## Bandwidth and transfer policy Neon changed its paid-plan public transfer allowance on June 1, 2026. Launch and Scale now include **500 GB of public transfer per month**, up from 100 GB. Transfer above the included amount remains $0.10/GB. The Free plan includes 5 GB of public transfer. Scale private-network transfer is priced separately at $0.01/GB in both directions. That makes Neon's external-data-transfer model straightforward to calculate: | Public transfer in a paid month | Neon transfer charge above allowance | |---:|---:| | 100 GB | $0 | | 500 GB | $0 | | 1 TB | About $52.40 | | 5 TB | About $471.60 | The examples use 1 TB = 1,024 GB and apply $0.10/GB only above the 500 GB included allowance. Raff private networking is free and private traffic inside Raff's VPC is unmetered. For managed-database traffic that leaves the Raff network over a public path, teams should verify the current product billing for that route instead of assuming the VM-specific 3 Gbps unmetered policy applies to databases. The architectural preference is the same on both platforms: keep application and database traffic private and geographically close where practical. Neon offers broader AWS/Azure placement; Raff is simpler when the application and database both fit `us-east`. ## Feature comparison: Neon vs Raff | Feature | Raff Managed PostgreSQL | Neon | |---|---|---| | Database model | Provisioned managed PostgreSQL | Serverless PostgreSQL with separated compute and storage | | Supported PostgreSQL majors | 14–16 | 14–18 | | Free tier | $0, 1 vCPU / 1 GB / 2 GB | $0, 100 CU-hours/project and 0.5 GB/project | | Paid entry | $7.99/month | Launch at $0.106/CU-hour + $0.35/GB-month | | Scale to zero | No | Yes; 5 minutes by default on Free and Launch | | Autoscaling | Plan resize | Automatic compute scaling within configured bounds | | Database branching | Conventional separate environments | Copy-on-write branches | | Connection pooling | Built in | Pooled and direct endpoints | | High availability | Optional +70% | SLA-backed compute endpoints on Scale/Business; different architecture | | Restore model | Managed backups and PITR on supported production workflows | 6 hours, 7 days, or 30 days by plan | | Private networking | Raff private connectivity | Private networking on Scale | | Read replicas | $29.99/month PostgreSQL read replica | Read replicas supported | | Public region model | `us-east` | Multiple AWS and Azure regions | | Support model | Direct Raff support | Community, billing, and plan-based support | Neon wins on branching, scale-to-zero, newer PostgreSQL major versions, and geographic choice. Raff wins on published provisioned tiers, a simple HA price formula, and fewer compute/storage usage meters for always-on production databases. ## Features and reliability: Raff vs Neon ### Engine and version coverage Raff Managed PostgreSQL currently supports PostgreSQL 14, 15, and 16. Neon supports PostgreSQL 14 through 18 and published current minor versions 14.21, 15.16, 16.12, 17.8, and 18.2 in February 2026. Neon therefore has the version-coverage advantage for applications that already require PostgreSQL 17 or 18. A Neon database on PostgreSQL 17 or 18 must resolve version compatibility before migration to Raff rather than assuming an in-place downgrade is possible. ### High availability topology Raff offers an optional PostgreSQL high-availability configuration priced at **+70% of the base plan**, using a synchronous standby and automatic failover model. The Production tier therefore moves from $39.99 to $67.98/month with HA. Neon does not expose a directly equivalent "+70% standby" toggle in its public pricing. Instead, the Scale/Business SLA applies to covered compute endpoints and uses a **99.95% monthly uptime threshold** for service-credit eligibility. These models should be compared through recovery time, recovery point, failover behavior, and application requirements rather than by feature name alone. ### Backup model Raff includes managed backups and supports point-in-time recovery for supported production workflows. The team still owns recovery-point selection and application validation after a restore. Neon provides time-travel and restore history by plan: up to 6 hours on Free, 7 days on Launch, and 30 days on Scale. Paid restore-history data is billed at $0.20/GB-month based on the volume of data changes during the selected window. ### Connection and networking Raff provides built-in pooling, TLS, allowlist controls, and private connectivity for Raff-hosted workloads. Private VPC traffic is unmetered. Neon provides pooled and direct connection endpoints, supports PgBouncer-based pooling, and offers private networking and IP allow rules on Scale. Paid plans include 500 GB/month of public transfer; Scale private transfer is metered separately. ### Upgrade and maintenance behavior Raff handles host-level and database-service maintenance for supported managed PostgreSQL versions, while the application team remains responsible for schema migrations, query compatibility, extensions, and release validation. Neon validates PostgreSQL minor releases and applies a new minor version the next time a compute restarts. Neon also uses scheduled update notices for PostgreSQL updates, security patches, and service changes. Teams should test extensions and application behavior before major-version changes on either platform. ### Reliability track record Raff publishes a 99.9% uptime SLA and supports 3,000+ customers and 15,000+ production VMs. Its Trustpilot profile was 4.5/5 on August 16, 2026. Neon's current SLA applies to Business/Scale compute endpoints and uses a 99.95% monthly uptime threshold; it explicitly does not cover every Neon API or platform component. Neon is a Databricks company, and its current site reports millions of Postgres databases started daily. Trustpilot shows an unclaimed `neon.com` profile at 3.2/5, which is too small a sample to treat as a broad product-satisfaction measure. ## When you should choose Neon over Raff - **Database branching** — Neon creates copy-on-write branches for pull requests, previews, CI jobs, and developer sandboxes. - **Intermittent databases** — Free and Launch computes can suspend after 5 idle minutes, reducing billed CU-hours when the database is inactive. - **Newer PostgreSQL majors** — Neon supports PostgreSQL 14–18, while Raff currently supports 14–16. - **Broader placement** — Neon publishes regional status endpoints for at least 11 AWS and Azure regions; Raff exposes 1 public region, `us-east`. - **Scale-plan SLA** — Neon Scale/Business compute endpoints use a 99.95% monthly uptime threshold for service credits. - **Elastic resource use** — Launch and Scale meter compute by CU-hour instead of requiring a continuously provisioned fixed tier. ## When you should choose Raff over Neon - **Fixed paid entry** — Raff's first paid PostgreSQL plan is $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. - **Explicit HA pricing** — PostgreSQL HA adds 70% to the selected Raff plan; the $39.99 Production tier becomes $67.98/month. - **Provisioned capacity** — Raff keeps the selected plan available rather than relying on a scale-to-zero wake-up path. - **Simple database budgeting** — published vCPU, RAM, and storage tiers reduce the number of compute and storage usage meters to forecast. - **Raff-hosted application paths** — private VPC traffic is unmetered when the application and database communicate inside Raff. - **Verified platform signals** — Raff supports 3,000+ customers and 15,000+ production VMs and was 4.5/5 on August 16, 2026. ## Migrating from Neon to Raff 1. **Inventory the Neon project.** Record PostgreSQL major version, extensions, branch hierarchy, roles, databases, pooled/direct endpoints, read replicas, restore window, IP rules, and private-network dependencies. 2. **Confirm Raff compatibility.** Select the Raff PostgreSQL tier, confirm every required extension, and resolve any PostgreSQL 17/18 source before migration because Raff currently supports 14–16. 3. **Transfer the database.** Use `pg_dump`/`pg_restore` for smaller databases or logical replication for an active production database where the source configuration permits it. 4. **Recreate access and networking.** Rotate credentials, replace Neon endpoint URLs, rebuild allowlists/private connections, and update application secrets, monitoring, and scheduled jobs. 5. **Verify before cutover.** Compare row counts, sequences, indexes, extensions, query plans, pooled connections, application writes, backups, restore expectations, and latency from the target application path. 6. **Cut over with rollback retained.** Bring replication lag to zero where used, coordinate final writes, switch the application connection string, verify production traffic, and keep Neon available until the rollback window closes. Operational gotchas: - Neon branches do not map one-for-one to Raff environments; choose which branch is the production source of truth before copying data. - A PostgreSQL 17 or 18 Neon source cannot be treated as a routine downgrade to Raff PostgreSQL 14–16; resolve version compatibility first. - Neon autoscaling and scale-to-zero assumptions must be replaced with a Raff plan sized for normal and peak demand. - Extension names can match while supported versions or configuration differ; test each required extension before cutover. For a stateful production database, plan a short write-coordination window even when logical replication is used. Short-lived preview branches are usually better recreated as development/test environments than migrated individually. ## About Neon [Neon](https://neon.com/) is operated by Neon, LLC, a Databricks affiliate headquartered in San Francisco and founded in 2021. Neon provides serverless PostgreSQL with separated compute and storage, branching, autoscaling, scale-to-zero, read replicas, and developer automation. Neon joined Databricks in May 2025 while continuing to operate the Neon PostgreSQL service. ## Conclusion: Neon or Raff? The comparison resolves across four decision axes: - **Pricing model** — Raff publishes a $7.99/month paid entry tier; Neon Launch meters compute at $0.106/CU-hour plus $0.35/GB-month. - **Developer workflow** — Neon leads on copy-on-write branches, autoscaling, and 5-minute scale-to-zero; Raff uses conventional provisioned database environments. - **Availability and placement** — Raff offers a +70% HA option in `us-east`; Neon offers a 99.95% Scale/Business compute-endpoint SLA threshold across multiple AWS/Azure regions. - **Operational fit** — Raff favors explicit capacity and predictable modifiers; Neon favors elastic usage and programmable database environments. Choose Neon when branching, scale-to-zero, PostgreSQL 17/18, or multi-region developer workflows are required. Choose Raff when an always-on managed PostgreSQL service needs published capacity, a fixed HA formula, private Raff connectivity, and direct support. Raff supports 3,000+ customers and 15,000+ production VMs and was verified at 4.5/5 on August 16, 2026. --- ### Render Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/render-alternative Description: Considering Render? Raff Apps starts at $3/mo with $0 egress and a default spend cap; Render adds five regions and a free tier. Raff Apps is a Render alternative for teams that prioritize lower published production tiers, $0 public egress, Docker Compose import, and a spend cap enabled by default. Render is stronger for five-region deployment, a $0 evaluation tier, Blueprints, Pro autoscaling, full-stack preview environments, and its broader managed PaaS workflow. Render can be cheaper for a prototype that stays on its free tier, while Raff becomes easier to forecast for always-on services and bandwidth-heavy applications. Choose Render when region choice and its mature PaaS workflow are decisive; choose Raff when predictable application cost and portability matter more. Raff Apps, the managed application platform from Raff Technologies, and Render both remove routine VM administration from web services, workers, scheduled jobs, and containerized applications. Raff starts at $3/month for 0.25 vCPU and 512 MB and charges $0 for public app egress. Render offers a free 0.1 CPU / 512 MB web-service tier, a $7 Starter service, and a $25 Standard service, while current workspace plans are Hobby $0, Pro $25 flat, Scale $499 flat, and Enterprise custom. The right choice depends on region, traffic, deployment workflow, and how much platform-specific behavior the application uses. ## Render vs Raff: which is right for you? Render is the safer default when an application needs geographic choice, established Blueprint workflows, or Pro-level collaboration and scaling features. Raff is the clearer alternative when one `us-east` region fits and the team values published monthly ceilings, $0 public egress, and a direct path between Apps, managed databases, object storage, VMs, and Kubernetes. | Decision factor | Choose Raff Apps | Choose Render | |---|---|---| | Entry path | You want a paid service from $3/month with explicit resources | You want a $0 web-service evaluation tier | | Always-on compute | You want 0.5 vCPU / 1 GB at $6.99 or 1 vCPU / 2 GB at $16.99 | You want Starter at $7 or Standard at $25 | | Public transfer | You want app egress priced at $0 | Your included workspace bandwidth covers usage or $0.15/GB overage is acceptable | | Deployment portability | Dockerfile, buildpacks, images, and full Docker Compose import matter | Git workflows, Docker, Blueprints, and Terraform fit the team | | Managed data | You want first-party PostgreSQL, MySQL, Valkey, ClickHouse, or Kafka alongside the app | You want Render Postgres and Render Key Value or will self-manage another datastore | | Geography | One public `us-east` region fits | You need Oregon, Ohio, Virginia, Frankfurt, or Singapore | | Team workflow | No workspace fee and a default spend cap matter | Pro autoscaling, audit logs, environment isolation, and full-stack previews matter | Our product decision at Raff was to put cost boundaries in place before an application scales: per-second compute has a published monthly ceiling, public egress is $0, and the spend cap starts enabled. That is useful for small teams because cost control does not depend on noticing a traffic spike after the invoice is already growing. For the broader architecture decision, read [Cloud VM vs App Platform: What Startups Should Know](/learn/guides/cloud-vm-vs-app-platform-startups). ## Render overview [Render](https://render.com/) is a managed application platform for deploying code as web services, static sites, private services, background workers, cron jobs, and Workflows, with managed Postgres and Key Value datastores alongside application services. Render supports Git-based deploys, Docker images, native runtimes, custom domains with managed TLS, health checks, zero-downtime deploys for eligible stateless services, persistent disks, Blueprints, Terraform, service previews, logs, metrics, and horizontal scaling. Manual scaling is available across workspaces, while autoscaling requires Pro or higher and supports up to 100 instances. Current web-service compute shapes include Free at 0.1 CPU / 512 MB, Starter at 0.5 CPU / 512 MB, Standard at 1 CPU / 2 GB, and Pro at 2 CPU / 4 GB, with larger service shapes available. Render's current public material verifies Starter at $7/month and Standard at $25/month for always-on services. Render introduced its current workspace plans on April 23, 2026. Hobby is $0, Pro is $25/month flat with unlimited team members, Scale is $499/month flat, and Enterprise is custom. Pro adds features such as autoscaling, audit logs, environment isolation, compliance-report access, and full-stack preview environments; Scale adds broader organization and compliance controls. Render's strongest advantages are geographic choice, a free evaluation path, mature declarative deployment workflows, managed previews, horizontal autoscaling, and an established application-platform operating model. Its company page reports $258 million raised. ## Raff overview [Raff Apps](/products/app-platform) deploys source code and containers without requiring teams to administer the underlying operating system. It supports GitHub push-to-deploy, Dockerfiles, existing container images, automatic buildpacks, full Docker Compose import, immutable revisions, one-click rollback, persistent volumes, and pull-request preview environments. Raff Apps currently provides five application service patterns: public web services, private services, background workers, timezone-aware cron jobs, and one-off jobs. Services can bind directly to Raff managed databases and object storage over private connectivity. Current Raff Apps compute tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Compute is billed per second against the published monthly ceiling. Raff Apps charges $0 for public egress and $0 per team seat, and the spend cap is enabled by default. Services can scale to zero, so an intermittently used service can finish below its monthly ceiling. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. Raff Technologies was verified at **4.5/5** on August 16, 2026, and G2 is 4.6/5. Raff is newer and geographically narrower than Render; its value is a compact application-and-infrastructure stack with explicit cost boundaries. ## Render pricing vs Raff pricing Render and Raff both separate application compute from attached data services, but the cost structure differs. Raff publishes per-instance monthly ceilings and charges $0 for app egress and team seats. Render combines workspace-plan fees, service compute, and usage-based items such as outbound bandwidth, persistent disks, extra build minutes, and extra custom domains. Current Render workspace pricing is: - **Hobby:** $0/month, one team member - **Pro:** $25/month flat, unlimited team members - **Scale:** $499/month flat, unlimited team members - **Enterprise:** custom Current Render service pricing verified in official Render material includes **Starter at $7/month for 0.5 CPU / 512 MB** and **Standard at $25/month for 1 CPU / 2 GB**. Free web services use 0.1 CPU / 512 MB, spin down after 15 minutes of inactivity, and are designed for evaluation rather than production. The closest verified buying positions are: | Buying position | Raff Apps | Render | Decision signal | |---|---:|---:|---| | Evaluation / hobby | Micro $3 — 0.25 vCPU / 512 MB | Free $0 — 0.1 CPU / 512 MB | Render wins when $0 evaluation is the priority | | Small always-on service | Starter $6.99 — 0.5 vCPU / 1 GB | Starter $7 — 0.5 CPU / 512 MB | Similar price; Raff publishes twice the RAM | | Standard service | Standard $16.99 — 1 vCPU / 2 GB | Standard $25 — 1 CPU / 2 GB | Raff is $8.01 lower for the published shape | | Pro workspace + Standard service | $16.99 service; $0 workspace fee | $25 Pro workspace + $25 Standard service = $50 | Features differ; Render Pro adds team and platform capabilities | | 5 TB public outbound on a Pro workspace | $0 app-egress line; compute separate | About $764.25 bandwidth overage + $25 workspace; compute separate | Transfer becomes a material Render line item | **Comparison class:** these are price-and-resource planning positions, not performance-equivalent benchmarks. CPU labels, host hardware, scheduling, build systems, networking, and storage paths differ, so the table does not prove equal throughput or latency. ### Additional Render billing lines Render bills persistent disks at $0.25/GB-month and Postgres storage at $0.30/GB-month. New workspace plans include 5 GB of outbound bandwidth on Hobby, 25 GB on Pro, and 1 TB on Scale, then charge $0.15/GB. Extra custom domains are $0.25/month each beyond the plan allowance, and additional standard build-pipeline usage is $5 per 1,000 minutes. These charges are not inherently disadvantages; Render exposes more workspace and platform controls than a simple compute-only comparison captures. The correct comparison is the full production stack, including database, storage, bandwidth, preview environments, and team plan. ### Automated backups and recovery Render persistent disks receive an automatic snapshot once every 24 hours, and snapshots remain available for at least seven days. Render explicitly warns against using disk-snapshot restore as the recovery method for a custom database such as MySQL or MongoDB; database-native backups should be maintained instead. Raff Apps persistent state should likewise be treated separately from disposable application compute. Managed databases provide database-specific backup workflows, and durable files can be placed in Raff Object Storage or persistent volumes according to the workload. Recovery should be tested independently of a successful application deploy. :::cta Deploy an App Now Deploy from GitHub, Docker, buildpacks, or Docker Compose with a spend cap enabled by default. ::: ## Bandwidth and transfer policy Raff Apps charges **$0 for public application egress**. Render measures outbound traffic sent from workspace services to destinations outside Render, applies a monthly allowance based on the workspace plan, and charges **$0.15/GB** above that allowance. Current included Render outbound bandwidth is **5 GB on Hobby, 25 GB on Pro, 1 TB on Scale, and custom on Enterprise**. Unused allowance does not roll over. For a production-oriented Render Pro workspace, using 1 TB = 1,024 GB and the 25 GB monthly allowance: | Monthly public outbound | Raff Apps egress | Render Pro bandwidth overage | |---:|---:|---:| | 1 TB | $0 | About $149.85 | | 5 TB | $0 | About $764.25 | | 10 TB | $0 | About $1,532.25 | | 50 TB | $0 | About $7,676.25 | These figures isolate the public-transfer line. Render's $25 Pro workspace fee and service compute are additional, while a Scale workspace includes 1 TB before overage but starts at $499/month. Private traffic inside a Render region follows different rules and should not be treated as public internet egress. For both platforms, keep internal service-to-database traffic private and move large durable files to object storage when that architecture fits. The bandwidth difference matters most for public APIs, downloads, media delivery, generated files, and other internet-heavy workloads. ## Feature comparison: Render vs Raff | Feature | Raff Apps | Render | |---|---|---| | Free web-service tier | No; Micro starts at $3 | Yes; 0.1 CPU / 512 MB with free-tier limits | | Paid Starter | $6.99 — 0.5 vCPU / 1 GB | $7 — 0.5 CPU / 512 MB | | Standard | $16.99 — 1 vCPU / 2 GB | $25 — 1 CPU / 2 GB | | Git deployment | GitHub | GitHub, GitLab, Bitbucket, public Git URLs | | Dockerfile / image deployment | Yes | Yes | | Full Docker Compose import | Yes | No native whole-stack Compose import documented; Blueprints are Render's declarative model | | Preview environments | Isolated pull-request stack previews | Full-stack preview environments require Pro+ | | Manual scaling | Yes | All workspaces, up to 100 instances | | Autoscaling | Platform capability | Pro+, up to 100 instances | | Managed PostgreSQL | Yes | Yes | | Managed MySQL | Yes | No first-party managed MySQL; custom MySQL can run on a persistent disk | | Redis-compatible managed service | Valkey | Render Key Value | | Managed object storage | Raff Object Storage | Use an external or self-managed object store | | Persistent disk / volume | Yes | Paid services; one service instance per disk | | Workflow orchestration | One-off jobs, cron, workers, Functions | Render Workflows beta for chained long-running tasks | | Public service regions | 1: `us-east` | 5: Oregon, Ohio, Virginia, Frankfurt, Singapore | | Workspace fee | $0 | Hobby $0, Pro $25, Scale $499 | | Seat fee | $0 | No per-seat fee on current Pro and Scale plans | | Public egress | $0 | Allowance by plan, then $0.15/GB | Render wins on region choice, Git-provider breadth, Blueprints/Terraform workflows, Pro autoscaling, Workflows, and mature workspace controls. Raff wins on lower verified Starter/Standard production pricing, $0 public egress, full Docker Compose import, first-party managed MySQL, and a default spend cap. ## Features and reliability: Raff vs Render This comparison includes **0 controlled Raff-vs-Render application benchmarks**, so it does not declare either platform faster. A credible test would require the same container, dependency versions, region assumptions, instance class, database path, request generator, concurrency, and repeated warm and cold runs. ### Deployment reliability Render performs zero-downtime deploys for eligible services without persistent disks. Health checks protect new releases: if a new version fails to become healthy, Render keeps the existing deployment serving traffic. Running instances that repeatedly fail health checks can be removed from routing and restarted automatically. Raff Apps uses immutable revisions, health-aware deployment workflows, one-click rollback, and a broader Raff platform covered by a 99.9% SLA. On either provider, application-level retries, external monitoring, database recovery, and tested rollback procedures still matter. ### Stateful-service trade-offs A Render persistent disk is attached to one service instance. A disk-backed service cannot scale horizontally to multiple instances, and attaching a disk disables the normal zero-downtime deployment path. Render's automatic daily disk snapshots provide a recovery option for files, but custom databases require database-native backup procedures. Raff persistent volumes also make an application stateful. For relational production data, managed databases are generally a cleaner boundary than placing the database inside the application service, because database backup and recovery can be managed independently from application revisions. ### Regional footprint Render offers **5 public service regions**: Oregon, Ohio, Virginia, Frankfurt, and Singapore. Existing Render services and databases cannot change region in place; a new resource must be created and configuration/data migrated. Raff Apps currently exposes **1 public region, `us-east`**. Render therefore has the clear advantage when geography, regional placement, or a European/Asian application location is mandatory. Raff is appropriate when the `us-east` location fits the user base and the cost model matters more than region choice. ### Operating trust Render's company page reports **$258 million raised**, and its documentation provides detailed operational guidance for health checks, maintenance, multi-instance availability, and backup testing. Raff reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. These signals are different rather than directly equivalent. Render has the longer specialized PaaS track record; Raff provides a smaller platform with public SLA and review signals that can be checked independently. ## When you should choose Render over Raff Choose Render when: - **You need more region choice.** Render offers five service regions; Raff Apps currently exposes one public `us-east` region. - **You need a $0 evaluation path.** Render's free web service is useful for prototypes and testing, although it spins down after 15 minutes of inactivity. - **Blueprint and Git-provider workflows matter.** Keeping a mature `render.yaml` definition and direct GitLab or Bitbucket integration can be lower-risk than translating the deployment. - **Pro autoscaling is a requirement.** Render can scale eligible services automatically by CPU and/or memory, with up to 100 instances. - **Full-stack preview environments matter.** Render can create disposable copies of Blueprint-defined services and datastores for pull requests on Pro and higher. - **You need Render Workflows.** Its beta workflow product chains long-running distributed tasks within the Render platform. - **You need Scale-level organization controls.** Render's Scale plan adds SSO, SCIM, advanced RBAC, HIPAA-enabled workspaces, and multi-workspace management. Render is also the cheaper option when a prototype genuinely fits the free web-service limits and does not need always-on production behavior. ## When you should choose Raff over Render Choose Raff Apps when: - **Lower verified always-on tiers matter.** Raff Starter is $6.99 for 0.5 vCPU / 1 GB versus Render Starter at $7 for 0.5 CPU / 512 MB, and Raff Standard is $16.99 versus Render Standard at $25 for 1 CPU / 2 GB. - **Public egress is substantial.** Raff app egress is $0, while Render Pro includes 25 GB then charges $0.15/GB. - **Docker Compose is already the source of truth.** Raff can import a full Compose stack instead of translating each service into a provider-specific definition. - **First-party managed MySQL is required.** Raff provides managed MySQL alongside PostgreSQL, Valkey, ClickHouse, and Kafka. - **Cost protection should be automatic.** Raff enables a spend cap by default and does not add a workspace or seat fee. - **Scale-to-zero is useful.** Raff Apps can reduce idle-service runtime below the monthly ceiling. - **One provider should cover both PaaS and infrastructure.** Raff connects Apps with managed databases, object storage, VMs, private networking, Kubernetes, and Functions. ## Migrating from Render to Raff 1. **Inventory the Render workspace.** Record every web service, private service, worker, cron job, Workflow, Postgres database, Key Value instance, persistent disk, environment group, custom domain, region, Blueprint, preview environment, and external allowlist. 2. **Map each service to Raff.** Move public web services to Raff web services, internal services to private services, background workers to workers, scheduled tasks to cron jobs, and suitable administrative commands to one-off jobs. **Gotcha:** Render Workflows do not map one-to-one to Raff Apps; preserve task dependencies, retries, and failure semantics explicitly. 3. **Choose the build path.** Connect the GitHub repository, deploy an existing container image, use a Dockerfile, let buildpacks detect the runtime, or import Docker Compose when several services already run together. **Gotcha:** Render Blueprints and Raff stack definitions are different configuration models. 4. **Move persistent state.** Export Postgres or Key Value data with engine-appropriate tools, move durable files from Render disks, and recreate storage or managed database targets on Raff. Do not use a disk snapshot as a substitute for a database-consistent export. 5. **Recreate configuration and test.** Add environment variables, secrets, private bindings, health checks, domains, scheduled-job timezones, storage mounts, webhook callbacks, and allowlists. Test on a temporary hostname and verify backup and restore procedures before cutover. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds** before the change, run the final state sync, update DNS and external callbacks, monitor production, and keep Render services available until the rollback window closes. Network identities, custom domains, OAuth callbacks, payment webhooks, SMTP allowlists, database allowlists, and preview-environment configuration can all change during migration. Treat the migration as a platform-behavior translation, not only a code copy. ## About Render [Render](https://render.com/) is a managed application platform headquartered in San Francisco. It provides web and private services, workers, cron jobs, static sites, Workflows, Postgres, Key Value, persistent disks, Blueprints, Terraform support, preview environments, and scaling features. Render's current public company page reports $258 million raised, and its current workspace pricing uses Hobby, Pro, Scale, and Enterprise plans. ## Conclusion: Render or Raff? The Render-versus-Raff decision resolves across four measured axes: entry and compute cost, public bandwidth, platform workflow, and regional reach. - **Entry and compute:** Render offers a $0 evaluation tier; Raff Starter is $6.99 versus Render Starter at $7, and Raff Standard is $16.99 versus Render Standard at $25. - **Bandwidth:** Raff Apps charges $0 for public egress; Render Pro includes 25 GB and then charges $0.15/GB. - **Workflow:** Render wins on Blueprints, broader Git-provider support, Pro autoscaling, full-stack previews, and Workflows; Raff wins on full Docker Compose import and default spend controls. - **Regions:** Render offers five public service regions; Raff Apps currently exposes one public region, `us-east`. Choose Render when the free evaluation path, five-region placement, or its PaaS-native workflow is a requirement. Choose Raff when the application fits `us-east` and lower published production tiers, $0 public egress, Docker Compose portability, and automatic cost boundaries are the stronger decision factors. Raff currently reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. For adjacent comparisons, review [Vercel alternatives](/learn/compare/vercel-alternative), [Netlify alternatives](/learn/compare/netlify-alternative), and [Railway comparison](/learn/compare/raff-vs-railway). --- ### Vercel Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/vercel-alternative Description: Considering Vercel? Raff Apps starts at $3/mo with $0 public egress; Vercel Pro is $20/mo with 1 TB transfer and 10M Edge Requests. Raff Apps wins on fixed service resources, full Docker Compose import, long-running workers, private services, and $0 public application egress. Vercel wins on its global CDN, 20 compute-capable regions, Next.js-first workflow, preview deployments, and $0 Hobby plan for qualifying personal use. Choose Vercel when framework-native global frontend delivery is the requirement; choose Raff when the application is a portable container stack with always-on processes and explicit cost ceilings. Raff Apps starts at $3/month, while Vercel Pro is $20/month and currently includes one deploying seat, $20 of usage credit, 1 TB of Fast Data Transfer, and 10 million Edge Requests. Vercel and Raff Apps solve different deployment problems even though both can ship web applications from source. Vercel combines a global delivery network with framework-aware builds and request-driven compute across 20 compute-capable regions. Raff Technologies positions Raff Apps around explicit service resources in one public `us-east` region, with a $3 entry tier, $0 public app egress, workers, cron jobs, private services, persistent volumes, and Docker Compose portability. The practical choice is therefore less about a single feature checklist and more about whether the production workload behaves like a globally delivered frontend or a connected set of application services. ## Vercel vs Raff: which is right for you? Use Vercel when the frontend platform itself is part of the application architecture. Use Raff when the application is better represented as services that should remain portable across source, containers, databases, storage, and private networking. | Decision factor | Choose Raff Apps | Choose Vercel | |---|---|---| | Primary workload | APIs, containers, workers, cron jobs, private services, and multi-service stacks | Next.js, framework frontends, static delivery, previews, and request-driven functions | | Entry path | Micro from $3/month with explicit resources | Hobby at $0 for qualifying personal/non-commercial use | | Commercial plan | Fixed service tier; no workspace or seat fee | Pro at $20/month with one deploying seat and usage allowances | | Public transfer | $0 application egress | Pro includes 1 TB Fast Data Transfer, then published overage pricing applies | | Deployment portability | Dockerfile, image, buildpacks, and full Docker Compose import | Git/framework builds, CLI, hooks, API, and Vercel platform conventions | | Global delivery | Add an external CDN when required | 126 PoPs across 94 cities and 51 countries, with 20 compute-capable regions | | Data architecture | First-party managed databases, object storage, persistent volumes | Vercel Blob, Edge Config, and Marketplace data providers | At Raff, we made a deliberate product decision to make cost boundaries visible before a service receives production traffic: each app tier has a published monthly ceiling, public app egress is $0, and the spend cap starts enabled. That model is useful for small teams running several persistent processes because cost protection does not depend on reverse-engineering request, seat, transfer, and function meters after launch. For the broader platform decision, review [Cloud VM vs App Platform: What Startups Should Know](/learn/guides/cloud-vm-vs-app-platform-startups). ## Vercel overview Vercel is a managed developer and AI cloud platform with deep Next.js roots. It connects to Git providers, builds framework projects, creates preview and production deployments, serves content through a global CDN, and runs server-side code through Vercel Functions and Fluid Compute. Its current public plans are: - **Hobby — $0/month:** intended for personal and non-commercial use. - **Pro — $20/month:** includes one deploying seat, $20 monthly usage credit, 1 TB Fast Data Transfer, and 10 million Edge Requests before additional metered usage. - **Enterprise — custom:** adds enterprise controls, multi-region compute and failover options, and a 99.99% SLA. Vercel's global network currently documents **126 points of presence across 94 cities and 51 countries**, with **20 compute-capable regions**. That footprint is a genuine advantage for globally distributed frontends because caching, routing, preview deployments, and framework-specific delivery are part of the platform rather than a separately assembled CDN layer. Vercel Functions use Fluid Compute rather than fixed application-server tiers. Current published usage rates start at **$0.128 per active CPU-hour**, **$0.0106 per provisioned GB-hour**, and **$0.60 per million invocations** after the applicable included usage. Functions automatically scale down when no requests are active. Vercel also provides Blob storage, Edge Config, image optimization, Web Analytics, Speed Insights, Observability, WAF and DDoS controls, Cron Jobs, and Marketplace integrations for third-party databases and data services. In September 2025, Vercel announced a $300 million Series F at a $9.3 billion valuation, which is a meaningful public scale and funding signal. ## Raff overview [Raff Apps](/products/app-platform) deploys source code and containers without requiring a team to administer the operating system. It supports GitHub push-to-deploy, Dockerfiles, existing container images, automatic buildpacks, full Docker Compose imports, immutable revisions, one-click rollback, persistent volumes, pull-request previews, and scale-to-zero behavior. Raff Apps supports public web services, private services, background workers, timezone-aware cron jobs, and one-off jobs. Applications can connect to managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, as well as object storage, VMs, private networking, Kubernetes, and Functions. Current Raff Apps tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Compute is billed per second against the published monthly ceiling. Public application egress and team seats are priced at $0, and the spend cap is enabled by default. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. Raff Technologies was verified at **4.5/5** on August 16, 2026, and G2 is 4.6/5. Raff is geographically narrower than Vercel; its strength is the explicit service model and the ability to keep app, database, storage, VM, and Kubernetes workloads under one cloud account. ## Vercel pricing vs Raff pricing Vercel and Raff expose different units of cost. Raff prices long-running application services by fixed vCPU/RAM tiers with per-second proration. Vercel Pro combines a $20 platform fee with included transfer/request allocations, a $20 usage credit, paid collaborator seats, and metered infrastructure products such as Functions, Blob storage, image optimization, and additional transfer. The closest useful buying positions are: | Buying position | Raff Apps | Vercel | Decision signal | |---|---:|---:|---| | Personal / hobby | Micro $3 — 0.25 vCPU / 512 MB | Hobby $0 for qualifying personal/non-commercial use | Vercel wins when a qualifying $0 frontend plan is enough | | Small commercial app | Starter $6.99 — 0.5 vCPU / 1 GB | Pro $20 platform fee with one deploying seat and usage allowances | Raff publishes fixed service resources; Vercel bundles frontend-platform allowances | | Standard backend | Standard $16.99 — 1 vCPU / 2 GB | No direct fixed-instance equivalent; Functions use CPU, memory, invocation, and transfer meters | Compare workload behavior rather than CPU labels | | Five deploying developers | $0 additional seat fee | $100/month in Pro platform/paid-seat fees before additional infrastructure usage | Vercel collaboration cost becomes material as deploying members increase | | 5 TB Fast Data Transfer | $0 app-egress line; compute separate | About $614.40 overage at the published starting $0.15/GB rate after the included 1 TB, plus Pro and other usage | Transfer-heavy apps can have very different bills | **Comparison class:** these are buying positions, not performance-equivalent instances. Vercel Functions and Raff application services have different execution, scaling, caching, host, and networking models, so matching a price or CPU label does not establish equal throughput or latency. ### Bandwidth cost math Vercel Pro currently includes **1 TB of Fast Data Transfer** before overage. Using 1 TB = 1,024 GB and Vercel's published **starting rate of $0.15/GB** after that allowance, the isolated transfer line is: | Monthly Fast Data Transfer | Raff Apps public egress | Vercel Pro transfer overage | |---:|---:|---:| | 1 TB | $0 | $0 | | 5 TB | $0 | About $614.40 | | 10 TB | $0 | About $1,382.40 | | 50 TB | $0 | About $7,526.40 | These examples isolate Fast Data Transfer. Vercel's $20 Pro fee, Functions, Blob, image optimization, build, and other usage are separate, while regional pricing can differ from the published starting rate. Vercel also meters other network paths separately, including Fast Origin Transfer and Blob Data Transfer. ### Automated backups Vercel's security documentation says Vercel platform customer data is backed up every **2 hours** and each backup is retained for **30 days**. That platform-resiliency statement should not be interpreted as a backup promise for every application datastore. Vercel Blob currently has **no native backup system**, and database backup, point-in-time recovery, and retention depend on the Marketplace database provider selected by the customer. Raff Apps likewise separates disposable application compute from durable application data. Ephemeral app disk is not a backup. Production state should live in managed databases, object storage, or persistent volumes, and backup/restore behavior should be verified for the selected Raff data service before launch. ### Other billable resources Vercel Pro includes one deploying seat; additional paid Owner or Member seats are **$20/month each**, while Viewer seats are free. Blob storage currently includes 1 GB then starts at $0.023/GB-month, with separate operation and data-transfer meters. Vercel's default on-demand budget for new teams is $200 per billing cycle and can be customized, with alerts and an optional hard pause at 100%. Raff does not add an Apps workspace or seat fee. Its main variable costs come from the selected app tiers and any separately attached managed database, storage, or infrastructure products. :::cta Deploy an App Now Deploy containers, workers, cron jobs, and Docker Compose stacks with explicit monthly ceilings. ::: ## Bandwidth and transfer policy Raff Apps charges **$0 for public application egress**. Vercel Pro includes **1 TB Fast Data Transfer** and **10 million Edge Requests** before additional usage is billed, so a typical frontend does not begin paying per GB from the first byte. Vercel's network model is more granular than a single bandwidth number. Fast Data Transfer covers delivery through the global network, Fast Origin Transfer measures traffic from origin compute into Vercel's network, and Blob has a separate data-transfer meter. Cacheable frontend applications can therefore benefit substantially from Vercel's CDN while keeping origin work low. For bandwidth-heavy APIs, generated downloads, package delivery, or dynamic content that regularly exceeds 1 TB on Pro, Raff's $0 app-egress line is simpler to forecast. For globally distributed static and framework-rendered frontends, Vercel's 126-PoP delivery network can provide operational value that a transfer-only comparison does not capture. The correct budgeting method is to separate four network behaviors: CDN delivery, origin transfer, storage transfer, and application-to-internet traffic. Raff collapses public Apps egress to $0; Vercel optimizes those paths globally but prices them as distinct infrastructure meters and allowances. ## Feature comparison: Vercel vs Raff | Feature | Raff Apps | Vercel | |---|---|---| | Primary deployment model | Long-running services and containers | Framework deployments and request-driven Functions | | Git deployment | GitHub | GitHub, GitLab, Bitbucket, Azure DevOps, CLI, hooks, API | | Dockerfile / existing image | Yes | Not the primary general-service model | | Full Docker Compose import | Yes | No native whole-stack Compose import | | Preview environments | Pull-request previews | Automatic deployment previews with framework-aware workflow | | Always-on worker | Yes | Not the primary Functions execution model | | Private service | Yes | Private backend design depends on platform/networking architecture | | Cron jobs | Timezone-aware app jobs | Cron Jobs invoke Vercel Functions | | Global CDN | External CDN can be added | Built in across 126 PoPs | | Compute regions | 1 public region: `us-east` | 20 compute-capable regions | | Persistent mounted volume | Yes | No general mounted persistent filesystem for Functions | | Managed PostgreSQL | First-party Raff managed database | Marketplace provider | | Managed MySQL | First-party Raff managed database | Marketplace/external provider | | Object storage | Raff Object Storage | Vercel Blob | | Team seat fee | $0 | One deploying seat included on Pro; additional paid members $20/month | | Public app transfer | $0 | 1 TB Fast Data Transfer on Pro, then published overage pricing | | Rollback | Immutable revisions and one-click rollback | Instant rollback to eligible prior production deployments | Vercel wins on global frontend delivery, framework integration, Git-provider breadth, preview collaboration, distributed function regions, and frontend observability. Raff wins on portable containers, Docker Compose, long-running workers, private services, fixed app resources, first-party managed MySQL, persistent volumes, and $0 public app egress. ## Features and reliability: Raff vs Vercel This comparison includes **0 controlled Raff-versus-Vercel application benchmarks**, so it does not declare either platform faster. Vercel's request-driven Functions and global CDN are not performance-equivalent to a continuously available Raff container, and a credible test must hold application code, cache policy, data location, request mix, and concurrency constant. ### Global delivery Vercel's **126 PoPs across 94 cities and 51 countries** and **20 compute-capable regions** give it the stronger default architecture for globally distributed frontends. Every request passes through Vercel's global CDN, and teams can place Functions in selected regions according to application needs. Raff Apps currently exposes one public `us-east` region. Teams can place a separate CDN in front of an application where necessary, but that is an additional architectural component. For a cache-heavy international frontend, Vercel therefore has a genuine out-of-the-box advantage. ### Compute model Raff exposes explicit vCPU and RAM tiers for processes that may remain available continuously. This maps naturally to APIs, WebSocket-oriented services, workers, private services, and multi-container applications. Vercel Functions scale around requests and can scale down to zero. Fluid Compute bills active CPU, provisioned memory, and invocations, which can be efficient for bursty or I/O-heavy workloads. It is less directly comparable to an always-on process because cost and concurrency depend on request behavior rather than a fixed instance shape. ### Rollback and data recovery Both platforms provide deployment rollback. Vercel Pro and Enterprise can roll back to eligible prior production deployments retained by the platform, while Raff uses immutable revisions and one-click rollback for application releases. Deployment rollback is not the same as data recovery. Vercel Blob has no native backup feature, and Marketplace database recovery depends on the chosen provider. Raff also separates application revision rollback from database, object-storage, and persistent-volume recovery. Production teams should test both code rollback and state restoration independently. ### Operating trust Vercel announced a **$300 million Series F at a $9.3 billion valuation** in September 2025 and publishes a **99.99% Enterprise SLA**. Raff reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. Those signals measure different things. Vercel has the larger global frontend-platform footprint and funding scale; Raff provides a smaller cloud with public customer, VM, SLA, and review signals that can be checked independently. ## When you should choose Vercel over Raff Choose Vercel when: - **Next.js and framework-native delivery are central.** Vercel integrates builds, routing, caching, previews, image optimization, and deployment behavior around frontend frameworks. - **Global delivery is mandatory.** Vercel documents 126 PoPs and 20 compute-capable regions; Raff Apps currently exposes one `us-east` region. - **A qualifying $0 personal plan matters.** Vercel Hobby costs $0 for personal/non-commercial use, while Raff Apps starts at $3/month. - **Preview collaboration is part of development.** Vercel generates deployment URLs around branches and commits and integrates them deeply into frontend workflows. - **Request-driven compute fits the workload.** Fluid Compute scales down to zero and bills CPU, memory, and invocations rather than a continuously running service tier. - **Enterprise multi-region failover is required.** Vercel Enterprise adds multi-region compute/failover options and a 99.99% SLA. Vercel is also the safer choice when replacing its framework-specific caching, Incremental Static Regeneration, image delivery, or preview behavior would create more engineering work than the migration saves. ## When you should choose Raff over Vercel Choose Raff Apps when: - **The application is container-first.** Raff supports Dockerfiles, existing images, buildpacks, and full Docker Compose imports. - **Long-running processes are required.** Web services, workers, private services, cron jobs, and one-off jobs map directly to persistent service types. - **Compute cost should be explicit.** Raff Standard is $16.99 for 1 vCPU / 2 GB and Raff Pro is $27.99 for 2 vCPU / 4 GB, each with a published monthly ceiling. - **Public egress is substantial.** Raff app egress is $0, while Vercel Pro includes 1 TB Fast Data Transfer before overage pricing applies. - **First-party managed MySQL is required.** Raff provides managed MySQL alongside PostgreSQL, Valkey, ClickHouse, and Kafka. - **Seat growth should not change the bill.** Raff Apps charges $0 per team seat; Vercel charges $20/month for each additional paid Pro Owner or Member. - **Docker Compose portability matters.** A multi-service development stack can be imported without translating every component into frontend-platform-specific products. ## Migrating from Vercel to Raff 1. **Inventory the Vercel project.** Record frameworks, build commands, environment variables, domains, rewrites, redirects, Functions, Cron Jobs, Blob stores, Edge Config, Marketplace databases, preview behavior, image optimization, and cache rules. 2. **Choose the Raff package.** Use buildpacks for a conventional source deployment, a Dockerfile for reproducible packaging, an existing container image for a prebuilt artifact, or Docker Compose for a multi-service stack. **Gotcha:** Vercel project configuration does not map one-to-one to a container or Compose definition. 3. **Map execution units.** Convert HTTP Functions into application routes, asynchronous consumers into workers, schedules into Raff cron jobs, and internal APIs into private services where appropriate. **Gotcha:** Function code that assumes ephemeral request execution may need explicit connection pooling, graceful shutdown, and concurrency handling. 4. **Move persistent state.** Copy Vercel Blob objects to Raff Object Storage, migrate Marketplace databases with provider-native export/import tools, and move Edge Config values into application configuration or a suitable datastore. Verify backup and restore before the final sync. 5. **Rebuild delivery behavior.** Recreate redirects, headers, image delivery, cache rules, and an external CDN where global edge delivery remains necessary. Test a temporary hostname from the regions that matter to users. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, perform the final state sync, update DNS, OAuth callbacks, webhooks, and allowlists, monitor production, and keep the Vercel deployment available until the rollback window closes. Stateless application code is usually the easiest part to move. Stateful data, framework-specific caching, preview environments, edge behavior, and public URLs create most migration risk, so each should have a tested rollback path before DNS changes. ## About Vercel [Vercel](https://vercel.com/) is operated by Vercel Inc., a developer and AI cloud company founded in 2015 and headquartered in San Francisco. It develops Next.js and provides Git-based deployments, preview environments, a global CDN, Vercel Functions, Fluid Compute, Blob storage, Edge Config, observability, image optimization, and Marketplace integrations for application data services. ## Conclusion: Vercel or Raff? The Vercel-versus-Raff decision resolves across four measured axes: cost model, application process model, global delivery, and data portability. - **Cost model:** Vercel Hobby can be $0 and Pro is $20 with allowances; Raff Apps starts at $3 and publishes fixed monthly service ceilings with $0 team seats. - **Application model:** Vercel centers framework deployments and request-driven Functions; Raff centers containers, workers, private services, cron jobs, and Docker Compose stacks. - **Global delivery:** Vercel provides 126 PoPs and 20 compute-capable regions; Raff Apps currently exposes one public `us-east` region and can use an external CDN when required. - **Data portability:** Vercel combines Blob, Edge Config, and Marketplace data providers; Raff connects Apps to first-party managed databases, object storage, persistent volumes, VMs, and Kubernetes. Choose Vercel when globally distributed frontend delivery and framework-native platform behavior are requirements. Choose Raff when the application is a portable service stack and explicit compute, seat, transfer, and data-service boundaries are more important than a built-in global frontend network. Raff currently reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. For adjacent comparisons, review [Render Alternative 2026](/learn/compare/render-alternative), [Netlify Alternative 2026](/learn/compare/netlify-alternative), and [Railway comparison](/learn/compare/raff-vs-railway). --- ### Supabase Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/supabase-alternative Description: Considering Supabase? Raff offers $0 PostgreSQL with 1 vCPU, 1 GB RAM and 2 GB storage; paid plans add fixed resources and optional HA. Raff wins on published PostgreSQL resources, explicit high-availability pricing, private Raff connectivity, and a database-first operating model. Supabase wins on integrated Auth, Storage, Realtime, generated APIs, Edge Functions, branching, and a much broader region footprint. Choose Supabase if those backend-as-a-service features replace application engineering; choose Raff if PostgreSQL operations, portability, and predictable capacity are the primary decision. Both offer permanent $0 tiers: Raff includes 1 vCPU, 1 GB RAM, and 2 GB database storage, while Supabase Free includes a 500 MB database and up to 2 active projects. After free, Raff Managed PostgreSQL starts at $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. Supabase Pro starts at $25/month and includes $10 in compute credits, enough for one Micro instance with 1 GB RAM and a 2-core ARM CPU. Supabase can also bill for database disk, egress, file storage, monthly active users, Realtime, Edge Functions, branches, and point-in-time recovery. Raff uses provisioned database tiers plus explicit storage, HA, and replica modifiers. ## Supabase vs Raff: which is right for you? Supabase and Raff overlap at managed PostgreSQL, but they solve different scopes. Supabase is a PostgreSQL-centered backend platform. Raff Managed PostgreSQL is a focused database service that sits alongside Raff application, compute, storage, and networking products. At Raff, our decision rule comes before the price table: **are you replacing a database service, or are you replacing an application backend?** If Auth, Storage, Realtime, generated APIs, and functions are requirements, Supabase is the broader product. If those concerns already have an owner, compare PostgreSQL operations directly. | Decision factor | Choose Raff | Choose Supabase | |---|---|---| | Primary need | Managed PostgreSQL with explicit capacity | Integrated backend platform around PostgreSQL | | Free database | 1 vCPU / 1 GB / 2 GB | 500 MB database, shared CPU, 500 MB RAM | | Paid entry | $7.99/month for 1 vCPU / 1 GB / 25 GB | Pro from $25/month with $10 compute credits | | Authentication | Use application or selected provider | Integrated Supabase Auth | | Realtime | Application-defined | Integrated Realtime service | | File storage | Separate Raff Object Storage product | Integrated Supabase Storage | | Functions | Raff Apps / Raff Functions as separate products | Integrated Edge Functions | | PostgreSQL version | 14–16 | Hosted platform currently defaults to PostgreSQL 17 | | Region choice | `us-east` | 17 specific AWS regions plus general-region selection | | HA model | Optional synchronous standby at +70% | Platform/read-replica model; no equivalent fixed +70% standby toggle | Supabase is the stronger choice when its integrated services remove meaningful application work. Raff is the stronger choice when the team wants PostgreSQL to remain a portable, separately operated infrastructure component. For the broader ownership model, read [Managed vs Self-Hosted Databases](/learn/guides/managed-vs-self-hosted-databases) and [PostgreSQL for SaaS Apps](/learn/guides/postgresql-for-saas-apps). ## Supabase overview [Supabase](https://supabase.com/) combines a dedicated PostgreSQL database with application-facing backend services. Every project includes database APIs, Auth, Storage, Realtime, Edge Functions, client tooling, and observability capabilities, with limits and feature access determined by plan. Its current public pricing starts with: - **Free — $0/month:** up to 2 active projects, 500 MB database size per project, shared CPU, 500 MB RAM, 50,000 monthly active users, 1 GB file storage, 5 GB egress, 5 GB cached egress, and community support. Free projects can pause after one week of inactivity. - **Pro — from $25/month:** 100,000 MAU, 8 GB database disk per project, 250 GB uncached egress, 250 GB cached egress, 100 GB file storage, email support, and daily backups retained for 7 days. - **Team — from $599/month:** adds collaboration, access-control, compliance, support, and 14-day backup-retention features. - **Enterprise — custom:** adds negotiated infrastructure, support, security, and uptime commitments. Paid plans include $10/month in compute credits. Supabase's current pricing page lists Micro compute at $10/month with 1 GB RAM, a 2-core ARM CPU, 60 recommended direct connections, and 200 pooler connections, so the credit covers one Micro project for a full billing month. Supabase's product advantage is integration. Auth can connect application identity to database Row Level Security; Storage and Realtime share the platform; generated APIs reduce boilerplate; Edge Functions provide a server-side runtime; and Pro branching can create isolated preview environments. A preview branch has no separate flat fee but incurs its own usage, with default Micro branch compute starting at $0.01344/hour. Supabase's hosted platform currently defaults to PostgreSQL 17. That is a version-coverage advantage over Raff for applications that specifically require PostgreSQL 17 today. ## Raff overview [Raff Managed PostgreSQL](/products/managed-databases/postgresql) provides managed PostgreSQL with published vCPU, RAM, and NVMe allocations, managed backups, point-in-time recovery for supported production workflows, monitoring, built-in connection pooling, private connectivity, storage expansion, and optional high availability. Raff's permanent PostgreSQL free tier includes 1 vCPU, 1 GB RAM, 2 GB storage, 60 direct connections, and 200 pooled connections. Current paid reference tiers include: | Raff PostgreSQL tier | Monthly price | Resources | |---|---:|---| | Entry | $7.99 | 1 vCPU / 1 GB / 25 GB | | Small production | $39.99 | 2 vCPU / 4 GB / 80 GB | | Scale | $127.99 | 8 vCPU / 16 GB / 180 GB | Raff Managed PostgreSQL starts at $7.99/month for 1 vCPU, 1 GB RAM, and 25 GB NVMe. Additional managed-database storage is $0.12/GB-month. PostgreSQL high availability adds 70% to the selected plan, and a PostgreSQL read replica is $29.99/month. Raff currently supports PostgreSQL 14, 15, and 16. The database service does not bundle Supabase-equivalent Auth, Realtime, generated client APIs, or file storage into the PostgreSQL product. Teams can combine Managed PostgreSQL with Raff Apps, Raff Functions, Object Storage, VPC networking, or their own application services without making those layers part of the database contract. Raff supports 3,000+ customers and 15,000+ production VMs under a published 99.9% platform SLA. On August 16, 2026, Raff's Trustpilot profile displayed 4.5/5; G2 is 4.6/5. ## Supabase pricing vs Raff pricing The two pricing models should not be treated as matched performance tiers. Supabase Pro is an organization-level backend plan with project compute and usage meters, while Raff prices provisioned managed PostgreSQL capacity directly. | Buying position | Raff Managed PostgreSQL | Supabase | Practical difference | |---|---|---|---| | Free development | $0 — 1 vCPU / 1 GB / 2 GB | $0 — 500 MB DB/project, shared CPU, 500 MB RAM, up to 2 active projects | Both have permanent free tiers; Supabase bundles more backend services | | Entry paid | $7.99 — 1 vCPU / 1 GB / 25 GB | Pro $25 — includes $10 compute credit covering one Micro | Raff is database-first; Supabase includes BaaS allowances | | Small production | $39.99 — 2 vCPU / 4 GB / 80 GB | Pro + Small compute totals $30 for one project after the $10 credit | Not a performance match; model workload and BaaS usage separately | | HA / recovery position | $67.98 — $39.99 tier with +70% HA | PITR starts about $100/month for 7 days and requires at least Small compute | Raff HA and Supabase PITR solve different risks | | Higher capacity | $127.99 — 8 vCPU / 16 GB / 180 GB | Compute scales separately up to larger paid instances | Compare actual workload, connections, disk, and service usage | **Comparison class:** these are buying positions, not matched benchmark tiers. Supabase Pro bundles backend services; Raff prices managed PostgreSQL capacity and explicit operational modifiers. A single Supabase Pro project on Small compute is illustrated in Supabase's billing documentation as $25 plan + $15 compute - $10 credit = **$30/month** before additional usage. A Micro project remains covered by the $10 compute credit, leaving the base Pro subscription at $25 when usage stays within included allowances. ### Automated backups and recovery cost Supabase automatically backs up Pro, Team, and Enterprise projects daily. Pro retains 7 days, Team 14 days, and Enterprise up to 30 days. Point-in-time recovery is a separate add-on: about $100/month for 7 days, $200 for 14 days, or $400 for 28 days, and the project must use at least Small compute. Raff includes managed backups and supports PITR for supported production PostgreSQL workflows. Optional HA is priced separately at +70% because failover availability and historical recovery are different controls. ### Usage and add-on costs Supabase Pro includes 8 GB of database disk per project and then charges $0.125/GB for general-purpose disk capacity. It also meters categories such as egress, file storage, MAU, Realtime messages and connections, Edge Function invocations, branching, and selected add-ons. Raff paid plans include their listed database storage allocation. Extra managed-database storage is $0.12/GB-month, PostgreSQL HA is +70%, and a PostgreSQL read replica is $29.99/month. :::cta Deploy a Database Now Deploy managed PostgreSQL with published resources, backups, pooling, private connectivity, and optional high availability. ::: ## Bandwidth and transfer policy Supabase Pro currently includes **250 GB of uncached egress** and **250 GB of cached egress**. Usage above those separate allowances is $0.09/GB uncached and $0.03/GB cached. Cached egress applies to Storage CDN traffic; database, Auth, Realtime, Functions, Supavisor, and other traffic can contribute to uncached egress. Using 1 TB = 1,024 GB and applying overage only after the 250 GB allowance, the transfer math is: | Monthly traffic in one egress category | Supabase uncached overage | Supabase cached overage | |---:|---:|---:| | 1 TB | $69.66 | $23.22 | | 5 TB | $438.30 | $146.10 | | 10 TB | $899.10 | $299.70 | | 50 TB | $4,585.50 | $1,528.50 | These figures model each quota independently; a real Supabase bill depends on how traffic is split between cached and uncached categories. Raff private VPC traffic is unmetered. For managed-database traffic that leaves Raff over a public path, verify the current billing for that route rather than assuming the VM-specific public bandwidth policy applies to databases. Supabase has an advantage when Storage CDN delivery and application services are deliberately integrated into the same billing model. Raff has an advantage when application-to-database traffic stays private inside Raff and the team wants database networking separated from public content delivery. ## Feature comparison: Supabase vs Raff | Feature | Raff Managed PostgreSQL | Supabase | |---|---|---| | Core product | Managed relational database service | PostgreSQL backend-as-a-service | | Permanent free tier | 1 vCPU / 1 GB / 2 GB | 500 MB DB/project, shared CPU, 500 MB RAM, 2 active projects | | Paid entry | $7.99/month | Pro from $25/month | | Current PostgreSQL versions | 14–16 | Hosted platform defaults to PostgreSQL 17 | | Connection pooling | Built in | Direct and pooled connection endpoints | | Authentication | Application / selected provider | Integrated Supabase Auth | | Generated APIs | Application-defined | Integrated database APIs | | Realtime | Application-defined | Integrated Realtime | | File storage | Separate Raff Object Storage | Integrated Supabase Storage | | Functions | Separate Raff Functions / Apps | Integrated Edge Functions | | Branching | Separate database environments | Preview branches on paid plans | | Backups | Managed | Daily on Pro/Team/Enterprise | | PITR | Supported production workflows | Paid add-on from about $100/month | | Traditional HA | Optional synchronous standby +70% | No directly equivalent fixed-price synchronous-standby toggle | | Region model | 1 public region: `us-east` | 17 specific AWS regions plus general regions | Supabase wins on application-backend integration, PostgreSQL 17, preview environments, and geographic choice. Raff wins on provisioned resource visibility, explicit HA pricing, a focused database operating model, and portability across separately selected application services. ## Features and reliability: Raff vs Supabase This is a non-VM comparison, so the useful evidence is feature and operating-model reliability rather than synthetic performance claims. Raff and Supabase have **0 controlled head-to-head database benchmarks** in this comparison, and neither is declared faster. ### Engine and version coverage Raff Managed PostgreSQL currently supports PostgreSQL 14–16. Supabase states that PostgreSQL 17 is now the default on its hosted platform and has also moved its current self-hosted default to PostgreSQL 17. Supabase therefore wins when PostgreSQL 17 is a hard requirement. A migration from Supabase PostgreSQL 17 to Raff must resolve version compatibility before data movement; it is not a routine downgrade. ### High availability and replicas Raff offers an optional synchronous standby and automatic failover model priced at +70% of the selected PostgreSQL plan. This exposes availability cost before deployment. Supabase offers read replicas and platform-managed project infrastructure, but its public pricing does not expose a directly equivalent fixed-price synchronous-standby toggle. Supabase's pricing page places formal uptime SLAs at Enterprise, while Team includes support SLAs. Read replicas should not be treated as backups or as an exact equivalent to Raff's synchronous HA topology. ### Backups and point-in-time recovery Raff includes managed backups and supports point-in-time recovery for supported production workflows. The application team still owns recovery-point selection and validation after restore. Supabase Pro includes 7 days of daily backups, Team 14 days, and Enterprise up to 30 days. PITR is available to paid projects as an add-on starting around $100/month for 7 days and requires at least Small compute. ### Networking and connections Raff provides built-in pooling, TLS, allowlist controls, and private connectivity for Raff-hosted workloads. Private VPC traffic is unmetered. Supabase gives each project direct and pooled PostgreSQL connection options. Its Pro pricing includes 250 GB uncached and 250 GB cached egress, while AWS PrivateLink is listed for Team and Enterprise rather than Free or Pro. ### Maintenance and upgrades Raff handles service-level maintenance for supported managed PostgreSQL versions while the application team owns schema migrations, query compatibility, extensions, credentials, and release validation. Supabase manages hosted project infrastructure and provides PostgreSQL upgrade workflows. Its 2026 platform direction uses PostgreSQL 17 as the default, so teams with older projects should treat major-version compatibility and extension support as explicit upgrade work. ### Reliability and trust signals Raff publishes a 99.9% platform SLA and supports 3,000+ customers and 15,000+ production VMs. Its Trustpilot profile displayed **4.5/5** on August 16, 2026. Supabase reports 8 million developers and 100,000 GitHub stars as of April 2026, which demonstrates a much larger developer ecosystem. Its Trustpilot page displayed **2.7/5** when checked on August 16, 2026. Review-site ratings are user sentiment signals, not uptime measurements. ## When you should choose Supabase over Raff - **Integrated backend services** — Supabase combines PostgreSQL with Auth, Storage, Realtime, APIs, and Edge Functions in one project. - **PostgreSQL 17** — Supabase's hosted platform currently defaults to PostgreSQL 17; Raff currently supports 14–16. - **Broader region choice** — Supabase lists 17 specific AWS regions plus general-region selection; Raff has 1 public region, `us-east`. - **Preview environments** — Supabase branching creates isolated environments on paid plans, with Micro branch compute starting at $0.01344/hour. - **Free BaaS experimentation** — Supabase Free provides 2 active projects plus Auth, Storage, Realtime, and Function allowances at $0. - **Large ecosystem** — Supabase reported 8 million developers and 100,000 GitHub stars in April 2026. ## When you should choose Raff over Supabase - **Focused managed PostgreSQL** — Raff provides a $0 database tier and paid PostgreSQL from $7.99/month without requiring adoption of a BaaS layer. - **Published capacity** — paid Raff tiers state vCPU, RAM, NVMe allocation, and monthly price directly. - **Explicit high availability** — PostgreSQL HA adds 70% to the selected Raff plan; the $39.99 tier becomes $67.98/month. - **Private Raff application paths** — private VPC traffic is unmetered when application and database services communicate inside Raff. - **Multiple database engines** — Raff also provides managed MySQL, Valkey, ClickHouse, and Kafka under the same cloud account. - **Portability by separation** — authentication, API, function, and storage choices can remain independent of the PostgreSQL service. ## Migrating from Supabase to Raff A Supabase-to-Raff migration is not only a PostgreSQL copy when the application uses Supabase-specific backend services. 1. **Inventory the Supabase project.** Record PostgreSQL major version, schemas, extensions, roles, Row Level Security policies, Auth providers, users, Storage buckets, Realtime subscriptions, Edge Functions, branches, webhooks, secrets, and client SDK dependencies. 2. **Confirm Raff compatibility and provision the target.** Select a Raff PostgreSQL tier, verify every required extension and PostgreSQL version, configure pooling, TLS, access rules, private networking, backups, and optional HA. 3. **Move PostgreSQL data.** Use `pg_dump`/`pg_restore` for suitable databases or logical replication for an active low-downtime migration where source and target configuration permit it. 4. **Replace application-backend dependencies.** Move file objects to the selected storage path, replace Supabase Auth where used, recreate API behavior, relocate Edge Functions, and redesign Realtime integrations that are not plain PostgreSQL features. 5. **Update application configuration.** Replace Supabase project URLs, keys, database endpoints, auth callbacks, storage URLs, secrets, webhooks, generated-client assumptions, and branch-specific environment configuration. 6. **Validate and cut over.** Verify row counts, sequences, extensions, RLS behavior, authentication, uploads, subscriptions, background jobs, connection pooling, backups, restore expectations, and rollback before switching production traffic. Operational gotchas: - A Supabase project already on PostgreSQL 17 cannot be treated as a routine downgrade to Raff PostgreSQL 14–16. - Row Level Security policies may remain PostgreSQL objects, but application identity claims supplied by Supabase Auth must be recreated correctly. - Supabase Storage signed URLs, Auth sessions, Realtime subscriptions, Edge Functions, and preview branches do not migrate automatically with the database. - Client libraries can combine database, Auth, Storage, and Realtime calls behind one SDK, so each dependency must be mapped explicitly. For a stateful production migration, keep Supabase available through a defined rollback window until database consistency and every application-facing replacement have been verified. ## About Supabase [Supabase](https://supabase.com/) is operated by Supabase Inc., a remote-first company whose work began in January 2020. The platform combines managed PostgreSQL with Auth, Storage, Realtime, generated APIs, Edge Functions, branching, SDKs, and observability. Supabase operates as a distributed global company rather than around a single conventional office headquarters. ## Conclusion: Supabase or Raff? The comparison resolves across four measured decision axes: - **Product scope** — Supabase bundles Auth, Storage, Realtime, APIs, Edge Functions, and branching; Raff keeps PostgreSQL focused and separately composable. - **Pricing model** — both have $0 tiers; Raff paid PostgreSQL starts at $7.99/month while Supabase Pro starts at $25/month plus applicable usage. - **Operations** — Raff publishes resource tiers and +70% PostgreSQL HA; Supabase combines project compute with platform services and add-ons. - **Reach and ecosystem** — Supabase offers 17 specific AWS regions and a much larger developer ecosystem; Raff exposes `us-east` and a narrower infrastructure model. Choose Supabase when integrated backend services, PostgreSQL 17, preview environments, or broad regional placement are requirements. Choose Raff when PostgreSQL should remain a focused managed service with explicit resources, recovery choices, private connectivity, and predictable operational modifiers. Raff supports 15,000+ production VMs and was verified at 4.5/5 on August 16, 2026. --- ### Fly.io Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/flyio-alternative Description: Considering Fly.io? Raff Apps starts at $3/mo with $0 public egress; Fly.io spans 18 regions with pay-as-you-go Machines. Raff Apps wins on fixed monthly ceilings, $0 public egress, full Docker Compose import, first-party managed data services, and a default spend cap. Fly.io wins on 18 global regions, Anycast routing, Machine-level control, flexible autoscaling, and region-specific pay-as-you-go compute that can be cheaper at some resource sizes. Choose Fly.io when multi-region placement and infrastructure control are requirements; choose Raff when `us-east`, predictable app costs, Compose portability, and a more managed workflow fit the workload. Raff Pro is $27.99/month for 2 vCPU and 4 GB, while Fly.io shared-cpu-2x with 4 GB currently runs about $21.40–$34.56/month across regional price matrices before storage, egress, IP, or support charges. Among Fly.io alternatives, Raff takes a deliberately different approach to application operations. Fly.io exposes 18 regions, Fly Machines, regional volumes, Anycast networking, and separate metered resources; Raff packages managed services into tiers from $3/month with $0 public app egress and visible monthly ceilings. Fly.io's short trial includes 2 total Machine hours or 7 days, while Raff's paid Micro tier is designed to remain deployed. The decision is less about which platform has more knobs and more about whether the team needs global infrastructure control or a tighter managed-service boundary. ## Fly.io vs Raff: which is right for you? The practical choice is global infrastructure control versus a managed application platform with tighter cost boundaries. | Decision factor | Choose Raff Apps | Choose Fly.io | |---|---|---| | Cost model | You want a published monthly ceiling per service | You want regional pay-as-you-go Machine pricing | | Entry service | You want 0.25 vCPU / 512 MB for $3/month | You want 1 shared CPU / 512 MB at about $3.19–$5.16/month by region | | Geography | One public `us-east` region fits | You need placement across 18 regions | | Bandwidth | Public application egress should cost $0 | $0.02–$0.12/GB internet egress is acceptable | | Deployment | GitHub, buildpacks, Dockerfile, image, or full Compose import fits | `flyctl`, `fly.toml`, Machines, and APIs fit | | Persistent state | App volumes plus 5 managed data engines fit | Regional Fly Volumes and Managed Postgres fit | | Scaling | Managed service tiers and scale-to-zero fit | Autostop/autostart and programmable metrics scaling are required | Fly.io is stronger when region placement, Anycast routing, and Machine-level behavior are part of the application architecture. Raff is stronger when the workload fits `us-east` and the team wants fewer infrastructure decisions, predictable service ceilings, and $0 public app egress. ## Fly.io overview Fly.io is a developer-focused public cloud built around Fly Machines. It turns application containers into hardware-isolated virtual machines and exposes them through `flyctl`, `fly.toml`, the Machines API, private networking, volumes, and a global Anycast network. Fly.io currently lists **18 application regions** across North America, Europe, Asia-Pacific, South America, and Africa. Machines and Fly Volumes are tied to the region where they are created, while Fly Proxy and Anycast networking can route traffic across globally distributed application instances. Fly.io supports two documented autoscaling models. **Autostop/autostart** starts or stops an existing pool of Machines based on traffic; it does not create new Machines. **Metrics-based autoscaling** can create, delete, start, or stop Machines based on a metric the team defines, with the reconciliation loop running every **15 seconds by default**. Stopped or suspended Machines do not incur CPU and RAM charges, but stopped Machine root filesystems and provisioned volumes can remain billable. This can reduce compute cost for sporadic workloads while increasing the importance of understanding Machine state, regional capacity, storage, and minimum-running settings. Fly.io's current free trial includes **2 total Machine hours or 7 days**, whichever comes first, with up to 10 Machines, 20 GB of volume storage, 2 vCPUs per Machine, and 4 GB of memory per Machine. It is an evaluation period, not a permanent free production tier. ## Raff overview [Raff Apps](/products/app-platform) is Raff's managed application platform for deploying source code and containers without administering the underlying operating system. It supports GitHub push-to-deploy, Dockerfiles, existing images, buildpacks, and full Docker Compose imports. Raff Apps supports public web services, private services, long-running workers, timezone-aware cron jobs, one-off jobs, pull-request preview environments, persistent application volumes, immutable revisions, one-click rollback, and scale-to-zero behavior. Applications can connect to Raff Managed Databases for PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, plus object storage, VMs, private networking, Kubernetes, and Functions. Current service tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Runtime is billed per second against each published monthly ceiling. Public application egress and Apps team seats cost $0, and the spend cap is enabled by default. From Raff's side, the pricing rule we use is simple: cost protection should exist before the first production traffic spike. That is why the service ceiling and default spend cap are part of the product model rather than optional cost controls a small team has to configure after deployment. Raff currently exposes one public Apps region, `us-east`. Raff reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. On August 16, 2026, Raff was rated **4.5/5**, with G2 at 4.6/5. ## Fly.io pricing vs Raff pricing Fly.io and Raff both meter runtime at a fine-grained level, but the pricing structures answer different questions. Raff asks the team to choose a service tier with a published monthly ceiling. Fly.io prices a running Machine from a regional CPU/RAM preset, then adds separately priced storage, snapshots, networking, databases, IP addresses, certificates, or support when used. | Buying position | Raff Apps | Fly.io | Decision signal | |---|---:|---:|---| | 512 MB service | Micro — 0.25 vCPU / 512 MB / $3 | shared-cpu-1x / 512 MB — about $3.19–$5.16 | Fly includes more listed shared CPU; Raff has one ceiling | | 1 GB service | Starter — 0.5 vCPU / 1 GB / $6.99 | shared-cpu-1x / 1 GB — about $5.70–$9.20 | Fly may be lower or higher by region | | 2 GB service | Standard — 1 vCPU / 2 GB / $16.99 | shared-cpu-1x / 2 GB — about $10.70–$17.28 | Published CPU labels are not benchmark equivalence | | 2 CPU / 4 GB service | Pro — 2 vCPU / 4 GB / $27.99 | shared-cpu-2x / 4 GB — about $21.40–$34.56 | Fly may be lower or higher before add-ons | | Technical support | Included direct cloud support | Community included; Standard $29/month | Paid Fly support can exceed small compute spend | **Comparison class:** these rows compare published resource shapes and current regional price matrices, not measured application throughput. Fly.io distinguishes shared and performance CPU classes and varies compute prices by region; Raff Apps does not publish an equivalent Fly CPU-class taxonomy. ### Bandwidth cost math Fly.io meters public internet egress by region group at **$0.02/GB** from North America and Europe, **$0.04/GB** from Asia-Pacific, Oceania, and South America, and **$0.12/GB** from Africa and India. Raff Apps public application egress is $0. | Monthly public egress | Raff Apps | Fly.io NA / Europe | Fly.io APAC / Oceania / South America | Fly.io Africa / India | |---:|---:|---:|---:|---:| | 1 TiB | $0 | $20.48 | $40.96 | $122.88 | | 5 TiB | $0 | $102.40 | $204.80 | $614.40 | | 10 TiB | $0 | $204.80 | $409.60 | $1,228.80 | The calculations use 1 TiB = 1,024 GB and include only public egress. They exclude compute, volumes, snapshots, cross-region private transfer, IP addresses, databases, support, certificates, and taxes. ### Automated backups Fly Volumes cost **$0.15/GB-month** and new volumes receive automatic daily block-level snapshots with **5 days of retention by default**. Snapshot storage costs **$0.08/GB-month**, with the first 10 GB free each month, and retention can be configured from 1 to 60 days. Fly.io explicitly warns that daily snapshots may not contain the latest data and recommends a separate backup plan for important state. Fly.io Managed Postgres includes high availability, backups, and connection pooling on every current plan; Basic starts at **$38/month** for Shared-2x and 1 GB RAM plus **$0.28 per provisioned GB-month** of database storage. Raff also separates application revision rollback from durable-data backup. Immutable app revisions help recover a deployment, but persistent volumes, managed databases, and object storage still need recovery policies appropriate to the data they hold. ### Hidden platform costs Fly.io's current pay-as-you-go model can add several resource lines beyond a running Machine: Volumes at $0.15/GB-month, snapshot storage at $0.08/GB-month after the first 10 GB, dedicated IPv4 at $2/month, paid support from $29/month, and public egress at $0.02–$0.12/GB by region group. Managed SSL is free for the first 10 single-hostname certificates, then $0.10/month each; wildcard certificates are $1/month. Fly.io offers a **40% compute discount** through eligible prepaid Machine reservations. Those reservations are specific to a region and CPU class, and unused monthly reservation credit does not roll over. That can improve Fly.io economics for stable workloads but is a different commitment model from on-demand comparison pricing. :::cta Deploy an App Now Deploy managed app services with fixed ceilings and $0 public egress. ::: ## Bandwidth and transfer policy Fly.io charges for traffic leaving an application to the public internet and for private traffic crossing regions. Under its granular rates, private cross-region transfer is currently **$0.006/GB** in North America and Europe, **$0.015/GB** in Asia-Pacific, Oceania, and South America, and **$0.05/GB** in Africa and India. Inbound traffic is free, and same-region transfer between apps or Machines is free within the documented granular-rate model. Raff Apps prices public application egress at $0. For public APIs, downloads, or products with unpredictable outbound traffic, that removes a variable charge from the app bill. Fly.io is stronger when its global region placement and Anycast design are worth the transfer complexity, particularly when most application and data traffic stays local to each region. A distributed Fly.io design should model both internet egress and cross-region private traffic. A centralized Raff Apps design should instead model the latency implications of keeping the application in one public `us-east` region. ## Feature comparison: Fly.io vs Raff | Feature | Raff Apps | Fly.io | |---|---|---| | Entry managed service | $3/month | 512 MB shared Machine about $3.19–$5.16/month by region | | Public regions | 1 — `us-east` | 18 | | Primary deployment workflow | Visual platform + GitHub | CLI-first with `flyctl` and `fly.toml` | | Dockerfile / image | Yes | Yes | | Full Docker Compose import | Yes | No whole-stack Compose import | | Persistent app storage | Yes | Fly Volumes at $0.15/GB-month | | Public app egress | $0 | $0.02–$0.12/GB by region group | | Scale-to-zero behavior | Available | Autostop/autostart existing Machines | | Metrics-based autoscaling | Not published as an equivalent Apps control | Creates/deletes or starts/stops Machines | | Managed PostgreSQL | Yes | Yes, from $38/month + storage | | Managed MySQL | Yes | No first-party Fly Managed MySQL product documented | | Managed Redis-compatible engine | Valkey | Upstash is a partnered extension | | Object storage | Raff S3-compatible Object Storage | Tigris is a partnered extension | | Included direct technical support | Yes | Community; paid email support from $29/month | Fly.io wins on global placement, Anycast networking, Machine-level control, performance CPU options, and programmable scaling. Raff wins on simpler fixed service ceilings, full Docker Compose import, $0 public app egress, first-party MySQL/Valkey choices, and included direct support. ## Features and reliability: Raff vs Fly.io This comparison includes **0 controlled Raff-versus-Fly.io application benchmarks**, so it does not declare either platform faster. A valid application test would need the same image, CPU scheduling class, memory, region, storage path, datastore placement, concurrency profile, network route, and repeated measurement window. ### Region placement and routing Fly.io's clearest reliability and latency advantage is geographic control. Teams can place Machines in **18 regions**, and the global Anycast network can route incoming connections toward deployed instances. This is materially stronger than Raff Apps' current single public `us-east` region for products serving users across several continents. That flexibility moves more architecture responsibility to the team. Machines and volumes are regional, so application state, database topology, request routing, and failover behavior need to match the chosen placement model. ### Autoscaling and stopped Machines Fly Proxy autostop/autostart starts and stops an existing Machine pool according to traffic and concurrency. Stopped or suspended Machines do not accrue CPU or RAM charges, though their root filesystems and attached volumes can remain billable. Fly.io's metrics-based autoscaler goes further by creating/deleting or starting/stopping Machines using user-defined metrics, with a **15-second default reconciliation loop**. This is more programmable than Raff's public Apps scaling surface and is a genuine advantage for infrastructure-aware teams. ### Persistent state and snapshots Fly Volumes are hardware-local, regional persistent NVMe storage. Fly.io takes daily block-level snapshots with **5-day default retention**, but explicitly recommends an independent backup plan for important data. A snapshot can restore into a new equal-or-larger volume; it does not turn a local volume into globally shared storage. Raff Apps supports persistent application volumes and also provides managed databases and object storage. On both platforms, stateful reliability requires matching the storage layer to the workload rather than treating application rollback as data protection. ### Managed database reliability Fly.io Managed Postgres includes high availability, backups, connection pooling, and replicated storage. It is available in **12 regions** and currently starts at **$38/month + $0.28/GB-month** of provisioned storage. Raff exposes five managed data engines—PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka—inside the same cloud workflow. Fly.io has the stronger distributed Postgres geography; Raff has the broader first-party engine set for this comparison. ### SLA and support Fly.io's current **99.9% uptime SLA is part of its Enterprise support plan**, which starts at **$2,500+/month**. Standard support is $29/month and Premium is $199/month; community support remains free. Raff publishes a **99.9% platform SLA** and includes direct cloud support without a separate entry support subscription. Public review evidence is also different: on August 16, 2026, Fly.io's unclaimed Trustpilot profile showed **2.8/5**, while Raff's claimed profile showed **4.5/5**. Review counts are small enough that neither score should substitute for architecture or support evaluation. ## When you should choose Fly.io over Raff Choose Fly.io when: - **Global placement is required.** Fly.io lists **18 regions** versus Raff Apps' single public `us-east` region. - **Anycast routing is part of the design.** Fly Proxy supports globally routed applications across regional Machine deployments. - **Machine-level control matters.** Fly exposes shared/performance CPU classes, memory, regional placement, `fly.toml`, `flyctl`, and the Machines API. - **Programmable autoscaling is required.** Metrics-based scaling can create, delete, start, or stop Machines with a **15-second default loop**. - **Sporadic workloads benefit from stopped compute.** Stopped/suspended Machines incur **$0 CPU and RAM charges**, though storage remains billable. - **Regional Managed Postgres matters.** Fly Managed Postgres is available in **12 regions** and includes HA and backups. - **Prepaying for stable compute is acceptable.** Eligible Machine reservations provide a **40% discount** for a specific region and CPU class. ## When you should choose Raff over Fly.io Choose Raff Apps when: - **A visible monthly ceiling matters.** Raff tiers run from **$3 to $119.99/month** with per-second prorating against the ceiling. - **Public egress is material.** Raff Apps charges **$0** for public egress versus Fly.io's $0.02–$0.12/GB regional rates. - **Docker Compose describes the stack.** Raff can import a **full Compose stack** instead of translating it into Fly-specific configuration. - **A broader first-party managed data set is useful.** Raff exposes **5 managed engines**: PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka. - **Support should not be a separate subscription.** Fly.io technical support starts at **$29/month**; Raff includes direct cloud support. - **A default spend guardrail matters.** Raff enables the Apps spend cap by default in addition to service ceilings. - **The workload fits `us-east`.** Fly.io's 18-region advantage adds little when one eastern-U.S. application region already meets the latency requirement. Raff currently supports **3,000+ customers and 15,000+ production VMs**. For adjacent app-platform decisions, compare [Render and Raff](/learn/compare/render-alternative), [Coolify and Raff](/learn/compare/coolify-alternative), and [DigitalOcean App Platform and Raff](/learn/compare/digitalocean-app-platform-alternative). ## Migrating from Fly.io to Raff 1. **Inventory the Fly.io organization.** Record apps, process groups, Machines, CPU/memory sizes, regions, volumes, secrets, certificates, IPs, private-network dependencies, Managed Postgres, extensions, and every `fly.toml` file. **Gotcha:** `fly.toml` is provider-specific and cannot be imported as a Raff service definition. 2. **Map Fly processes to Raff services.** Move HTTP processes to web services, internal processes to private services, consumers to workers, scheduled tasks to cron jobs, and administrative commands to one-off jobs. 3. **Choose a portable deployment source.** Connect GitHub, deploy an image, use a Dockerfile or buildpack, or convert a multi-service stack into Docker Compose. **Gotcha:** Fly autostop, concurrency, regional placement, and Machine-count rules need to be redesigned rather than copied verbatim. 4. **Export persistent state.** Use database-native export/restore tools for PostgreSQL and synchronize files from every Fly Volume. Move durable shared uploads to object storage where multiple app instances need access. 5. **Recreate configuration and verify.** Add secrets, domains, private bindings, health checks, volumes, managed data services, callbacks, and outbound allowlists. Validate on a temporary hostname and rehearse a restore before production cutover. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, complete the final data synchronization, update DNS, callbacks, and allowlists, monitor the Raff deployment, and retain Fly.io until the rollback window closes. Stateless containerized services are usually the simplest part of the move. Stateful volumes, Managed Postgres, Anycast assumptions, cross-region traffic, fixed outbound IPs, and Fly-specific scaling rules create most of the migration risk. ## About Fly.io [Fly.io](https://fly.io/) is operated by **Fly.io, Inc.**, a developer-focused public cloud founded in **2017** and based in Chicago. It runs containerized applications as hardware-isolated Fly Machines across 18 regions, with Anycast networking, regional volumes, Managed Postgres, APIs, and Fly Kubernetes. Current Fly.io terms identify Fly.io, Inc. as the contracting entity. ## Conclusion: Fly.io or Raff? The Fly.io-versus-Raff decision resolves across four measured axes: cost boundary, global placement, state and recovery, and operational control. - **Cost boundary:** Raff Pro is **$27.99/month** at 2 vCPU / 4 GB with $0 public app egress; Fly.io's comparable published shared-cpu-2x / 4 GB shape is about **$21.40–$34.56/month by region** before separate storage, egress, IP, or support charges. - **Global placement:** Fly.io offers **18 application regions** and Anycast routing; Raff Apps currently exposes one public `us-east` region. - **State and recovery:** Fly Volumes cost **$0.15/GB-month** with daily snapshots and 5-day default retention; Raff combines persistent app volumes with five first-party managed data engines and object storage. - **Operational control:** Fly.io exposes Machines, `fly.toml`, APIs, regional networking, and programmable autoscaling; Raff emphasizes GitHub deployment, full Compose import, service ceilings, a default spend cap, and included support. Choose Fly.io when multi-region placement, Anycast routing, Machine control, or programmable scaling are required. Choose Raff when `us-east` is sufficient and the team values predictable service ceilings, $0 public egress, Docker Compose portability, first-party managed data options, and a more managed operating model. Raff currently reports **3,000+ customers, 15,000+ production VMs, Trustpilot 4.5/5, G2 4.6/5, and a 99.9% platform SLA**. --- ### Coolify Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/coolify-alternative Description: Considering Coolify? Raff Apps starts at $3/mo with $0 public egress; Coolify is free self-hosted but requires your own server. Raff Apps wins on managed runtime infrastructure, fixed service ceilings, $0 public application egress, first-party managed data services, and reduced server maintenance. Coolify wins on open-source ownership, host-level control, infrastructure-provider choice, broader Git-provider support, and the ability to deploy unlimited workloads across user-selected servers. Choose Coolify when owning the server and control plane is part of the requirement; choose Raff when the goal is to deploy services without operating the platform beneath them. Raff Apps starts at $3/month including runtime, while Coolify self-hosted software is $0 and Coolify Cloud starts at $5/month for two connected servers before workload-server costs. Coolify and Raff Apps can both deploy Git projects, Dockerfiles, images, and Docker Compose stacks, but the operational boundary is fundamentally different. Coolify runs as an open-source control plane over infrastructure the customer supplies, and Coolify Cloud manages that control plane for $5/month while customers still bring their own servers. Raff Technologies includes the application runtime inside published service tiers, starting at $3/month with $0 public app egress. The comparison therefore turns on infrastructure ownership, operating responsibility, and whether server density or service-by-service cost boundaries matter more. ## Coolify vs Raff: which is right for you? Coolify is the better fit when server ownership is intentional. Raff is the better fit when infrastructure maintenance is work the application team wants the platform to absorb. | Decision factor | Choose Raff Apps | Choose Coolify | |---|---|---| | Operating model | Managed application runtime and platform | Open-source control plane on servers you own or rent | | Entry price | Micro from $3/month including runtime | Self-hosted software $0; server required | | Managed control plane | Included | Cloud $5/month for 2 connected servers | | Cost boundary | Published per-service ceiling and default spend cap | Server bill + storage + networking + backup + optional Cloud fee | | Server maintenance | Raff manages platform hosts | Customer manages workload servers | | Location choice | One public `us-east` region | Any supported user-selected server location | | Portability | Dockerfile, image, buildpacks, and full Compose import | Open-source control plane, Docker, Compose, and host access | For a small team, the most important question is not whether Coolify or Raff has more deployment features. It is whether Linux patching, Docker capacity, SSH security, disk pressure, network policy, workload backups, and provider billing should remain part of the team's operating model. ## Coolify overview [Coolify](https://coolify.io/) is an open-source, self-hostable platform for deploying applications, databases, and Docker-compatible services on infrastructure selected by the user. Its documentation explicitly says Coolify is not a cloud service that supplies application compute: users provide a VPS, EC2 instance, Raspberry Pi, laptop, or other supported server and connect it over SSH. The self-hosted edition is **free forever** with the full feature set. Coolify supports GitHub, GitLab, Bitbucket, Gitea, and other Git sources; Dockerfiles; Docker Compose; container images; pull-request deployments; automatic Let's Encrypt certificates; APIs; webhooks; monitoring; database deployments; S3-compatible backups; and Docker Swarm. Its current documentation says Kubernetes support is coming later. Coolify Cloud manages the Coolify control plane rather than the workload servers. It costs **$5/month for up to 2 connected servers** and **$3/month for each additional server**, with a 20% discount displayed for annual billing. Customers still bring and pay for the servers where applications, databases, and services run. Coolify Cloud reports **2,100+ active users**, while the broader Coolify documentation reports **204,000+ servers** running Coolify and a community above 16,000 members. Coolify's strongest advantages are ownership and infrastructure freedom. Teams can choose server providers and locations, keep data and configuration on their own infrastructure, use host-level Docker capabilities, and move the control plane without translating every application into a proprietary runtime model. ## Raff overview [Raff Apps](/products/app-platform) is a managed application platform for deploying source code and containers without administering the underlying operating system. It supports GitHub push-to-deploy, buildpacks, Dockerfiles, existing container images, and full Docker Compose imports. Raff Apps supports public web services, private services, background workers, timezone-aware cron jobs, one-off jobs, pull-request previews, immutable revisions, one-click rollback, persistent volumes, and scale-to-zero behavior. Applications can connect to managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, as well as object storage, VMs, private networking, Kubernetes, and Functions. Current Raff Apps tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Compute is billed per second against the published monthly ceiling. Public application egress and team seats are priced at $0, and the spend cap is enabled by default. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. Raff was verified at **4.5/5** on August 16, 2026, and G2 is 4.6/5. Raff gives up Coolify's host-level freedom in exchange for a smaller operational surface and explicit service-by-service resource boundaries. ## Coolify pricing vs Raff pricing Coolify and Raff price different layers. Raff's Apps price includes the application runtime. Coolify self-hosted is software that runs on infrastructure the customer supplies, while Coolify Cloud charges for a hosted control plane and still requires external workload servers. | Buying position | Raff Apps | Coolify | Decision signal | |---|---:|---:|---| | Entry deployment | Micro $3 including runtime | Self-hosted $0 software + server | Coolify wins if suitable infrastructure already exists | | Hosted control plane | Included in Apps service | Cloud $5/month for up to 2 servers | Coolify Cloud fee does not include workload compute | | 3 connected servers | Workloads priced by selected Apps services | $8/month control-plane fee + 3 server bills | Coolify rewards teams intentionally operating a server fleet | | 10 connected servers | Workloads priced by selected Apps services | $29/month control-plane fee + 10 server bills | Server, storage, transfer, and operations dominate total cost | | 2 vCPU / 4 GB application | Raff Pro $27.99 including managed runtime | No fixed Coolify compute price; depends on chosen server | Not a performance-equivalent price comparison | **Comparison class:** Coolify is a control plane, not a fixed compute service. Its software fee cannot be compared directly with a Raff Apps instance unless the Coolify workload server, storage, bandwidth, backup destination, and operating effort are included. ### Automated backups Coolify Cloud automatically backs up the **Coolify Cloud database every 24 hours**. That protects the managed control plane; it should not be treated as an automatic backup of every application, database, or persistent volume on connected servers. For workload data, Coolify supports scheduled database backups using cron-style frequencies and can store backups locally or in S3-compatible storage with configurable retention. The operator chooses the schedule, storage target, and retention policy and remains responsible for verifying restores. Raff also separates application deployment rollback from durable-data recovery. App revisions are not database backups. Production state should live in managed databases, object storage, or persistent volumes with a documented recovery path appropriate to the selected service. ### Hidden infrastructure costs Coolify's self-hosted $0 software price is real, but total application cost can include the server, block or local storage, snapshots, public transfer, backup storage, monitoring, spare capacity for builds, and engineering time for updates and incidents. Coolify Cloud removes maintenance of the Coolify instance itself, not the connected workload servers. Coolify can be cheaper when several low-traffic applications share one well-managed server. Raff can cost more than dense server packing because services have explicit resource boundaries, but that model also limits the number of operational variables a small application team must own. :::cta Deploy an App Now Deploy containers, workers, cron jobs, and Docker Compose stacks with managed runtime infrastructure. ::: ## Bandwidth and transfer policy Raff Apps charges **$0 for public application egress**. Coolify does not publish one universal workload-bandwidth price because the user's connected server provider controls transfer allowances, overage rates, port characteristics, and regional network charges. That distinction makes Coolify's network economics highly provider-dependent. A server with generous or unmetered transfer can make a Coolify deployment attractive for bandwidth-heavy applications, while a server with metered cloud egress can create a materially different bill even though Coolify itself adds no per-GB application fee. For budgeting, a Coolify team must evaluate at least two separate network boundaries: traffic associated with the workload server and any storage or cross-region transfer used by the application. Raff collapses normal public Apps egress to $0, making transfer easier to forecast but offering less location choice than Coolify's bring-your-own-server model. ## Feature comparison: Coolify vs Raff | Feature | Raff Apps | Coolify | |---|---|---| | Primary model | Managed app runtime | Open-source deployment control plane | | Git providers | GitHub | GitHub, GitLab, Bitbucket, Gitea, other Git sources | | Dockerfile / existing image | Yes | Yes | | Docker Compose | Full stack import | Primary deployment path, including raw Compose | | Pull-request deployments | Yes | Yes | | Host-level access | No | Yes, on user-controlled servers | | Location choice | Public `us-east` region | Any supported server location/provider | | Public app egress | $0 | Provider-dependent | | Long-running workers | First-class service type | Containers/services configured by operator | | Private services | First-class service type | Docker/provider networking controlled by operator | | Persistent volumes | Managed application volumes | Host/provider storage controlled by operator | | Managed PostgreSQL | First-party Raff service | Customer-operated PostgreSQL deployment | | Managed MySQL | First-party Raff service | Customer-operated MySQL/MariaDB deployment | | S3-compatible backups | Available through Raff data products | Configurable scheduled DB/instance backups | | Multi-server | Managed platform abstraction | Unlimited connected servers; Docker Swarm supported | | Kubernetes | Raff Managed Kubernetes is live separately | Documented as coming later | | Team members | $0 Apps seat fee | Unlimited; Cloud teams can require separate subscriptions | | Open-source control plane | No | Yes | Coolify wins on infrastructure-provider choice, host access, open-source ownership, Git-provider breadth, and server-level Docker control. Raff wins on managed workload infrastructure, explicit service resources, first-party managed data services, $0 public application egress, and removing Linux/Docker host maintenance from the application team's responsibilities. ## Features and reliability: Raff vs Coolify This comparison includes **0 controlled Raff-versus-Coolify application benchmarks**, so it does not declare either platform faster. Coolify does not have one standardized compute substrate: the user can deploy it against VPS instances, dedicated servers, local machines, cloud instances, or Docker Swarm clusters, so performance follows the chosen infrastructure and topology. ### Reliability ownership Raff operates the Apps platform host, deployment system, and runtime infrastructure. The customer still owns application code, configuration, data design, secrets, and external dependencies. Coolify self-hosting shifts more of the reliability surface to the operator: Linux security updates, SSH access, Docker updates, disk capacity, reverse proxy availability, server monitoring, provider incidents, workload backups, and recovery. Coolify Cloud removes maintenance of the Coolify control plane, but connected servers remain customer-operated infrastructure. ### Application isolation and density Coolify lets teams pack several workloads onto one server and configure Docker resource limits themselves. That can improve infrastructure utilization, but it also creates a shared capacity and failure domain unless the operator deliberately isolates workloads and reserves headroom. Raff assigns applications to published service tiers. The team gives up some server-packing flexibility but gets explicit vCPU/RAM boundaries and monthly ceilings per service. ### Backups and recovery Coolify supports scheduled database backups and S3-compatible destinations with configurable retention. Coolify Cloud separately backs up its own control-plane database every 24 hours. Application volumes, uploaded files, provider snapshots, and external services still need an explicit recovery design. Raff also requires state-aware recovery planning. Application revision rollback, managed-database recovery, object storage, and persistent-volume protection are separate concerns and should be tested independently. ### Release safety Coolify supports health checks and can roll back using Docker images that remain available locally. Raff uses immutable application revisions and one-click rollback. In both cases, rolling application code backward does not automatically undo incompatible database migrations or restore lost data. ### Availability design Coolify can connect unlimited servers and supports single-server, multi-server, and Docker Swarm setups, giving experienced teams wide freedom to design availability. The platform does not turn a single connected server into a highly available application automatically. Raff publishes a **99.9% platform SLA** and abstracts host placement from the Apps user. Application architecture still matters: a single app instance, database, or external dependency can remain a failure point on either model. ## When you should choose Coolify over Raff Choose Coolify when: - **Open-source ownership is mandatory.** The full Coolify feature set is available in its $0 self-hosted edition. - **You already operate servers well.** The team has Linux, Docker, monitoring, backup, and incident-response practices in place. - **Infrastructure-provider choice matters.** Coolify can connect unlimited compatible servers from locations and providers you select. - **Multi-app server density is valuable.** Several low-traffic services can share one server instead of each having a separate managed service tier. - **Git-provider breadth matters.** Coolify supports GitHub, GitLab, Bitbucket, Gitea, and other Git workflows. - **Deep Docker control is required.** Raw Compose, custom networks, storage, and host-level configuration remain available to the operator. - **A large self-hosted service catalog is useful.** Coolify documents 200+ one-click services alongside arbitrary Docker-compatible workloads. Coolify can also run on a Raff Linux VM when a team wants Coolify's control plane while keeping the underlying server on Raff infrastructure. The [Coolify installation tutorial](/learn/tutorials/install-coolify-ubuntu-24-04) covers that path. ## When you should choose Raff over Coolify Choose Raff Apps when: - **Server maintenance should disappear from the workflow.** Raff manages the runtime host instead of asking the application team to patch Linux and Docker. - **Service cost boundaries matter.** Raff Standard is $16.99 for 1 vCPU / 2 GB and Raff Pro is $27.99 for 2 vCPU / 4 GB, each with a published ceiling. - **Public transfer is substantial.** Raff Apps prices public egress at $0 rather than inheriting a connected server provider's transfer schedule. - **Managed databases are preferred.** Raff provides PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka without operating database containers inside the app stack. - **A default spend guardrail matters.** The Apps spend cap is enabled by default. - **Persistent application services are the main abstraction.** Web, private, worker, cron, and one-off services are first-class platform types. - **One cloud account should span the stack.** Apps can connect to Raff databases, object storage, VMs, private networks, Kubernetes, and Functions. ## Migrating from Coolify to Raff 1. **Inventory every Coolify resource.** Record applications, Compose stacks, Git sources, domains, environment variables, secrets, ports, health checks, volumes, databases, schedules, webhooks, and host-specific dependencies. **Gotcha:** Coolify labels and proxy rules are not portable application configuration. 2. **Map workloads to Raff services.** Move public HTTP workloads to web services, internal components to private services, consumers to workers, schedules to cron jobs, and administrative commands to one-off jobs. 3. **Choose a portable deployment source.** Use GitHub, an existing image, a Dockerfile, buildpacks, or a Docker Compose import. **Gotcha:** bind mounts, host networking, privileged containers, devices, and host paths may need redesign on a managed platform. 4. **Export persistent state.** Create database-native dumps, archive application volumes, copy uploaded files, verify checksums, and move shared object data to an appropriate durable service before final synchronization. 5. **Recreate configuration and verify.** Add secrets, domains, health checks, private bindings, storage, database credentials, OAuth callbacks, webhooks, and allowlists. Test a temporary hostname and perform a restore rehearsal. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, freeze writes where necessary, complete the final data sync, change DNS and callbacks, monitor production, and retain the Coolify deployment until the rollback window closes. Stateless containers are usually the simplest part of a Coolify-to-Raff migration. Stateful volumes, databases, host networking, server cron, proxy labels, and provider-specific infrastructure create most of the migration risk. ## About Coolify [Coolify](https://coolify.io/) is an open-source self-hosting platform operated by **coolLabs Solutions Kft.**, a Hungary-based software company. It deploys applications, databases, and Docker-compatible services to customer-controlled infrastructure and offers both a free self-hosted control plane and a managed Coolify Cloud option. Official documentation currently reports 204,000+ servers running Coolify. ## Conclusion: Coolify or Raff? The Coolify-versus-Raff decision resolves across four measured axes: operating responsibility, cost boundary, infrastructure control, and data/availability ownership. - **Operating responsibility:** Raff manages the Apps runtime host; Coolify users manage workload servers even when the Coolify Cloud control plane is managed. - **Cost boundary:** Raff Apps starts at $3 with published service ceilings; Coolify self-hosted is $0 software and Cloud starts at $5 for 2 servers, but workload infrastructure is separate. - **Infrastructure control:** Coolify provides open-source host access and user-selected locations; Raff deliberately abstracts the host and exposes one public `us-east` Apps region. - **Data and availability ownership:** Coolify gives operators direct control over Docker, storage, backup schedules, and multi-server topology; Raff provides managed service boundaries and first-party data products. Choose Coolify when open-source ownership, server density, provider choice, and host-level control justify owning the infrastructure lifecycle. Choose Raff when the objective is to ship connected application services with explicit resource ceilings, $0 public egress, managed data services, and less server administration. Raff currently reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. For adjacent decisions, review [Render Alternative 2026](/learn/compare/render-alternative), [Self-Hosting Apps on Raff](/learn/guides/self-hosting-apps-on-raff), and [Install Coolify on Ubuntu 24.04](/learn/tutorials/install-coolify-ubuntu-24-04). --- ### DigitalOcean App Platform Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/digitalocean-app-platform-alternative Description: Considering DigitalOcean App Platform? Raff Apps starts at $3/mo with $0 public egress; DigitalOcean starts at $5/mo across 12 regions. Raff Apps wins on lower comparable service prices, $0 public application egress, persistent application volumes, full Docker Compose imports, and first-party managed data services. DigitalOcean App Platform wins on 12 deployment regions, a free static-site tier, GitLab and Bitbucket sources, dedicated CPU plans, mature autoscaling, and a 99.95% per-component SLA. Choose DigitalOcean App Platform when regional placement and autoscaling are requirements; choose Raff when `us-east`, durable app volumes, Compose portability, and a tighter monthly cost boundary fit the workload. Raff Pro is $27.99/month for 2 vCPU and 4 GB, while DigitalOcean's 2 shared vCPU / 4 GiB plan is $50/month with 250 GiB of outbound transfer included. DigitalOcean App Platform and Raff Apps are both managed deployment platforms, but their strongest buying cases are different. DigitalOcean spreads dynamic apps across 12 regions and can autoscale request-driven services to 100 containers, while Raff exposes one public `us-east` region and emphasizes predictable service tiers, $0 public app egress, and persistent volumes. DigitalOcean starts dynamic compute at $5/month; Raff Apps starts at $3/month. For small SaaS teams, the useful comparison is therefore not only deployment convenience but the full cost and operating model once transfer, durable state, source integrations, and scaling requirements are included. ## DigitalOcean App Platform vs Raff: which is right for you? DigitalOcean App Platform is the stronger fit when location choice, autoscaling, dedicated CPU, or multiple Git providers are requirements. Raff is the stronger fit when the workload can stay in `us-east` and the team values lower listed service prices, persistent application volumes, Docker Compose portability, and $0 public egress. | Decision factor | Choose Raff Apps | Choose DigitalOcean App Platform | |---|---|---| | Dynamic entry price | You want a managed runtime from $3/month | You want 1 shared vCPU / 512 MiB from $5/month | | Geography | One public `us-east` region fits the workload | You need one of 12 App Platform regions | | Persistent files | Application-attached persistent volumes matter | Durable state can live in Spaces or Managed Databases | | Bandwidth | Public application egress should cost $0 | Included pooled transfer plus $0.02/GiB overage fits | | Source providers | GitHub is sufficient | GitHub, GitLab, or Bitbucket is required | | Scaling | Published service tiers and scale-to-zero fit | Request-based or CPU-based autoscaling is required | | Deployment model | Full Docker Compose import matters | App Spec, API, `doctl`, or Terraform is preferred | From the Raff pricing side, the practical lesson is to compare the complete application bill rather than the smallest plan card. DigitalOcean's $5 entry tier includes more listed shared CPU than Raff Micro, but the decision changes materially at matched 1 vCPU / 2 GB and 2 vCPU / 4 GB sizes, and changes again when outbound transfer or persistent state enters the architecture. ## DigitalOcean App Platform overview DigitalOcean App Platform is a fully managed PaaS that builds and deploys applications from Git repositories or container images while DigitalOcean manages the underlying infrastructure. It supports web services, static sites, workers, cron jobs, deployment jobs, functions, and database integrations. Current source options include GitHub, GitLab, and Bitbucket repositories plus images from DigitalOcean Container Registry, Docker Hub, and GitHub Container Registry. Apps can be managed through the control panel, API, `doctl`, Terraform, and a YAML App Spec. DigitalOcean offers shared and dedicated CPU plans. Shared dynamic plans start at **$5/month for 1 shared vCPU / 512 MiB**, while dedicated plans start at **$29/month for 1 dedicated vCPU / 512 MiB**. Request-based autoscaling works with shared and dedicated CPU plans and supports up to **100 containers**; CPU-based autoscaling requires dedicated CPU and, like fixed scaling, can reach **250 containers**. DigitalOcean also provides a free static-site tier for up to **3 apps** containing only static-site components, with **1 GiB outbound transfer per app**. Its strongest advantages in this comparison are 12 deployment regions, a 99.95% App Platform component SLA, multiple source providers, dedicated CPU options, autoscaling, and integration with the wider DigitalOcean cloud. Its clearest constraint is durable local state. App Platform does not support volumes, and the local filesystem is limited to **4 GiB** and is ephemeral across deployments and other container replacements. Persistent data therefore belongs in services such as Spaces or DigitalOcean Managed Databases. ## Raff overview [Raff Apps](/products/app-platform) is Raff's managed application platform for deploying source code and containers without administering the operating system beneath them. It supports GitHub push-to-deploy, buildpacks, Dockerfiles, existing container images, and full Docker Compose imports. Raff Apps supports public web services, private services, long-running workers, timezone-aware cron jobs, one-off jobs, pull-request previews, persistent application volumes, immutable revisions, one-click rollback, and scale-to-zero behavior. Applications can connect to Raff Managed Databases for PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, plus object storage, VMs, private networking, Kubernetes, and Functions. Current service tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Runtime is billed per second against each published monthly ceiling. Public application egress and Apps team seats cost $0, and the spend cap is enabled by default. Raff currently exposes one public region, `us-east`, which is a real limitation for teams that require placement closer to users elsewhere. Raff reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. On August 16, 2026, Raff was rated **4.5/5**, with G2 at 4.6/5. ## DigitalOcean App Platform pricing vs Raff pricing DigitalOcean bills each App Platform component according to its container size and replica count. Apps are billed by the second with a one-minute minimum. Raff also prorates Apps runtime by the second but caps each service at its published monthly price. | Buying position | Raff Apps | DigitalOcean App Platform | Decision signal | |---|---:|---:|---| | Entry dynamic app | Micro — 0.25 vCPU / 512 MB / $3 | 1 shared vCPU / 512 MiB / $5 | DigitalOcean includes more listed shared CPU; Raff is $2 lower | | 1 GB dynamic | Starter — 0.5 vCPU / 1 GB / $6.99 | 1 shared vCPU / 1 GiB / $12 scalable | DigitalOcean adds manual horizontal scaling | | 1 vCPU / 2 GB | Standard — $16.99 | 1 shared vCPU / 2 GiB — $25 | Closely matched published CPU/RAM totals | | 2 vCPU / 4 GB | Pro — $27.99 | 2 shared vCPU / 4 GiB — $50 | Raff is $22.01 lower before DO overage | | Static sites | No equivalent published free Apps tier | Up to 3 static-only apps free | DigitalOcean wins for qualifying static-only projects | **Comparison class:** these rows compare published CPU, memory, and price positions, not measured application performance. DigitalOcean distinguishes shared and dedicated CPU scheduling; Raff Apps does not publish the same shared-versus-dedicated labels, so resource counts alone should not be treated as benchmark equivalence. ### Bandwidth cost math DigitalOcean's 2 shared vCPU / 4 GiB plan includes **250 GiB** outbound transfer. Additional outbound transfer costs **$0.02/GiB**, and App Platform allowance and usage are pooled across apps at the team level. Raff Apps public egress is $0. | Monthly outbound traffic | Raff Pro | DigitalOcean 2 shared vCPU / 4 GiB | |---:|---:|---:| | 250 GiB | $27.99 | $50.00 | | 500 GiB | $27.99 | $55.00 | | 1 TiB | $27.99 | $65.48 | | 2 TiB | $27.99 | $85.96 | | 5 TiB | $27.99 | $147.40 | The DigitalOcean examples assume no unused transfer allowance from other App Platform components in the same team pool. Pooling can reduce overage for teams whose other apps use less than their accumulated allowance. ### Automated backups DigitalOcean App Platform rollback and data backup are separate systems. App Platform can roll an app's **code, configuration, and App Spec** back to one of the **10 most recent successful deployments**, but DigitalOcean explicitly states that this rollback does not restore database data. DigitalOcean Managed Databases include **daily backups with point-in-time recovery**; PostgreSQL and MySQL documentation currently describes PITR within the previous **7 days**. App Platform's 4 GiB local filesystem is ephemeral and should not be treated as a backup target. Raff likewise separates application revision rollback from durable-data recovery. Persistent volumes, managed databases, and object storage need recovery policies appropriate to the state they hold; one-click application rollback does not substitute for a database or file backup. ### Hidden platform costs DigitalOcean dedicated egress IPs are billed per second up to **$25/month**. Development databases cost **$7/month per 512 MB**, while production managed databases are separate resources. DigitalOcean can still be the better buy when its 12-region footprint, autoscaling, dedicated CPU, or source-provider integrations eliminate other operational work. :::cta Deploy an App Now Deploy web services, workers, cron jobs, and Docker Compose stacks with managed runtime infrastructure. ::: ## Bandwidth and transfer policy Every current DigitalOcean App Platform compute plan includes an outbound-transfer allowance, from **50 GiB** on the $5 shared plan to **900 GiB** on the largest listed dedicated plan. Additional outbound transfer is $0.02/GiB and inbound transfer is free. Transfer allowance and usage are pooled across App Platform apps at the team level and do not roll over. DigitalOcean currently notes that users can view ingress bandwidth for individual apps but cannot directly view accrued App Platform transfer allowance or cumulative App Platform usage. That makes the final monthly charge more dependent on team-wide traffic patterns than a single component's plan card suggests. Raff Apps prices public application egress at $0. For bandwidth-heavy APIs, downloads, or traffic with large seasonal swings, that removes a variable from the application bill. DigitalOcean remains stronger when global regional placement is more valuable than the transfer difference or when pooled allowances cover the team's normal traffic. ## Feature comparison: DigitalOcean App Platform vs Raff | Feature | Raff Apps | DigitalOcean App Platform | |---|---|---| | Dynamic entry price | $3/month | $5/month | | Source providers | GitHub | GitHub, GitLab, Bitbucket | | Dockerfile / existing image | Yes | Yes | | Docker Compose | Full stack import | App components are modeled through App Platform configuration/App Spec | | Public regions | 1: `us-east` | 12 | | Free static tier | No equivalent published Apps tier | Up to 3 static-only apps | | Persistent app volumes | Yes | No | | App local filesystem | 2–80 GB ephemeral disk by Raff tier | 4 GiB ephemeral limit | | Public application egress | $0 | Included allowance, then $0.02/GiB | | Request-based autoscaling | Not published as a Raff Apps control | Shared and dedicated services, up to 100 containers | | CPU autoscaling | Not published as a Raff Apps control | Dedicated plans, up to 250 containers | | Dedicated CPU app plans | Not separately labeled | Yes, from $29/month | | Deployment rollback | Immutable revisions, one-click rollback | 10 most recent successful deployments | | Managed data options | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | PostgreSQL, MySQL, Valkey, MongoDB, Kafka, OpenSearch | | SLA | 99.9% platform SLA | 99.95% per App Platform component instance | DigitalOcean wins clearly on region count, Git-provider breadth, dedicated CPU choices, free static hosting, autoscaling controls, and the higher numerical App Platform SLA. Raff wins on lower listed prices at the matched 1 vCPU / 2 GB and 2 vCPU / 4 GB positions, persistent application volumes, full Compose imports, and $0 public egress. ## Features and reliability: Raff vs DigitalOcean App Platform This comparison includes **0 controlled Raff-versus-DigitalOcean App Platform application benchmarks**, so it does not declare either platform faster. DigitalOcean publishes both shared and dedicated CPU app plans, while Raff Apps does not expose the same CPU-class labels; a responsible benchmark would need matched CPU scheduling, region, memory, application image, database placement, caching, concurrency, and repeated test windows. ### Reliability commitment DigitalOcean commits to **99.95% monthly uptime for each App Platform component instance**. Raff publishes a **99.9% platform SLA**. On the numerical commitment alone, DigitalOcean has the stronger SLA. DigitalOcean also documents high availability for apps running **two or more containers**. That is an important strength for teams prepared to pay for multiple replicas. A one-container deployment still leaves the application at one runtime instance, even though the platform's component SLA applies. ### Persistent state DigitalOcean App Platform does not support volumes. Its local filesystem is **4 GiB and ephemeral**, so production files must be externalized to Spaces, Managed Databases, or another durable service. That architecture is often desirable for horizontally scaled apps, but it can require application changes for software that expects local persistent files. Raff Apps supports persistent application volumes. This makes lift-and-shift deployment easier for some stateful applications, though horizontally scaled services still need a deliberate shared-data design rather than assuming one attached filesystem solves multi-instance state. ### Autoscaling and capacity DigitalOcean has the more mature documented autoscaling surface. Request-based autoscaling can use requests per second or P95 request duration on shared or dedicated services, with a maximum of **100 containers**. CPU-based autoscaling requires dedicated CPU and can scale to **250 containers**. Request-based autoscaling and Scale to Zero cannot be enabled on the same service. Raff's public Apps model is simpler: teams choose a service tier, can use scale-to-zero behavior, and work within the platform's managed service abstraction. Teams that specifically need request-target or CPU-target autoscaling should treat DigitalOcean as the stronger option. ### Release and data recovery DigitalOcean can roll back to one of the **10 most recent successful deployments**, restoring code, configuration, and App Spec while leaving database data untouched. Raff uses immutable revisions and one-click application rollback. Both models require separate database and file recovery planning when a release includes state changes. ### Platform breadth DigitalOcean's wider cloud catalog is a genuine operational advantage for teams already using Droplets, DOKS, Spaces, Container Registry, Functions, or its Managed Databases. Raff offers a smaller integrated surface across Apps, VMs, managed databases, object storage, Kubernetes, Functions, and private networking. ## When you should choose DigitalOcean App Platform over Raff Choose DigitalOcean App Platform when: - **Regional placement is mandatory.** DigitalOcean App Platform exposes **12 regions** versus Raff Apps' single public `us-east` region. - **Autoscaling is a core requirement.** Request-based rules can scale to **100 containers**, while fixed and CPU-based scaling can reach **250**. - **GitLab or Bitbucket is required.** DigitalOcean supports both directly in addition to GitHub. - **Dedicated CPU app containers matter.** Current dedicated plans start at **$29/month** for 1 dedicated vCPU / 512 MiB. - **Static-only projects should be free.** DigitalOcean allows up to **3 qualifying static-only apps** at $0. - **A higher numerical SLA is required.** DigitalOcean commits to **99.95%** per App Platform component instance. - **The team already uses DigitalOcean.** App Platform integrates with its databases, Spaces, registry, Functions, DOKS, API, `doctl`, and Terraform workflows. ## When you should choose Raff over DigitalOcean App Platform Choose Raff Apps when: - **Comparable service prices matter.** Raff Standard is **$16.99** at 1 vCPU / 2 GB versus DigitalOcean's **$25** shared plan; Raff Pro is **$27.99** at 2 vCPU / 4 GB versus **$50**. - **Public egress is material.** Raff Apps charges **$0** for public application egress instead of $0.02/GiB after DigitalOcean's pooled allowance. - **Persistent app volumes are required.** DigitalOcean App Platform provides **0 persistent volumes** and a 4 GiB ephemeral filesystem. - **Docker Compose is the deployment artifact.** Raff can import a **full Compose stack** instead of translating services into platform-specific components. - **A default cost guardrail matters.** Raff Apps uses published monthly ceilings and enables the spend cap by default. - **Managed data should stay in the same compact workflow.** Raff provides **5 managed data engines**: PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka. - **The workload fits `us-east`.** DigitalOcean's 12-region advantage has little value if one eastern-US deployment location already meets latency and architecture requirements. Raff currently supports **3,000+ customers and 15,000+ production VMs**. For adjacent app-platform choices, compare [Render and Raff](/learn/compare/render-alternative), [Coolify and Raff](/learn/compare/coolify-alternative), and [Netlify and Raff](/learn/compare/netlify-alternative). ## Migrating from DigitalOcean App Platform to Raff 1. **Inventory the App Platform app.** Export the App Spec and record services, static sites, workers, jobs, functions, databases, repositories, branches, build/run commands, environment-variable scopes, domains, routes, health checks, replica counts, autoscaling, region, egress IPs, logs, and alerts. **Gotcha:** App Spec fields are platform configuration, not a portable Compose file. 2. **Map components to Raff services.** Move public HTTP components to web services, internal APIs to private services, consumers to workers, schedules to cron jobs, and administrative commands to one-off jobs. 3. **Choose a portable build source.** Use GitHub, a Dockerfile, a prebuilt image, buildpacks, or Docker Compose. **Gotcha:** GitLab and Bitbucket source workflows need a GitHub mirror or an external image-building pipeline before direct Raff deployment. 4. **Move durable state.** Export managed databases with native tools and copy Spaces objects to Raff Object Storage or another S3-compatible destination. Do not plan around App Platform's local filesystem because it is ephemeral. 5. **Recreate configuration and verify.** Add secrets, routes, domains, health checks, private bindings, persistent volumes, managed data services, callbacks, and external allowlists. Test on a temporary hostname and perform a restore rehearsal. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, freeze writes where necessary, complete the final data sync, update DNS and callback URLs, monitor production, and retain the DigitalOcean app until the rollback window closes. Stateless source/image components are usually the easiest part of this migration. Stateful databases, object storage, App Spec assumptions, source-provider integrations, autoscaling rules, egress IP allowlists, and region-specific dependencies create most of the migration risk. ## About DigitalOcean App Platform [DigitalOcean App Platform](https://www.digitalocean.com/products/app-platform) is a managed PaaS from **DigitalOcean Holdings, Inc.**, whose principal executive offices are in New York. DigitalOcean was founded in **2012**. App Platform deploys source code and container images across 12 regions with managed builds, routing, scaling, monitoring, and integrations into DigitalOcean's broader cloud portfolio. ## Conclusion: DigitalOcean App Platform or Raff? The DigitalOcean-App-Platform-versus-Raff decision resolves across four measured axes: cost boundary, regional/scaling reach, durable state, and platform operations. - **Cost boundary:** Raff starts at **$3/month**, is $27.99 at 2 vCPU / 4 GB, and charges $0 public app egress; DigitalOcean starts dynamic compute at **$5/month**, is $50 at 2 shared vCPU / 4 GiB, and meters transfer above plan allowances. - **Regional and scaling reach:** DigitalOcean provides **12 regions**, request-based autoscaling to **100 containers**, CPU/fixed scaling to **250**, and dedicated CPU plans; Raff exposes one public `us-east` Apps region and a simpler service model. - **Durable state:** Raff supports persistent application volumes; DigitalOcean App Platform supports **0 volumes** and limits local storage to a 4 GiB ephemeral filesystem, encouraging state to live in databases or object storage. - **Platform operations:** DigitalOcean offers GitHub, GitLab, Bitbucket, App Spec, `doctl`, Terraform, and a 99.95% component SLA; Raff emphasizes full Compose import, service ceilings, a default spend cap, and a 99.9% platform SLA. Choose DigitalOcean App Platform when multi-region placement, autoscaling, dedicated CPU, GitLab/Bitbucket, or DigitalOcean-native operations are requirements. Choose Raff when a `us-east` deployment can trade geographic breadth for lower comparable service prices, persistent volumes, Docker Compose portability, $0 public egress, and a tighter billing model. Raff currently reports **3,000+ customers, 15,000+ production VMs, Trustpilot 4.5/5, G2 4.6/5, and a 99.9% platform SLA**. --- ### DigitalOcean Kubernetes Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/digitalocean-kubernetes-alternative Description: Considering DigitalOcean Kubernetes? Raff is $13.99/mo for 2 vCPU/4 GB with $0 egress; DOKS is $24/mo with broader regions. Raff wins on lower comparable worker prices, a $30 HA control-plane add-on, $0 public egress, $0.08/GB-month cluster storage, and a simpler small-team cost model. DigitalOcean Kubernetes wins on broader regional placement, dedicated CPU and GPU node choices, mature DigitalOcean integrations, and a 99.95% HA control-plane SLA. Choose DigitalOcean Kubernetes when region choice or specialized worker classes are requirements; choose Raff when `us-east`, lower published worker prices, and predictable transfer costs fit the workload. Two 2 vCPU / 4 GB workers with HA cost $57.98/month on Raff versus $88/month on DigitalOcean before storage, load balancers, and other attached services. DigitalOcean Kubernetes and Raff both remove day-to-day control-plane administration while leaving application architecture, workload sizing, policies, and data protection with the customer. The standard control plane is $0 on both platforms, but their surrounding economics differ: Raff's 2 vCPU / 4 GB worker is $13.99/month, while DigitalOcean's Basic 2 vCPU / 4 GiB worker is $24/month. DOKS offers a wider infrastructure catalog and geographic footprint; Raff focuses on one public `us-east` region, $0 public egress, lower cluster-storage pricing, and a smaller operating surface for teams that do not need every cloud primitive. ## DigitalOcean Kubernetes vs Raff: which is right for you? DigitalOcean Kubernetes is the stronger choice for global placement, specialized node classes, and DigitalOcean-native infrastructure. Raff is the stronger choice when the cluster can run in `us-east` and monthly worker, HA, storage, and transfer costs need to stay easy to forecast. | Decision factor | Choose Raff | Choose DigitalOcean Kubernetes | |---|---|---| | 2 vCPU / 4 GB worker | $13.99/month | $24/month Basic | | HA control plane | $30/month | $40/month | | Geography | `us-east` fits | You need broader DOKS region choice | | Worker classes | General Kubernetes worker tiers fit | Dedicated CPU, storage-optimized, or GPU nodes are required | | Public egress | You want $0 public egress | Pooled node transfer plus $0.01/GiB overage fits | | Persistent storage | $0.08/GB-month cluster storage fits | DigitalOcean Volumes at $0.10/GiB-month fit | | Operations | Built-in Raff cluster workflow is enough | API, `doctl`, Terraform, registry, VPC, and wider DigitalOcean integrations matter | A specific first-hand decision rule from Raff's infrastructure work is to price the cluster around the steady worker floor before adding optional platform services. For a small team, two always-on workers, HA, storage, and outbound traffic usually explain more of the bill than the nominal $0 control plane. ## DigitalOcean Kubernetes overview [DigitalOcean Kubernetes](https://www.digitalocean.com/products/kubernetes), or DOKS, is DigitalOcean's managed Kubernetes service. DigitalOcean operates the Kubernetes control plane while customers manage node pools, workloads, policies, application availability, persistent data, and recovery design. DOKS worker nodes use DigitalOcean Droplet sizes. Current Basic Regular prices include **$12/month for 1 vCPU / 2 GiB**, **$24/month for 2 vCPU / 4 GiB**, and **$48/month for 4 vCPU / 8 GiB**. DigitalOcean also offers dedicated CPU, memory-focused, storage-focused, and GPU compute options for teams whose workloads need different node characteristics. The standard DOKS control plane is free. The HA control plane costs **$40/month** and carries a **99.95% control-plane SLA**. DOKS supports node-pool autoscaling, automatic version workflows, VPC networking, DigitalOcean Volumes, DigitalOcean Load Balancers, Container Registry, API access, `doctl`, and Terraform. DigitalOcean's strongest advantages are its broader regional footprint, specialized worker classes, mature automation tooling, and the ability to connect Kubernetes to a larger DigitalOcean product catalog without leaving the provider. ## Raff overview [Raff Kubernetes](/products/kubernetes) is a managed Kubernetes service with a free standard control plane, optional three-master HA, worker-node autoscaling, built-in monitoring, managed cluster networking, and a deployment workflow designed for small teams and operators that want Kubernetes without maintaining the control plane themselves. Current worker tiers are: | Worker | vCPU | RAM | SSD | Monthly price | |---|---:|---:|---:|---:| | K8s Starter | 1 | 2 GB | 50 GB | $9.99 | | K8s Standard | 2 | 4 GB | 80 GB | $13.99 | | K8s Performance | 4 | 8 GB | 120 GB | $30.99 | | K8s High Memory | 8 | 16 GB | 180 GB | $59.99 | | K8s Large | 8 | 32 GB | 240 GB | $115.99 | | K8s Scale | 16 | 64 GB | 480 GB | $229.99 | The standard control plane costs **$0**. Optional HA with three masters and etcd quorum costs **$30/month**. Cluster storage is **$0.08/GB-month**, with a 10 GB minimum, 100 GB default, and 1 TB maximum; replicated cluster storage requires at least two nodes. Cluster-to-storage traffic is not metered. Raff Kubernetes prices public egress at **$0**. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. Raff's Trustpilot rating was verified at **4.5/5** on August 16, 2026, with G2 at 4.6/5. Raff gives up DigitalOcean's geographic and machine-class breadth in exchange for a more compact `us-east` operating and billing model. ## DigitalOcean Kubernetes pricing vs Raff pricing Both services charge $0 for the standard managed control plane. The meaningful price comparison therefore starts with worker nodes and then adds HA, storage, outbound traffic, load balancing, databases, and any other services the workload actually uses. | Buying position | Raff Kubernetes | DigitalOcean Kubernetes | Decision signal | |---|---:|---:|---| | 1 vCPU / 2 GB worker | $9.99/month | $12/month Basic | Raff is $2.01 lower | | 2 vCPU / 4 GB worker | $13.99/month | $24/month Basic | Raff is $10.01 lower | | 4 vCPU / 8 GB worker | $30.99/month | $48/month Basic | Raff is $17.01 lower | | HA control plane | $30/month | $40/month | Raff add-on is $10 lower | | Persistent storage | $0.08/GB-month | $0.10/GiB-month | Raff has the lower published unit price | **Comparison class:** these rows compare published resource shapes and prices, not measured Kubernetes performance. DigitalOcean Basic workers use a shared-CPU Droplet class; Raff does not publish an identical DigitalOcean CPU-scheduling taxonomy, so vCPU counts alone are not benchmark equivalence. A two-node 2 vCPU / 4 GB cluster costs **$27.98/month** on Raff and **$48/month** on DOKS before HA. With HA enabled, the totals become **$57.98** and **$88** respectively before storage and surrounding services. ### Bandwidth cost math DigitalOcean pools outbound-transfer allowances from worker nodes and charges **$0.01/GiB** above the pooled account allowance. A current $12 Basic worker includes 2,000 GiB, while the $24 2 vCPU / 4 GiB Basic worker includes 4,000 GiB of transfer. Raff Kubernetes prices public egress at $0. For a two-node DOKS cluster using the $24 worker shape, the two nodes contribute **8,000 GiB** of listed transfer allowance before account-level pooling effects from other eligible resources. | Public outbound traffic | Raff egress charge | DOKS overage from an 8,000 GiB two-worker allowance | |---:|---:|---:| | 4,000 GiB | $0 | $0 | | 8,000 GiB | $0 | $0 | | 10,000 GiB | $0 | $20 | | 20,000 GiB | $0 | $120 | The DOKS examples isolate worker transfer and overage. A real DigitalOcean account can pool eligible transfer across resources, so the invoice can differ from a single-cluster example. ### Automated backups Neither managed control plane should be treated as an automatic backup of Kubernetes application data. DOKS manages the control plane, but customers still need a recovery plan for PersistentVolume data, databases, object storage, manifests, secrets, and application-level state. DigitalOcean Volumes used by Kubernetes cost **$0.10/GiB-month** and support snapshots, but snapshots are a separately managed protection mechanism rather than a blanket DOKS workload-backup policy. Teams running stateful workloads should define snapshot or backup schedules and test restores instead of assuming control-plane HA protects data. Raff follows the same separation of responsibilities. Managed control-plane availability does not replace workload backups. Raff cluster storage, managed databases, object storage, and application configuration each need recovery procedures appropriate to the state they hold. :::cta cluster Deploy a Raff Kubernetes cluster with a $0 standard control plane; add three-master HA for $30/month when required. ::: ## Bandwidth and transfer policy Raff Kubernetes prices public egress at **$0**, and cluster-to-Raff-cluster-storage traffic is not metered. That makes outbound traffic a fixed-cost decision from the Kubernetes side rather than an additional per-GiB line item. DigitalOcean includes outbound-transfer allowances with worker Droplets and pools eligible transfer at the account level. Basic worker allowances range by selected size; the current 2 vCPU / 4 GiB Basic size includes **4,000 GiB**. Usage above the pooled allowance is billed at **$0.01/GiB**. DigitalOcean's model can work well when workloads stay inside pooled allowances. Raff's model is simpler for APIs, downloads, media, package distribution, or other workloads where outbound transfer can be large or uneven from month to month. ## Feature comparison: DigitalOcean Kubernetes vs Raff | Feature | Raff Kubernetes | DigitalOcean Kubernetes | |---|---|---| | Standard control plane | $0 | $0 | | HA control plane | $30/month | $40/month | | 2 vCPU / 4 GB worker | $13.99/month | $24/month Basic | | Node-pool autoscaling | Yes | Yes | | Dedicated CPU worker class | No separately published class | Yes | | GPU workers | No published Kubernetes GPU tier | Yes | | Public regions | 1 — `us-east` | Broader global DOKS footprint | | Public egress | $0 | Pooled allowance, then $0.01/GiB | | Persistent storage | Raff cluster storage | DigitalOcean Volumes through CSI | | Storage unit price | $0.08/GB-month | $0.10/GiB-month | | Full `kubectl` workflow | Yes | Yes | | Monitoring | Built into Raff cluster workflow | DigitalOcean monitoring plus user-selected tooling | | API / CLI / Terraform | Raff platform workflows | API, `doctl`, Terraform | | Container registry | Compatible external registries | Native DigitalOcean Container Registry integration | | Managed data options | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | DigitalOcean Managed Databases catalog | DigitalOcean wins on region choice, specialized workers, GPU availability, native registry integration, and mature DigitalOcean automation. Raff wins on the published worker examples above, HA add-on price, cluster-storage unit price, and $0 public Kubernetes egress. ## Features and reliability: Raff vs DigitalOcean Kubernetes This comparison includes **0 controlled Raff-versus-DigitalOcean Kubernetes workload benchmarks**, so it does not declare either platform faster. A valid Kubernetes performance comparison would require matched CPU scheduling, Kubernetes versions, node counts, CNI behavior, storage paths, regions, Pod requests, application images, and repeated workload runs. ### Control-plane reliability DigitalOcean's HA control plane carries a **99.95% SLA**, which is a stronger numerical control-plane commitment than Raff's **99.9% platform SLA**. DigitalOcean should be preferred when that specific contractual figure is a hard requirement. Raff's HA option uses three masters with etcd quorum and costs $30/month. DigitalOcean's HA control plane costs $40/month. The lower Raff price does not make application workloads automatically highly available: replica count, Pod disruption behavior, worker capacity, ingress, storage, and external dependencies still determine application resilience. ### Worker and scaling choices DigitalOcean has the wider worker catalog. DOKS can use shared Basic Droplets as well as dedicated and specialized compute families, including GPU options. This is a genuine advantage for workloads that need stronger CPU isolation, memory-heavy nodes, local-storage characteristics, or accelerators. Raff exposes a smaller set of Kubernetes worker tiers from 1 vCPU / 2 GB through 16 vCPU / 64 GB. That narrower catalog makes ordinary small-team sizing simpler but does not cover every specialized DigitalOcean use case. ### Stateful recovery DigitalOcean Volumes and Raff cluster storage both persist independently of an individual Pod, but persistence is not the same as backup. Kubernetes operators still need to define what is copied, how often it is copied, where recovery data lives, how databases are made consistent, and how restore procedures are tested. ### Trust and operating evidence DigitalOcean has the deeper public operating history and review base. Its Trustpilot profile was **4.6/5** when checked for this refresh. Raff's current Trustpilot signal is **4.5/5**, alongside **3,000+ customers and 15,000+ production VMs**. The much larger DigitalOcean review sample is a genuine trust advantage; neither review score should replace architecture or SLA evaluation. ## When you should choose DigitalOcean Kubernetes over Raff Choose DigitalOcean Kubernetes when: - **Broader region choice is required.** DOKS supports deployment beyond Raff's single public `us-east` region. - **Dedicated CPU nodes matter.** DigitalOcean offers dedicated compute families in addition to shared Basic workers. - **GPU workers are required.** DigitalOcean offers GPU infrastructure that Raff Kubernetes does not currently publish. - **A 99.95% HA control-plane SLA is mandatory.** Raff publishes a 99.9% platform SLA. - **DigitalOcean-native integrations reduce work.** DOKS connects naturally to VPCs, Container Registry, Volumes, Load Balancers, Managed Databases, API, `doctl`, and Terraform. - **A larger public review history matters.** DigitalOcean's Trustpilot profile currently contains versus Raff's 16. - **Your pooled transfer allowance is sufficient.** DOKS overage starts only after eligible account-level allowances are exhausted. ## When you should choose Raff over DigitalOcean Kubernetes Choose Raff Kubernetes when: - **Published worker price matters.** Raff is $13.99/month at 2 vCPU / 4 GB versus $24/month for the DOKS Basic shape. - **HA cost matters.** Raff's three-master HA add-on is $30/month versus $40/month for DOKS HA control plane. - **Public egress should stay at $0.** DOKS charges $0.01/GiB after pooled allowances. - **Cluster storage cost matters.** Raff cluster storage is $0.08/GB-month versus $0.10/GiB-month for DigitalOcean Volumes. - **The workload fits `us-east`.** DigitalOcean's broader region map adds little if one eastern-U.S. region already satisfies the architecture. - **A smaller product surface is preferable.** Raff combines Kubernetes with VMs, managed databases, object storage, Apps, Functions, and private networking without requiring the team to choose among as many compute families. - **Built-in cluster monitoring fits the operating model.** Raff packages monitoring into its managed Kubernetes workflow. Raff currently reports **3,000+ customers and 15,000+ production VMs**. For the broader decision, read [Kubernetes vs Docker Compose for Small Teams](/learn/guides/kubernetes-vs-docker-compose-small-teams) and [Kubernetes Cost Optimization](/learn/guides/kubernetes-cost-optimization-startups). ## Migrating from DigitalOcean Kubernetes to Raff 1. **Inventory the DOKS cluster.** Record Kubernetes version, node pools, autoscaling limits, namespaces, Helm releases, CRDs, ingress controllers, DigitalOcean Load Balancers, Volumes, storage classes, registry integrations, secrets, policies, DNS, and external allowlists. 2. **Create the Raff target cluster.** Select the control-plane model, worker sizes, node counts, autoscaling ranges, cluster storage, private networking, and monitoring configuration. 3. **Replace provider-specific integrations.** Convert DigitalOcean storage classes, load-balancer annotations, registry credentials, VPC assumptions, and CSI/CCM dependencies to the Raff equivalents. **Gotcha:** provider-specific Kubernetes annotations can survive YAML exports and fail silently on the target platform. 4. **Move persistent data.** Use database-native exports, application replication, backup tools, or verified copy workflows for persistent volumes. **Gotcha:** Kubernetes manifests recreate resource definitions; they do not contain the application data stored inside volumes or external databases. 5. **Deploy and verify workloads.** Apply CRDs and operators first, then namespaces, configuration, workloads, services, ingress, policies, storage, and observability. Test readiness, autoscaling, jobs, restore procedures, and failure behavior on the target cluster. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, perform the final state synchronization, update DNS and allowlists, monitor production, and keep DOKS available until the rollback window closes. Stateless manifests and Helm releases are usually the easiest part of a DOKS-to-Raff move. Persistent volumes, DigitalOcean-specific annotations, registry authentication, external IP allowlists, autoscaler assumptions, and version-dependent CRDs create most of the migration risk. ## About DigitalOcean Kubernetes [DigitalOcean Kubernetes](https://www.digitalocean.com/products/kubernetes) is the managed Kubernetes service from **DigitalOcean Holdings, Inc.**, a publicly traded cloud company headquartered in New York. DOKS provides a managed control plane, node pools, autoscaling, persistent-volume integration, regional deployment, and connections to DigitalOcean networking, registry, database, API, CLI, and Terraform workflows. ## Conclusion: DigitalOcean Kubernetes or Raff? The DigitalOcean-Kubernetes-versus-Raff decision resolves across four measured axes: cluster cost, infrastructure breadth, reliability commitments, and transfer/storage economics. - **Cluster cost:** two 2 vCPU / 4 GB workers plus HA total **$57.98/month on Raff** versus **$88/month on DOKS** before storage and surrounding services. - **Infrastructure breadth:** DigitalOcean offers broader regions, dedicated CPU classes, GPU nodes, and a larger native cloud catalog; Raff deliberately exposes a smaller Kubernetes footprint in `us-east`. - **Reliability:** DOKS has a **99.95% HA control-plane SLA**; Raff publishes a **99.9% platform SLA** and offers three-master HA for $30/month. - **Transfer and storage:** Raff public Kubernetes egress is **$0** and cluster storage is **$0.08/GB-month**; DOKS uses pooled transfer with $0.01/GiB overage and DigitalOcean Volumes at $0.10/GiB-month. Choose DigitalOcean Kubernetes when geographic reach, specialized compute, DigitalOcean-native integrations, or the 99.95% HA control-plane SLA are hard requirements. Choose Raff when `us-east` is sufficient and lower published worker/HA/storage prices plus $0 public egress make the cluster easier to budget. Raff currently reports **3,000+ customers, 15,000+ production VMs, Trustpilot 4.5/5, G2 4.6/5, and a 99.9% platform SLA**. Continue with [Kubernetes vs Docker Compose for Small Teams](/learn/guides/kubernetes-vs-docker-compose-small-teams), [Kubernetes Cost Optimization](/learn/guides/kubernetes-cost-optimization-startups), and [K3s vs Kubernetes](/learn/guides/k3s-vs-full-kubernetes-cluster-model). --- ### UpCloud Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-upcloud Description: Considering UpCloud? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe against UpCloud Premium at about $30.14 with 50 GB. UpCloud is a Finnish cloud provider that has sold infrastructure since 2011, with 15 data centers across four continents and a 99.999% uptime SLA on its production tiers. Raff Technologies is a US cloud provider running 15,000+ VMs for 3,000+ customers from a single us-east region. Both sell shared-vCPU cloud servers, managed databases, managed Kubernetes and object storage, so this is a platform comparison rather than a server comparison. At the matched production shape, Raff General Purpose is $13.99/month for 2 vCPU, 4 GB and 80 GB NVMe; the equivalent UpCloud Premium plan is about $30.14 with 50 GB. ## UpCloud VPS and Raff at a glance **UpCloud** sells three cloud-server lines. **Starter** is the budget tier on previous-generation AMD CPUs and Standard SSD, from €3/month with a 99.99% SLA. **Premium** is the production tier on newer AMD CPUs with MaxIOPS storage included, from €5/month at 99.999%. **Cloud Native** decouples compute from storage, from €12/month, and stops charging compute while a server is stopped. UpCloud publishes no CPU-dedication guarantee on any of the three — its only dedicated-hardware product is Private Cloud, from €3,190/month. Around the servers sits a substantial catalog: Managed Databases for PostgreSQL and MySQL from €9/month, Valkey from €8/month and OpenSearch from €100/month; Managed Kubernetes with a free development control plane and €60/month for production; block storage in MaxIOPS, Standard and Archive tiers; managed NFS file storage; object storage; load balancers; NAT and VPN gateways; GPU servers with NVIDIA L4 through B200; and Private Cloud on dedicated hardware. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.9% uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Raff's platform covers managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. One structural difference is worth stating up front: **UpCloud has 15 regions to Raff's one.** If your users sit outside North America, that matters more than anything else on this page. ## UpCloud VPS pricing vs Raff pricing UpCloud publishes no CPU-dedication guarantee on Starter, Premium or Cloud Native, which makes **Raff General Purpose the like-for-like match** and means Raff CPU-Optimized has no UpCloud counterpart short of Private Cloud. **Premium is the fair comparison**: both include storage in the plan price, both are the production tier, both carry the vendor's top SLA. | Shape | Raff General Purpose | UpCloud Premium | |---|---|---| | 1 vCPU / 1 GB | **$4.99** — 25 GB NVMe | €5 ≈ $5.80 — 25 GB MaxIOPS | | 2 vCPU / 2 GB | **$8.49** — 40 GB NVMe | €16 ≈ $18.55 — 50 GB MaxIOPS | | 2 vCPU / 4 GB | **$13.99** — 80 GB NVMe | €26 ≈ $30.14 — 50 GB MaxIOPS | | 2 vCPU / 8 GB | **$27.99** — 160 GB NVMe | €38 ≈ $44.05 — 100 GB MaxIOPS | | 4 vCPU / 8 GB | **$30.99** — 160 GB NVMe | €52 ≈ $60.28 — 100 GB MaxIOPS | | 4 vCPU / 16 GB | **$52.99** — 320 GB NVMe | €92 ≈ $106.66 — 150 GB MaxIOPS | | 8 vCPU / 16 GB | **$59.99** — 320 GB NVMe | €148 ≈ $171.58 — 200 GB MaxIOPS | | 8 vCPU / 32 GB | **$115.99** — 640 GB NVMe | €192 ≈ $222.59 — 200 GB MaxIOPS | *Raff General Purpose against UpCloud Premium — both shared vCPU with storage included. UpCloud prices read 2026-08-18, exclude local taxes, converted at €1 = $1.1593 (ECB, 2026-08-17).* Raff is **37% to 65% cheaper at every matched tier above the entry shape, and includes more storage at every one of them** — 320 GB against 200 GB at 8 vCPU / 16 GB, 640 GB against 200 GB at 8 vCPU / 32 GB. Only the 1 vCPU / 1 GB entry is close, and Raff is still 14% lower there. ### UpCloud's Starter line for reference Starter is UpCloud's budget tier, and it is genuinely cheaper than Raff: | Shape | Raff General Purpose | UpCloud Starter | |---|---|---| | 1 vCPU / 1 GB | $4.99 — 25 GB | **€3 ≈ $3.48** — 10 GB | | 2 vCPU / 4 GB | $13.99 — 80 GB | **€12 ≈ $13.91** — 30 GB | | 2 vCPU / 8 GB | $27.99 — 160 GB | **€18 ≈ $20.87** — 40 GB | | 4 vCPU / 16 GB | $52.99 — 320 GB | **€28 ≈ $32.46** — 50 GB | What Starter gives up is stated by UpCloud itself: **previous-generation AMD CPUs**, Standard SSD rather than MaxIOPS, a **99.99% SLA instead of 99.999%**, and 250–500 Mbit/s rather than 1000 Mbps. Storage is three to six times smaller at every tier. If your workload fits that envelope, Starter is the cheaper buy and this page will not argue otherwise. ### Cloud Native — compute and storage billed separately Cloud Native decouples the two: compute from €12/month for 4 GB / 1 core, with storage added at €0.220/GB-month for MaxIOPS, €0.085 for Standard, or €0.056 for Archive. A 2-core, 4 GB Cloud Native server with 80 GB Standard storage works out at about €21.80 ≈ $25.27/month against Raff's $13.99 with 80 GB included. The model is useful when storage and compute scale independently, or when a stopped server should stop billing — UpCloud does not charge for compute while a Cloud Native server is stopped, which Raff does not offer. ### Bandwidth Neither provider bills standard outbound transfer per gigabyte. Raff includes unmetered transfer on a 3 Gbps port. UpCloud includes transfer under a Fair Transfer Policy with zero-cost egress, at 250–500 Mbit/s on Starter and 1000 Mbps on Premium and Cloud Native. Raff's port is three times faster than UpCloud's fastest tier; UpCloud's policy is a fair-share model rather than a hard cap. ### Automated backups Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. UpCloud Simple Backups are priced by server plan or by storage size and retention schedule, so backup cost scales with what you keep rather than being bundled. ## UpCloud VPS performance vs Raff ### Methodology Measured 30 March 2026 on Ubuntu 24.04, single-pass: Raff CPU-Optimized 2 vCPU / 4 GB in us-east against UpCloud Cloud Native 2 cores / 4 GB in Helsinki. Paid at standard rates by Raff Technologies, with no sponsorship or rebate from UpCloud. UpCloud publishes no dedicated-vCPU line, so no same-class pairing exists. ### Results | Benchmark | Raff | UpCloud | Notes | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,627 | Raff 1.39x higher | | Geekbench 6 multi-core | **4,057** | 2,944 | Raff 1.38x higher | | sysbench CPU single-thread | **2,171 ops/s** | 1,591 ops/s | Raff 1.36x higher | | sysbench CPU multi-thread | **4,320 ops/s** | 3,167 ops/s | Raff 1.36x higher | | sysbench memory read | **17.79 GiB/s** | 10.41 GiB/s | Raff 1.71x higher | | sysbench memory write | **11.42 GiB/s** | 4.70 GiB/s | Raff 2.43x higher | | fio 64K read | **1,459.6 MB/s** | 401.5 MB/s | Raff 3.64x higher | | fio 64K write | **1,467.3 MB/s** | 403.6 MB/s | Raff 3.64x higher | | sysbench random read 4K | 52.31 MiB/s | **151.07 MiB/s** | UpCloud 2.89x higher | | sysbench random write 4K | 25.15 MiB/s | **42.55 MiB/s** | UpCloud 1.69x higher | | sysbench sequential read 128K | **1,730 MiB/s** | 401.38 MiB/s | Raff 4.31x higher | | sysbench sequential write 128K | **664.85 MiB/s** | 398.93 MiB/s | Raff 1.67x higher | | Best IPv4 download | **3,635 Mbps** | 1,075 Mbps | Raff 3.38x higher | | Best IPv4 upload | **9,574 Mbps** | 6,154 Mbps | Raff 1.56x higher | ### What the results tell us Raff led CPU by roughly 1.36x to 1.39x on both Geekbench and sysbench, memory write by 2.43x, sequential and 64K disk throughput by 1.67x to 3.64x, and network by 1.56x to 3.38x. **UpCloud won small-block random I/O** — 2.89x on 4K random read and 1.69x on 4K random write. That is the pattern databases and write-heavy queues care about most, and it comes from UpCloud's MaxIOPS storage, which is built for exactly that. If your bottleneck is small synchronous writes, UpCloud's storage is the stronger platform in this test. Read it as a trade: Raff for CPU, memory, sequential throughput and egress; UpCloud for small-block random I/O. ## UpCloud vs Raff: features and reliability ### Compute UpCloud offers three shared-vCPU lines from 1 to 80 cores and 1 GB to 512 GB RAM — a far wider ceiling than Raff's 16 vCPU and 32 GB. Raff offers General Purpose from $4.99/month and CPU-Optimized dedicated vCPU from $9.99/month, on AMD EPYC with DDR5 ECC memory, and resizes on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint. ### Networking Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. UpCloud includes 1000 Mbps on production tiers with zero-cost egress, software-defined private networks, load balancers, and managed NAT and VPN gateways. ### Storage Raff separates storage into VM disk, block volumes at $0.08/GiB-month and object storage at $7/month for 100 GB with 1 TB of egress. UpCloud offers three block tiers — MaxIOPS at €0.220/GB-month with up to 100k IOPS, Standard at €0.085, Archive at €0.056 — plus managed NFS file storage, which Raff does not offer. UpCloud's storage catalog is the more configurable of the two; Raff's is the simpler. ### Support and reliability Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines. On published commitments, UpCloud advertises 99.999% monthly uptime on Premium and Cloud Native; Raff commits to **99.90% monthly, contractual with service credits**, measured from a public status page. Both figures are credit thresholds rather than measured availability, and neither vendor's number is evidence of what your workload will actually see. What is clearly in UpCloud's favour is footprint: 15 data centers against Raff's single us-east region. ### Platform Both sell the layers around the VM, which makes this a rare like-for-like platform comparison. | Product | Raff | UpCloud | |---|---|---| | Managed PostgreSQL / MySQL | **from $7.99/mo** | from €9/mo ≈ $10.43 | | Managed Valkey / Redis-compatible | **from $7.99/mo** | from €8/mo ≈ $9.27 | | Managed Kubernetes control plane | **free** | free (dev) · €60/mo production | | Object storage | **$7/mo — 100 GB + 1 TB egress** | available | | Block storage | **$0.08/GiB-mo** | €0.085 Standard ≈ $0.099 · €0.220 MaxIOPS | | Functions / serverless | **free tier, 100,000 GB-s** | not offered | | PaaS / app deployment | **Raff Apps from $3/mo** | not offered | | ClickHouse, Kafka | **from $7.99/mo** | not offered | | OpenSearch | not offered | **from €100/mo** | | Managed NFS file storage | not offered | **available** | | GPU servers | not offered | **NVIDIA L4 – B200** | | Private cloud | not offered | **from €3,190/mo** | Raff is cheaper on the products both sell and adds Functions, Apps, ClickHouse and Kafka. UpCloud adds OpenSearch, NFS, GPU and Private Cloud, and its Kubernetes production tier costs €60/month where Raff's control plane is free at every size. ## When you should choose UpCloud over Raff - **Users outside North America** — 15 data centers across four continents against Raff's single us-east region - **Small-block random I/O workloads** — MaxIOPS measured 2.89x higher on 4K random read in paid head-to-head testing - **GPU, search or shared-filesystem workloads** — NVIDIA L4 through B200, managed OpenSearch and managed NFS, none of which Raff sells - **Budget servers where specs can slip** — the Starter line undercuts Raff at every tier if previous-generation CPUs and smaller disks are acceptable - **Very large single servers** — up to 80 cores and 512 GB RAM against Raff's 16 vCPU and 32 GB ## When you should choose Raff over UpCloud - **Production VMs at lower cost** — 37% to 65% cheaper than UpCloud Premium at every matched tier, with more storage included at each ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **CPU and memory-bound services** — 1.36x to 1.39x faster CPU and 2.43x faster memory write in paid head-to-head testing - **Egress-heavy applications** — a 3 Gbps unmetered port against 1000 Mbps, and 3.38x measured download throughput - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month against €9/month, on the same account over private networking ([VPS for databases](/learn/guides/vps-for-databases)) - **Kubernetes at production scale** — a free control plane at every cluster size, against €60/month for UpCloud's production tier - **Serverless and app deployment** — Functions with a free monthly tier and Raff Apps from $3/month, neither of which UpCloud offers ## Migrating from UpCloud to Raff 1. **Check your region requirement first** — Raff serves us-east only. If your users are in Europe or Asia, this migration adds latency that no other difference offsets. 2. **Right-size on utilisation** — UpCloud shapes run wider than Raff's ceiling of 16 vCPU and 32 GB. Measure what the workload actually uses before assuming a match exists. 3. **Test disk-bound paths explicitly** — UpCloud MaxIOPS measured faster on small-block random I/O. If your application is bound by small synchronous writes, benchmark it on Raff before committing. 4. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then static assets to object storage. Keep the UpCloud server running throughout. 5. **Cut over and verify billing** — lower DNS TTL beforehand, switch, then confirm your UpCloud resources are deleted rather than stopped, since block storage bills whether or not a server runs. ## About UpCloud UpCloud is a Finnish cloud infrastructure provider founded in 2011 and headquartered in Helsinki, offering cloud servers, managed databases, managed Kubernetes, object and file storage, GPU servers and private cloud from 15 data centers across Europe, North America, Asia and Australia. See [UpCloud pricing](https://upcloud.com/pricing) for current plans and terms. ## Conclusion: UpCloud or Raff? The comparison resolves across four axes: - **Price** — Raff wins on the production tier, 37% to 65% below UpCloud Premium with more storage included; UpCloud's Starter line is cheaper than both - **Performance** — split: Raff leads CPU, memory, sequential disk and network; UpCloud leads small-block random I/O by 2.89x - **Reach** — UpCloud wins, 15 data centers across four continents against Raff's single us-east region - **Platform** — Raff is cheaper on the products both sell and adds Functions, Apps, ClickHouse and Kafka; UpCloud adds OpenSearch, NFS, GPU and Private Cloud If you need multiple regions, GPU or shared filesystems, choose UpCloud. If your users are in North America and you want production VMs and managed databases at materially lower cost, choose Raff. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.9% uptime SLA in writing. --- ### Contabo Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-contabo Description: Considering Contabo? Raff is $30.99/mo for 4 vCPU, 8 GB and 160 GB NVMe on a 3 Gbps port against Contabo's 500 Mbit/s. Contabo is a German hosting company that has sold servers since 2003 — VPS, dedicated machines and object storage — at some of the lowest prices on the market. Raff Technologies is a US cloud provider where the virtual machine is one product among several, alongside managed databases, object storage, Functions and Kubernetes on the same account. Both sell shared-vCPU VMs, so the comparison is a fair one: Contabo Cloud VPS Plus 4 is €13.50/month (about $15.65) for 4 vCPU and 8 GB, and the closest Raff plan is $30.99/month. What differs is not really the server. It is what sits around it, and what you do when one server is no longer enough. ## Contabo VPS and Raff at a glance **Contabo** is a German hosting provider with data centers across Europe, the US, Asia and Australia, rated 4.6/5 on Trustpilot. Its VPS catalog splits three ways. **Core VPS** is the budget line from €5.50/month on SSD with 200 Mbit/s to 1 Gbit/s ports and 1–3 snapshots. **Performance VPS**, branded Cloud VPS Plus, is the NVMe line from €13.50/month with 500 Mbit/s to 1 Gbit/s ports and 5 snapshots. **Max Performance VPS** sits above it, and Cloud VDS offers dedicated cores. Both VPS lines run AMD EPYC — the Core-class VMs benchmarked below reported EPYC 7282 — so storage and port speed, not CPU family, separate them. Contabo advertises 99.9% uptime, unlimited traffic and a free firewall with DDoS protection across the range. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from its us-east region, with a 99.9% uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. The catalogs differ past the VM. Raff sells S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Contabo VPS pricing vs Raff pricing Contabo Performance VPS uses shared AMD EPYC cores, so the like-for-like Raff line is General Purpose. | Contabo shape | Contabo Performance VPS | Raff General Purpose | |---|---|---| | 4 vCPU / 8 GB | **€13.50** (about $15.65) · Plus 4 · 150 GB NVMe · 500 Mbit/s | **$30.99** · 4 vCPU / 8 GB · 160 GB NVMe · **3 Gbps** | | 6 vCPU / 12 GB | **€19.00** (about $22.03) · Plus 6 · 300 GB NVMe · 500 Mbit/s | no 6-core plan · closest is **$37.99** at 8 vCPU / 8 GB · 160 GB NVMe · **3 Gbps** | | 8 vCPU / 24 GB | **€35.00** (about $40.58) · Plus 8 · 450 GB NVMe · 1 Gbit/s | **$115.99** · 8 vCPU / 32 GB · 640 GB NVMe · **3 Gbps** | | 12 vCPU / 48 GB | **€59.00** (about $68.40) · Plus 12 · 600 GB NVMe · 1 Gbit/s | **$90.99** · 12 vCPU / 24 GB · 480 GB NVMe · **3 Gbps** | | 16 vCPU / 64 GB | **€79.00** (about $91.58) · Plus 16 · 750 GB NVMe · 1 Gbit/s | **$129.99** · 16 vCPU / 32 GB · 640 GB NVMe · **3 Gbps** | *Raff General Purpose against Contabo Performance VPS — both shared AMD EPYC on NVMe. Raff CPU-Optimized from $9.99/mo is the match for Contabo Cloud VDS. Contabo standard monthly rates, read 2026-08-18, excluding the discounted first-24-month rate; €1 = $1.1593 (ECB, 2026-08-17).* At the matched 4 vCPU / 8 GB shape Raff is about 98% more expensive. Higher up the range Contabo also sells memory shapes Raff does not offer at any price: 48 GB at 12 cores and 64 GB at 16 cores. Contabo is the cheaper product, and at the memory-heavy end it is the only product. ### Contabo's Core VPS line for reference Core VPS is the budget line, also AMD EPYC but on SSD with lower port speeds. It is not the like-for-like match, and it is the line benchmarked below — worth seeing beside the others: | Shape | Core VPS (SSD) | Performance VPS (NVMe) | Raff General Purpose (NVMe) | |---|---|---|---| | 4 vCPU / 8 GB | €5.50 (about $6.38) · 100 GB · 200 Mbit/s | €13.50 (about $15.65) · 150 GB · 500 Mbit/s | $30.99 · 160 GB · **3 Gbps** | | 8 vCPU / 24 GB | €14.00 (about $16.23) · 300 GB · 600 Mbit/s | €35.00 (about $40.58) · 450 GB · 1 Gbit/s | $115.99 at 8 vCPU / 32 GB · 640 GB · **3 Gbps** | | 16 vCPU / 64 GB | €37.00 (about $42.89) · 500 GB · 1 Gbit/s | €79.00 (about $91.58) · 750 GB · 1 Gbit/s | $129.99 at 16 vCPU / 32 GB · 640 GB · **3 Gbps** | If your priority is the lowest price per gigabyte of RAM and SSD is acceptable, Core VPS is the cheapest option on this page by a wide margin. ### Bandwidth and transfer Neither provider meters standard outbound transfer. Contabo lists unlimited traffic under a fair-use policy; Raff includes unmetered transfer. The difference is the pipe: Contabo Performance VPS runs 500 Mbit/s on Plus 4 and Plus 6 and 1 Gbit/s from Plus 8 up — its own headline is "Unlimited Traffic up to 1 Gbit/s" — while every Raff plan runs a 3 Gbps port regardless of tier. At the matched shape that is a six-fold difference in ceiling. Unlimited transfer on a 500 Mbit/s port and unmetered transfer on a 3 Gbps port are not the same product. ### Automated backups Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure yourself, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. Contabo Performance VPS includes 5 snapshots and sells automated backups as a paid add-on at checkout. Compare the configured price, not the headline price, if scheduled backups are a requirement. ### Location and term Contabo's advertised rates are European base prices, and some US, Asian and Australian locations carry a surcharge — confirm the price for the region you need. The rates above are standard monthly prices; the advertised lower rate is a 24-month commitment, not the ongoing price. Raff prices are not region-surcharged, bill monthly with no term, and carry a 14-day money-back guarantee. ## Contabo VPS performance vs Raff ### Methodology Raff figures are internal, measured March–May 2026 on a 2 vCPU / 4 GB instance rather than the 4 vCPU / 8 GB shape priced above. Contabo figures are third-party, from VPSBenchmarks. Sequential throughput is shown in MB/s on both sides. Two Core VPS figures are withheld because they exceed Contabo's own newer NVMe tier by roughly four times — most likely page-cache effects rather than a real result. ### Results | Metric | Raff General Purpose | Contabo Performance VPS (Plus 4) | Contabo Core VPS | |---|---:|---:|---:| | Geekbench 6 single-core | 2,266 | **2,476** | 1,163 | | Geekbench 6 multi-core | 4,057 (2 vCPU) | **8,157** (4 vCPU) | 4,700 (4 vCPU) | | fio 4K read, 50/50 mix | **48,670 IOPS** | 15,948 IOPS | 15,768 IOPS | | fio 4K read, read-only | **74,562 IOPS** | not published | not published | | fio 1M sequential read | **2,491 MB/s** | 534.8 MB/s | withheld | | fio 1M sequential write | **1,257 MB/s** | 570.4 MB/s | withheld | | iperf3 peak † | **9,574 Mbps** | 496 Mbps | 485–496 Mbps | | CPU steal, sustained load | 0.13–0.32% over 26h | **0.00%** avg and max | 3.08–4.26% | | Request timeouts @ 120 req/s | not run | not run | **4,058** | † Raff VMs publish a 3 Gbps port speed and are provisioned on 10 Gbps host uplinks in us-east. The 9,574 Mbps figure is a measured peak across parallel iperf3 streams, above the published per-VM rate — treat 3 Gbps as the committed speed, not 9.5. ### What this tells you **On CPU the two are close.** 2,476 against 2,266 single-core is about 9% apart, across separate tests on different days — inside the range where the honest answer is *comparable* rather than *faster*. CPU steal is effectively zero on both: 0.00% on Contabo Performance, 0.13–0.32% on Raff across a 26-hour run. Neither shows the shared-core variance that makes a server feel slow under load. If per-core CPU is all your workload cares about, this comparison does not separate them, and Contabo is cheaper. **Raff separates on throughput.** Sequential 1M reads ran 2,491 MB/s against 534.8 MB/s, writes 1,257 MB/s against 570.4 MB/s, and the 4K mixed job 48,670 IOPS against 15,948. The network gap is structural rather than tuning: Plus 4 lists a 500 Mbps maximum and measured 496 Mbps. **The Core column shows what the cheap line gives up:** roughly half the single-core score, 3.08–4.26% CPU steal under load, and 4,058 request timeouts at 120 req/s. CPU steal is time your VM was ready to run but waiting for a core held by a neighbour — at 3–4%, a server stays online and answers monitoring checks while individual requests queue. That is how a platform records high availability and slow page loads at the same time. It belongs to Core VPS, not to Performance VPS. ## Contabo vs Raff: features and reliability ### Compute Contabo Performance VPS offers five shared AMD EPYC shapes from 4 to 16 cores and 8 to 64 GB RAM, with more memory per core than Raff sells at any tier. Raff offers General Purpose from $4.99/month and CPU-Optimized dedicated vCPU from $9.99/month, on AMD EPYC with DDR5 ECC memory, scaling to 16 vCPU and 32 GB. Raff plans resize on demand: stop the VM, switch plan, restart, with the difference settled to your account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking Raff includes a 3 Gbps port on every plan, private networking, VPC, firewall controls and site-to-site VPN gateways. Contabo includes a free firewall and DDoS protection, with port speeds of 500 Mbit/s to 1 Gbit/s on the Performance line. ### Storage Both lines use NVMe, but not in the same way. Contabo attaches local NVMe to the host. Raff runs distributed block storage across an NVMe cluster, so a write crosses the network and is replicated before it is acknowledged. What that model buys is everything around the disk: data replicated rather than pinned to one machine, snapshots and backups taken at the storage layer, and a VM that changes plan by stopping and restarting rather than being rebuilt. Block volumes at $0.08/GiB-month attach and resize independently for the same reason. Contabo ships more capacity per plan — 150 GB at 4 cores rising to 750 GB at 16 — against Raff's 160 GB and 640 GB at the same core counts. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines, through the same queue. Contabo's help centre describes a different model. Live chat requires an active Contabo account and a login to the customer panel, and the conversation starts with ContaBro, a virtual assistant, before a human agent is reached. Phone support runs 08:00 to 23:00 European time. Ticket support accepts requests at any hour, but Contabo does not publish a response target. The practical difference shows up twice: before you buy, when you cannot reach Contabo chat without an account, and at 3 AM, when a bot answers first. ### Platform This is the widest gap, and for most buyers the one that decides the question. A VM is rarely the whole requirement. An application needs a database, somewhere to put uploads, background jobs, and eventually a way to scale beyond one server. On Raff those are products on the same account: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month for 100 GB and 1 TB of egress, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds per month, Raff Apps from $3/month, and managed Kubernetes with a free control plane and workers from $9.99/month. They connect over private networking rather than the public internet, share one API, one CLI and one bill, and the database you attach today is the one you scale next quarter. Contabo offers object storage and managed services alongside its servers, but the catalog is oriented around servers — a database, a queue and an object store assembled from separate places, each with its own credentials, billing and failure modes. The honest counter-argument is that you can run Postgres on the same Contabo box for free. You can, and on a 48 GB plan it will run well. What you are then operating is backups, restore testing, failover, point-in-time recovery and version upgrades. If that work is inside your team's capability and time budget, Contabo is genuinely cheaper. If it is not, the question is not which VM costs less this month — it is what the second and third piece of your stack cost in time when you need them. ## When you should choose Contabo over Raff - **Memory-heavy batch and analytics** — 48 GB at 12 cores for €59.00 (about $68.40) and 64 GB at 16 cores for €79.00 (about $91.58); Raff sells no equivalent at any price - **Self-hosted storage, media and backup targets** — 750 GB NVMe at the top tier against Raff's 640 GB, with unlimited traffic - **Large dev, test and CI fleets** — comparable per-core CPU at roughly half the cost, where latency variation costs nothing - **Single CPU-bound servers** — 2,476 Geekbench 6 single-core with 0.00% CPU steal, cheaper than Raff at every matched tier - **Users outside the United States** — data centers across Europe, Asia and Australia against Raff's single us-east region ## When you should choose Raff over Contabo - **User-facing APIs and web applications** — 9,574 Mbps measured against 496 Mbps, on a 3 Gbps port at every tier ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **Database-backed products** — 48,670 4K read IOPS on a 50/50 mix against 15,948, and 2,491 MB/s sequential read, with managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month on the same account ([VPS for databases](/learn/guides/vps-for-databases)) - **Stacks that will outgrow one server** — object storage at $7/month, Functions with a free monthly tier, Raff Apps from $3/month and managed Kubernetes with a free control plane, connected over private networking - **Production workloads that must recover** — Daily and Weekly schedules on a free storage pool, retention from 1 to 365 days, and uncapped snapshots, against 5 snapshots with backups sold as an add-on - **Latency-sensitive services** — CPU-Optimized dedicated vCPU from $9.99/month where shared-core variance is unacceptable - **Teams evaluating without commitment** — monthly billing, a 14-day money-back guarantee, and no KYC verification step before first provisioning ## Migrating from Contabo to Raff 1. **Right-size on measured utilisation** — do not match core and RAM counts by default. Contabo's memory-heavy shapes are often larger than the workload needs. 2. **Plan the memory gap honestly** — if you genuinely use 48 or 64 GB, Raff has no equivalent plan, and that is a reason to stay. 3. **Provision and harden** — create the Raff VM on the same distribution, apply firewall rules, attach private networking before moving data. 4. **Move data in order** — files with rsync or SCP, then database dumps, then static assets to object storage. Keep the Contabo VPS running throughout. 5. **Test under load, not at idle** — the differences here appear under sustained traffic. Replay real traffic before switching DNS. 6. **Cut over and check the term** — lower DNS TTL beforehand, switch, then confirm your Contabo billing term. A discounted 24-month rate continues after you migrate. ## About Contabo Contabo is a German hosting provider founded in Munich, offering Core, Performance and Max Performance VPS lines, Cloud VDS, dedicated servers and object storage from data centers in Europe, the US, Asia and Australia. It is known for high RAM and core counts at low monthly prices. See [Contabo VPS](https://contabo.com/en/vps/) for current plans and terms. ## Conclusion: Contabo or Raff? The comparison resolves across four measured axes: - **Price** — Contabo wins: €13.50 (about $15.65) against $30.99 at 4 vCPU and 8 GB, roughly half, and cheaper at every tier above - **Per-core CPU** — comparable, 2,476 against 2,266 Geekbench 6 single-core, with CPU steal effectively zero on both - **Throughput** — Raff wins, 9,574 Mbps against 496 Mbps and 2,491 MB/s sequential read against 534.8 MB/s - **Platform** — Raff adds managed databases from $7.99/month, Functions, object storage, Apps and Kubernetes to the same account, over private networking If you are buying one server, CPU is what you care about, and price decides it, choose Contabo — per-core performance is comparable and it costs roughly half. If you are building an application that will also need a managed database, object storage, Functions or Kubernetes, choose Raff: those run on the same account, over private networking, on one bill. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.9% uptime SLA in writing. --- ### Oracle Cloud Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-oracle-cloud Description: Considering Oracle Cloud? Compare Raff at $30.99/mo for 4 vCPU, 8 GB and 160 GB NVMe with OCI E6 pricing, bandwidth, Free Tier and tradeoffs. Raff is an Oracle Cloud alternative for conventional application infrastructure when a workload fits `us-east` and the priorities are lower published VM pricing, included NVMe capacity, unmetered bandwidth, and a smaller operating surface. Oracle Cloud Infrastructure is stronger when the architecture needs 50+ public cloud regions, Oracle Database services, flexible AMD, Intel, or Arm shapes, bare metal, GPUs, enterprise governance, multicloud interconnects, or Always Free resources. For a current **spec-level** comparison, Raff General Purpose provides **4 vCPU / 8 GB / 160 GB NVMe for $30.99/month**, while OCI `VM.Standard.E6.Flex` at 2 OCPUs / 8 GB plus 160 GB of Balanced Block Volume storage is approximately **$62.28/month** before backups, paid support, premium software, and services beyond the included network allowance. Raff has no controlled Oracle Cloud benchmark within the last 90 days, so this page compares verified pricing, architecture, included resources, and platform fit without declaring a performance winner. ## Oracle Cloud vs Raff: which is right for you? Oracle Cloud Infrastructure and Raff solve different operating problems. OCI is a global enterprise cloud with flexible infrastructure and deep Oracle-native services; Raff is a smaller cloud platform designed to reduce packaging and billing complexity. | Decision factor | Choose Raff | Choose Oracle Cloud Infrastructure | |---|---|---| | Geography | Your workload fits one region named `us-east` | You need 50+ public cloud regions, sovereign realms, or specific country placement | | VM economics | You want a published VM plan with listed NVMe capacity and unmetered transfer | You can model OCPU, memory, boot volume, performance units, backups, and services separately | | CPU architecture | Conventional x86 VM plans fit the workload | You need flexible AMD, Intel, Arm, bare metal, GPU, or HPC shapes | | Databases | You need managed PostgreSQL, MySQL, Valkey, ClickHouse, or Kafka | You need Autonomous Database, Exadata, Oracle Database, MySQL HeatWave, or Oracle licensing integration | | Application platform | You need VMs, Kubernetes, databases, Apps, Functions, and storage in a compact platform | You need OKE, OCI Functions, Container Instances, API Gateway, analytics, AI, and enterprise integration | | Free usage | You prefer a paid production plan with clear included resources | Your eligible workload can remain inside OCI Always Free limits and available capacity | | Operations | Direct support and a smaller product surface are valuable | Compartments, IAM policies, tenancy governance, quotas, and enterprise controls are required | Raff is not a replacement for every OCI product. It is most relevant as an Oracle Cloud VM alternative for conventional Linux and Windows application infrastructure where predictable cost matters more than Oracle-native platform depth. For the wider location decision, review [how to choose a U.S. cloud server for latency and compliance](/learn/guides/choose-us-cloud-server-latency-compliance). ## Oracle Cloud Infrastructure overview Oracle Cloud Infrastructure is Oracle's public cloud platform for compute, networking, storage, databases, containers, analytics, AI, security, identity, governance, and hybrid or multicloud deployments. Oracle currently describes a footprint of **50+ public cloud regions across 28 countries**, including commercial, government, sovereign, and multicloud locations. OCI Compute supports flexible AMD, Intel, and Arm virtual machine shapes. On x86 shapes, **1 OCPU equals 2 vCPUs**. `VM.Standard.E6.Flex` is the newer AMD Standard Flex generation and allows teams to adjust OCPU and RAM rather than selecting only fixed bundles. Oracle's current E6 shape supports up to 126 OCPUs and up to 1,454 GB of memory, with network bandwidth scaling by OCPU. Oracle also provides Ampere Arm shapes through `VM.Standard.A1.Flex`. OCI's Always Free documentation currently includes **1,500 A1 OCPU-hours and 9,000 GB-hours per month**, equivalent to 2 OCPUs and 12 GB of memory for Always Free tenancies, plus **200 GB of combined boot/block volume storage**, five volume backups, and **20 GB of combined Object and Archive Storage**. Always Free capacity can be unavailable in a preferred availability domain, and idle compute instances can be reclaimed under Oracle's published policy. OCI's strongest differentiators are Oracle Database services, Autonomous Database, Exadata, MySQL HeatWave, flexible compute, bare metal, high-performance networking, enterprise identity and governance, and interconnect options with other hyperscalers. ## Raff overview Raff serves customers from one public region named `us-east`. The current platform includes: - General Purpose shared-vCPU VMs - CPU-Optimized dedicated-vCPU VMs - Linux and Windows operating systems - Managed Kubernetes - Managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka - Raff Apps - Raff Functions - S3-compatible Object Storage - Block Storage Volumes at $0.08/GB-month - Snapshots at $0.06/GB-month - Private networking, firewall controls, DDoS protection, IPv4, and IPv6 - API, CLI, Terraform, web console, VNC, resize, and custom OS workflows Current General Purpose shared-vCPU plans include: - **2 vCPU / 2 GB / 40 GB NVMe — $8.49/month** - **2 vCPU / 4 GB / 80 GB NVMe — $13.99/month** - **4 vCPU / 4 GB / 80 GB NVMe — $16.99/month** - **2 vCPU / 8 GB / 160 GB NVMe — $27.99/month** - **4 vCPU / 8 GB / 160 GB NVMe — $30.99/month** - **8 vCPU / 8 GB / 160 GB NVMe — $37.99/month** - **8 vCPU / 16 GB / 320 GB NVMe — $59.99/month** Raff also offers CPU-Optimized plans for workloads that need dedicated-vCPU allocation. This refresh does not publish CPU-Optimized prices because the current buyer-facing comparison is anchored to the live General Purpose catalog. VM bandwidth is unmetered on a standard **3 Gbps** public port. Raff's current data-protection model uses a **free backup-and-snapshot storage pool** rather than the older three-slot model; additional protection storage is priced separately when the included pool is exceeded. Raff reports **3,000+ customers and 15,000+ VMs**, publishes a **99.9% uptime SLA**, and currently shows **4.5/5 on Trustpilot** and **4.6/5 on G2**. ## Oracle Cloud pricing vs Raff pricing The current table compares Raff General Purpose with OCI `VM.Standard.E6.Flex`. This is a **spec-level buying comparison, not a claim of equal CPU allocation or equal performance**: Raff General Purpose uses shared vCPU, while OCI E6 uses Oracle's OCPU-based Standard Flex model. OCI estimates use **$0.03 per OCPU-hour**, **$0.002 per GB-hour**, 730 hours per month, and Balanced Block Volume storage at **$0.0425 per GB-month**. | Published CPU / memory / storage class | Raff General Purpose | OCI E6 Flex + Balanced storage | Difference before other OCI add-ons | |---|---:|---:|---:| | 2 vCPU / 4 GB / 80 GB | **$13.99** | $27.74 compute + $3.40 storage = **$31.14** | Raff about 55% lower | | 4 vCPU / 8 GB / 160 GB | **$30.99** | $55.48 compute + $6.80 storage = **$62.28** | Raff about 50% lower | | 8 vCPU / 16 GB / 320 GB | **$59.99** | $110.96 compute + $13.60 storage = **$124.56** | Raff about 52% lower | OCI flexible shapes can be right-sized more precisely than Raff's fixed published tiers. A team can choose a different memory-to-OCPU ratio and potentially avoid paying for unused RAM. OCI also gives buyers more processor, accelerator, and infrastructure options. Raff's advantage is the lower published VM price, included listed NVMe capacity, and a simpler bandwidth model. ### Oracle Cloud Free Tier OCI's Always Free resources remain a meaningful advantage for eligible experiments and small workloads. Oracle's current detailed documentation includes: - Up to two AMD `VM.Standard.E2.1.Micro` instances - Ampere A1 Always Free compute allocation - **200 GB** combined boot and Block Volume storage - **Five** Always Free volume backups - **20 GB** combined Object and Archive Storage for Always Free-only accounts - Additional Always Free platform resources The tradeoffs matter. Ampere A1 is Arm rather than x86, so third-party binaries and proprietary software must support the architecture. Free compute can also be unavailable because of regional capacity, and Oracle documents reclamation criteria for idle Always Free compute. ### What OCI compute pricing does not include OCI VM compute pricing does not include: - Boot and data Block Volume capacity - Balanced or higher Block Volume performance units where applicable - Block Volume backups and retained snapshots beyond free allocations - Paid support - Load Balancer capacity where used - Database licenses or premium operating systems where applicable - Public egress above the included monthly allowance - Additional OCI services used by the workload OCI Balanced Block Volume totals **$0.0425/GB-month** at the standard balanced configuration used in this comparison. Raff includes the listed plan NVMe capacity and unmetered VM bandwidth. Its current protection model provides a free backup-and-snapshot storage pool, with additional protection storage billed when usage exceeds that pool. :::cta Deploy Your Server Compare current Raff VM plans with included NVMe storage and unmetered bandwidth. ::: ## Bandwidth and transfer policy Oracle Cloud has one of the more generous hyperscaler egress policies. OCI includes the first **10 TB of outbound data per month** and advertises outbound pricing starting at **$0.0085/GB above 10 TB**. Inbound transfer and many intra-region transfer paths are free under OCI's published networking model. Raff VM plans include unmetered bandwidth on a standard **3 Gbps** public port. Raff does not add a per-GB internet egress line item to normal VM plans. | Monthly outbound transfer | Raff | OCI public internet egress | |---:|---:|---:| | 1 TB | Included | Included in first 10 TB | | 5 TB | Included | Included in first 10 TB | | 10 TB | Included | Included in first 10 TB | | 20 TB | Included | About **$85** for 10 TB above allowance | | 50 TB | Included | About **$340** for 40 TB above allowance | OCI is unusually competitive on bandwidth for a hyperscaler. Below 10 TB/month, both Raff and OCI avoid a variable public-egress charge. Above 10 TB, Raff remains simpler because transfer stays included, while OCI's published overage rate remains relatively low. OCI also offers Site-to-Site VPN and FastConnect for hybrid networking. Oracle's global network and many regions are stronger for distributed or hybrid systems; Raff is simpler for a single-region `us-east` application stack. ## Feature comparison: Oracle Cloud vs Raff ### Compute | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Shared compute | General Purpose shared vCPU | Flexible and fixed VM shapes | | Dedicated compute | CPU-Optimized family available | Bare metal and specialized compute options | | Current pricing anchor | $30.99 — 4 vCPU / 8 GB / 160 GB | E6 Flex ≈ $62.28 with matched 160 GB Balanced storage | | CPU architectures | x86 VM catalog | AMD, Intel, Arm, GPU, and HPC families | | Flexible CPU/RAM ratio | Fixed published plans | Flexible OCPU and RAM configuration | | Bare metal | Not in current public VM catalog | Available | | Preemptible capacity | Not in current public VM catalog | Available for supported shapes | | GPUs and HPC | Not in current public VM catalog | Broad GPU, RDMA, HPC, and AI infrastructure | | Custom images | Available | Available | OCI clearly wins on architecture choice and infrastructure breadth. Raff offers fewer choices but a shorter buying path for ordinary application infrastructure. ### Networking | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Public egress | Unmetered at 3 Gbps | First 10 TB/month free; from $0.0085/GB above | | Private networking | Available | VCN, peering, DRG, and private endpoints | | Firewall | Included platform controls | Security Lists, Network Security Groups, OCI Network Firewall | | IPv4 and IPv6 | Available | Available | | Load balancing | Not used as a Raff advantage in this comparison | Flexible Load Balancer and Network Load Balancer | | Site-to-site VPN | Standard integration pattern | OCI Site-to-Site VPN | | Dedicated connectivity | External provider integration | FastConnect | | Geography | One `us-east` region | 50+ public cloud regions | OCI wins on global, hybrid, and enterprise network architecture. Raff wins when a single-region workload benefits from fewer network products and no transfer meter. ### Storage & Backups | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | VM storage | Listed NVMe capacity included | Boot volume billed separately outside free allocations | | Additional block storage | Volumes at $0.08/GB-month | Multiple Block Volume performance tiers | | On-demand snapshots | $0.06/GB-month | Block Volume and boot-volume backups | | Automated protection baseline | Free backup-and-snapshot storage pool | Oracle-defined or custom backup policies | | Performance controls | Plan-dependent | VPUs, IOPS, throughput, autotuning, elastic performance | | Object storage | S3-compatible Object Storage | Object Storage and Archive Storage | OCI offers deeper storage-performance tuning and enterprise policy controls. Raff provides a simpler VM-storage and protection workflow. ### Platform Features | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Managed Kubernetes | Available | Oracle Kubernetes Engine | | Managed relational databases | PostgreSQL and MySQL | Autonomous Database, Oracle Database, MySQL HeatWave, PostgreSQL services | | Managed data services | Valkey, ClickHouse, Kafka | Oracle-native database, analytics, streaming, integration, and data services | | Functions | Raff Functions | OCI Functions | | Application platform | Raff Apps | Container Instances, Functions, OKE, API Gateway, DevOps services | | Oracle software integration | General Linux and Windows hosting | Deep Oracle Database and enterprise-application integration | | AI and analytics | Focused application platform | OCI Generative AI, Data Science, analytics, GPUs, and HPC | | API, CLI, Terraform | Available | Extensive APIs, OCI CLI, Resource Manager, Terraform ecosystem | OCI wins on Oracle-native databases, enterprise integration, analytics, AI, and specialized services. Raff covers a compact application stack for teams that do not need the wider Oracle portfolio. ### Pricing & Billing | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Billing choices | Subscription terms plus hourly PAYG options | Usage-based billing and enterprise commitments | | Compute sizing | Fixed published plans | Flexible OCPU and memory | | VM disk included | Yes | Boot volume billed separately outside free allocations | | Internet egress | Unmetered | First 10 TB/month free, then low overage pricing | | Protection baseline | Free backup-and-snapshot storage pool | Policies and retained backups configured separately | | Free tier | No permanent free VM tier | Always Free resources and trial credits where eligible | OCI provides more flexibility and a valuable free tier. Raff requires less cost modeling for an ordinary paid production server. ### Trust & Operations | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Scale signal | 3,000+ customers; 15,000+ VMs | Global enterprise cloud operated by Oracle | | Public rating | Trustpilot 4.5/5; G2 4.6/5 | Broad enterprise customer and partner ecosystem | | SLA | 99.9% | Service- and architecture-specific SLAs | | Support | Direct 24/7 support | Documentation, partners, enterprise support, and Oracle support programs | | Governance | Focused platform controls | Tenancies, compartments, IAM policies, quotas, Cloud Guard, Security Zones | | Compliance | Focused provider program | Extensive global and industry-specific compliance portfolio | OCI wins on enterprise governance, compliance breadth, support programs, and ecosystem depth. Raff offers a more direct operating relationship and a smaller surface to manage. ### Infrastructure | Feature | Raff | Oracle Cloud Infrastructure | |---|---|---| | Public region model | One region named `us-east` | 50+ regions across 28 countries | | Availability architecture | Raff region model | Availability domains and fault domains where supported | | CPU architectures | x86 | AMD, Intel, Arm, GPU, bare metal, HPC | | Multicloud | Standard internet and partner integrations | Interconnect options with other major clouds in selected regions | | Hybrid cloud | Standard integration patterns | Dedicated Region, Cloud@Customer, FastConnect, and edge options | | Best fit | Predictable U.S.-East application infrastructure | Oracle databases, global enterprise, regulated, AI, HPC, and multicloud systems | ## Performance benchmarks: Raff vs Oracle Cloud Raff has not completed a controlled, matched Oracle Cloud Infrastructure benchmark within the last 90 days. This page therefore does **not** claim that Raff or OCI is faster. A valid benchmark would need to match: - OCI region and Raff `us-east` network test paths - Linux distribution, kernel, and tuning - x86 architecture on both sides - Oracle OCPU-to-vCPU mapping - Raff General Purpose or CPU-Optimized class - Block Volume size, VPUs, caching, IOPS, and throughput - At least three passes per test - CPU, memory, fio, PostgreSQL, Redis, HTTP, and network workloads - Full monthly cost including OCI compute and storage Ampere A1 should not be used as the primary benchmark opponent for Raff's x86 plans because Arm and x86 compatibility, instruction sets, compiler behavior, and workload optimization differ. OCI E6 Flex would be the cleaner current x86 comparison, but its flexible memory and storage-performance settings must be recorded. Until that test exists, use the pricing and feature sections to make the decision. ## When you should choose Oracle Cloud over Raff Choose Oracle Cloud when: - You need deployment across 50+ public cloud regions. - Your organization runs Oracle Database, Exadata, Autonomous Database, or Oracle enterprise applications. - You need flexible OCPU and RAM ratios rather than fixed VM bundles. - Arm, Intel, AMD, bare metal, GPU, HPC, or RDMA infrastructure is required. - OCI Always Free resources fit an experimental or small Arm-compatible workload. - Your architecture requires compartments, advanced IAM policies, Cloud Guard, Security Zones, or enterprise governance. - OKE, MySQL HeatWave, OCI Functions, Data Science, Generative AI, analytics, or integration services are central. - FastConnect, sovereign-cloud options, Cloud@Customer, or multicloud interconnects are required. ## When you should choose Raff over Oracle Cloud Choose Raff when: - You want **2 vCPU / 4 GB / 80 GB NVMe for $13.99/month**. - You want **4 vCPU / 8 GB / 160 GB NVMe for $30.99/month**. - You want unmetered VM bandwidth rather than a 10 TB allowance and usage meter above it. - The current free backup-and-snapshot storage pool fits your ordinary protection needs. - Your workload uses conventional Linux or Windows VMs, managed databases, Kubernetes, Apps, Functions, and object storage. - Your users and compliance requirements fit `us-east`. - You do not need Oracle Database, Exadata, Arm, GPU, bare metal, HPC, or Oracle enterprise governance. - You prefer direct support and fewer billing dimensions. Compare nearby decisions with [Raff versus Google Cloud](/learn/compare/raff-vs-google-cloud), [Raff versus Azure Virtual Machines](/learn/compare/raff-vs-azure-virtual-machines), and [Raff versus AWS Lightsail](/learn/compare/raff-vs-aws-lightsail). :::cluster ## Migrating from Oracle Cloud to Raff 1. **Inventory the OCI tenancy.** Record Compute instances, shapes, OCPUs, memory, architecture, boot and block volumes, VPUs, VCNs, subnets, security lists, NSGs, public IPs, load balancers, DNS, IAM policies, compartments, backups, and managed-service dependencies. 2. **Classify portable and OCI-native components.** Standard x86 Linux or Windows VMs, containers, files, and common databases are usually portable. Autonomous Database, Oracle Database systems, Exadata, OKE-specific controllers, MySQL HeatWave, OCI Vault, Functions, Streaming, and private service endpoints need replacement or hybrid planning. 3. **Resolve architecture compatibility.** Ampere A1 workloads are Arm. Confirm that container images, packages, binaries, agents, and proprietary software have x86 builds before moving to Raff's x86 VM catalog. 4. **Choose the Raff compute class.** Use General Purpose for shared-vCPU workloads or CPU-Optimized where dedicated-vCPU allocation is required. Match RAM, usable disk, public IPs, private networking, firewall exposure, and protection requirements. 5. **Move applications and data.** Redeploy from source control, transfer files with rsync or secure copy, move compatible object data with S3 tools, and migrate databases using native dump/restore, replication, or application-level export. 6. **Validate before cutover.** Test TLS, SSH or RDP, application health, database consistency, storage mounts, scheduled jobs, outbound email, IPv6, backups, restores, monitoring, and third-party allowlists through a temporary hostname. 7. **Cut over and remove residual OCI charges.** Lower DNS TTL, perform the final sync, update A and AAAA records, monitor production, retain OCI for rollback, then delete unused instances, boot volumes, block volumes, backups, reserved IPs, load balancers, gateways, and paid services. Operational gotchas: - OCI public IP addresses cannot move to Raff. Update DNS, security allowlists, payment providers, SMTP relays, VPN peers, and partner integrations. - OCI Block Volume backups are not directly attachable to Raff. Use file-, image-, database-, or application-level migration methods. - Ampere A1 Arm binaries do not automatically run on x86 VMs. Rebuild containers and packages for `amd64` where required. - Oracle Database licensing, support contracts, and application dependencies require separate commercial and technical review. ## About Oracle Cloud Infrastructure [Oracle Cloud Infrastructure](https://www.oracle.com/cloud/) is Oracle's global public cloud platform for compute, networking, storage, databases, containers, analytics, AI, security, governance, and hybrid or multicloud deployment. Its strongest differentiation is the combination of Oracle Database services, flexible infrastructure, enterprise controls, and 50+ public cloud regions. ## Conclusion: Oracle Cloud or Raff? Raff is the stronger Oracle Cloud alternative for ordinary production servers when the workload fits `us-east` and predictable VM economics matter more than global enterprise breadth. - **Current VM pricing:** Raff 4 vCPU / 8 GB / 160 GB is $30.99; OCI E6 Flex at 2 OCPUs / 8 GB plus 160 GB Balanced storage is approximately $62.28 before backups and additional services. - **Bandwidth:** Raff is unmetered on a standard 3 Gbps port; OCI includes 10 TB/month and charges from $0.0085/GB above it. - **Protection:** Raff uses a free backup-and-snapshot storage pool; OCI backup policies and retained data are separately configured outside applicable Free Tier allocations. - **Free tier:** OCI offers meaningful Always Free compute, block storage, backups, and object/archive storage for eligible accounts; Raff focuses on paid production plans. - **Platform:** OCI wins on 50+ regions, Oracle Database, flexible shapes, Arm, bare metal, GPUs, HPC, enterprise governance, and multicloud products. - **Performance evidence:** no matched benchmark is available, so neither provider is declared faster. Choose Oracle Cloud for Oracle-native databases, global enterprise systems, free-tier experiments, specialized compute, governance, or multicloud infrastructure. Choose Raff for `us-east` Linux and Windows application stacks that benefit from included NVMe, unmetered bandwidth, managed databases, Kubernetes, Apps, Functions, and direct support. Continue with [the U.S. cloud server decision guide](/learn/guides/choose-us-cloud-server-latency-compliance) or review [Raff VM plans](/products/raff-vm). --- ### Azure Virtual Machines Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-azure-virtual-machines Description: Considering Azure Virtual Machines? Compare Raff at $30.99/mo for 4 vCPU, 8 GB and 160 GB NVMe with Azure VM pricing, bandwidth and tradeoffs. Raff is an Azure Virtual Machines alternative when a workload fits `us-east` and the priorities are lower published VM pricing, included NVMe capacity, unmetered bandwidth, and a smaller operating surface. Azure Virtual Machines is stronger when the architecture needs more than 70 regions, availability zones, Microsoft identity and licensing integrations, GPUs, confidential computing, scale sets, hybrid connectivity, or Azure-native managed services. At the 4 vCPU / 8 GB shared-class comparison point, Raff General Purpose is **$30.99/month** with 160 GB NVMe and unmetered bandwidth, while Azure `B4ls v2` in East US is about **$107.31/month for Linux compute only** before managed disk, outbound transfer, snapshots, and support. Raff has not completed a controlled Azure benchmark within the last 90 days, so this page compares current pricing, CPU behavior, included resources, and platform fit without declaring a performance winner. For buyers searching for an **Azure VM alternative, Azure VPS, Azure Virtual Machines pricing, or a cheaper Azure alternative**, the practical decision is whether Microsoft's global platform breadth matters more than simpler `us-east` VM economics. For the broader location decision, review [how to choose a U.S. cloud server for latency and compliance](/learn/guides/choose-us-cloud-server-latency-compliance). ## Azure Virtual Machines vs Raff: which is right for you? The choice is between Azure's globally distributed enterprise platform and Raff's simpler infrastructure package. | Decision factor | Choose Raff | Choose Azure Virtual Machines | |---|---|---| | Geography | Your users and compliance requirements fit one region named `us-east` | You need more than 70 regions, availability zones, or specific data-residency options | | VM economics | You want listed NVMe capacity and unmetered transfer in the published VM price | You can model compute, disk, transfer, snapshots, licenses, and network services separately | | CPU behavior | You want shared-vCPU General Purpose or a dedicated-vCPU product family | You want burstable B-series, fixed-performance families, Spot VMs, confidential VMs, GPUs, or specialized sizes | | Windows | You need a straightforward hosted Windows VM workflow | You need Azure Hybrid Benefit, Microsoft Entra integration, Azure Virtual Desktop, or enterprise Microsoft agreements | | Application platform | You need VMs, Kubernetes, managed databases, Apps, Functions, and storage in a compact platform | You need AKS, Azure SQL, Cosmos DB, Functions, App Service, Fabric, AI services, or deep Microsoft integration | | Networking | Public egress is large or unpredictable | You need ExpressRoute, Virtual WAN, global load balancing, Front Door, or complex hybrid networks | Raff is not a replacement for every Azure service. It is most relevant as an Azure VM alternative for conventional Linux and Windows servers where predictable infrastructure cost matters more than hyperscaler breadth. ## Azure Virtual Machines overview Azure Virtual Machines is Microsoft's infrastructure-as-a-service compute product for Linux and Windows workloads. Azure currently provides **more than 70 regions globally**, with availability-zone support in many regions and a large portfolio of networking, security, backup, monitoring, identity, and hybrid services. Azure offers many VM families: burstable B-series, general-purpose D-series, memory-optimized E-series, compute-optimized F-series, storage-optimized L-series, GPU families, confidential VMs, and specialized high-performance computing options. That breadth is a major advantage, but it also means that Azure VM pricing depends on family, region, OS, purchase model, disk, IP, transfer, and support. This comparison uses the current **Bsv2 low-memory Linux family in East US** because it provides clean 2 vCPU / 4 GB, 4 vCPU / 8 GB, and 8 vCPU / 16 GB sizes. `B2ls v2`, `B4ls v2`, and `B8ls v2` each have a **30% base CPU performance level** and use CPU credits to burst toward full vCPU performance. They have no local temporary storage and rely on Azure Managed Disks. Azure supports pay-as-you-go, Spot VMs, savings plans, and one-year or three-year reservations. Discounts can materially reduce compute cost, but they do not eliminate every surrounding storage, transfer, backup, support, or software charge. ## Raff overview Raff serves customers from one public region named `us-east`. Its current platform includes: - General Purpose shared-vCPU VMs - CPU-Optimized dedicated-vCPU VMs - Linux and Windows operating systems - Managed Kubernetes - Managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka - Raff Apps - Raff Functions - S3-compatible Object Storage - Block Storage Volumes at $0.08/GB-month - Snapshots at $0.06/GB-month - Private networking, firewall controls, DDoS protection, IPv4, and IPv6 - API, CLI, Terraform, web console, VNC, resize, and custom OS workflows Current General Purpose plans include: - **2 vCPU / 2 GB / 40 GB NVMe — $8.49/month** - **2 vCPU / 4 GB / 80 GB NVMe — $13.99/month** - **4 vCPU / 4 GB / 80 GB NVMe — $16.99/month** - **2 vCPU / 8 GB / 160 GB NVMe — $27.99/month** - **4 vCPU / 8 GB / 160 GB NVMe — $30.99/month** - **8 vCPU / 8 GB / 160 GB NVMe — $37.99/month** - **8 vCPU / 16 GB / 320 GB NVMe — $59.99/month** Raff also offers CPU-Optimized plans for workloads that require dedicated-vCPU allocation. This refresh does not publish CPU-Optimized prices because the buyer-facing comparison is anchored to the current General Purpose catalog. VM bandwidth is unmetered on a standard **3 Gbps** public port. Raff's current data-protection model uses a **free backup-and-snapshot storage pool** rather than the older three-slot model; additional protection storage is billed when the included pool is exceeded. Raff reports **3,000+ customers and 15,000+ VMs**, publishes a **99.9% uptime SLA**, and currently shows **4.5/5 on Trustpilot** and **4.6/5 on G2**. ## Azure Virtual Machines pricing vs Raff pricing The table below compares Raff General Purpose shared-vCPU plans with Azure Bsv2 low-memory Linux pay-as-you-go compute in East US. Azure figures are monthly equivalents at 730 hours and exclude managed disk, outbound transfer, snapshots, premium software, support, and other network services. | Matched resource class | Raff General Purpose | Azure Bsv2 Linux, East US | Difference before Azure add-ons | |---|---:|---:|---:| | 2 vCPU / 4 GB | **$13.99** with 80 GB NVMe | `B2ls v2` about **$30.37 compute only** | Raff about 54% lower | | 4 vCPU / 8 GB | **$30.99** with 160 GB NVMe | `B4ls v2` about **$107.31 compute only** | Raff about 71% lower | | 8 vCPU / 16 GB | **$59.99** with 320 GB NVMe | `B8ls v2` about **$215.35 compute only** | Raff about 72% lower | This is a **resource-and-price comparison, not a performance-equivalent match**. Raff General Purpose uses shared vCPU, while Azure Bsv2 uses a CPU-credit burst model with a 30% baseline on the selected sizes. For sustained CPU demand, Azure buyers should compare a non-burstable family, and Raff buyers should evaluate the dedicated-vCPU CPU-Optimized family. ### What Azure's compute price does not include The Azure Bsv2 compute figure does not include: - An OS managed disk - Additional data disks - Standard SSD transaction charges where applicable - Snapshot storage - Internet data transfer beyond the free allowance - Load Balancer, Application Gateway, Front Door, NAT Gateway, VPN, or ExpressRoute where used - Azure Backup or Site Recovery resources - Paid support - Windows Server or SQL Server software charges where applicable Azure Managed Disks are billed by disk type, capacity or performance tier, redundancy, and—in some cases—transactions. Azure snapshots are billed separately from the VM compute charge. Raff includes the listed NVMe capacity and unmetered VM transfer. Its current protection model uses a free backup-and-snapshot storage pool, with additional protection storage billed when the included pool is exceeded. ### Windows Server pricing and licensing Azure Windows VM pricing includes a Windows Server software component in the pay-as-you-go rate. Qualified customers can reduce eligible Windows Server licensing costs with Azure Hybrid Benefit when the applicable Microsoft licensing requirements are met. Raff provides hosted Windows VMs through its Windows VM product. Azure is stronger when an organization already operates Microsoft licensing agreements, Entra ID, Azure Virtual Desktop, or hybrid Microsoft infrastructure. Raff is simpler when the requirement is a conventional hosted Windows server without the surrounding Azure governance stack. :::cta Deploy Your Server Compare current Raff VM plans with included NVMe storage and unmetered bandwidth. ::: ## Bandwidth and transfer policy Raff VM plans include unmetered bandwidth on a standard **3 Gbps** public port. There is no per-GB public internet egress line item on normal VM plans. Azure internet ingress is free. For internet egress routed through Microsoft's Premium Global Network from North America or Europe, Azure currently includes the first **100 GB per month**, then charges **$0.087/GB for the next 10 TB**, **$0.083/GB for the next 40 TB**, and lower tiered rates at larger volumes. Microsoft defines 1 TB as 1,000 GB on the pricing page. | Monthly outbound transfer | Raff | Azure Premium Network from North America | |---:|---:|---:| | 1 TB | Included | About **$78.30** | | 5 TB | Included | About **$426.30** | | 10 TB | Included | About **$861.30** | | 20 TB | Included | About **$1,691.70** | | 50 TB | Included | About **$4,181.70** | Azure can lower some transfer costs through CDN, Front Door, routing preference, private connectivity, or architectures that keep traffic inside eligible boundaries. Inter-region transfer, cross-zone patterns, NAT, load balancing, and hybrid services can have separate pricing rules. Raff is easier to budget for public APIs, SaaS traffic, downloads, media, remote desktops, backup replication, and unexpected traffic spikes. Azure is stronger when global routing, private backbone paths, hybrid connectivity, and Microsoft network services are deliberately designed into the architecture. ## Feature comparison: Azure Virtual Machines vs Raff ### Compute | Feature | Raff | Azure Virtual Machines | |---|---|---| | Shared or burstable compute | General Purpose shared vCPU | B-series CPU-credit burstable VMs | | Dedicated compute | CPU-Optimized family available | Multiple fixed-performance and specialized families | | Current 4 vCPU / 8 GB anchor | $30.99 with 160 GB NVMe | `B4ls v2` about $107.31 compute only | | Bsv2 CPU baseline | Not applicable | 30% on B2ls/B4ls/B8ls v2 | | Autoscaling | Application/platform dependent | Virtual Machine Scale Sets | | Spot VMs | Not in current public VM catalog | Available with eviction risk | | GPUs and confidential VMs | Not in current public VM catalog | Available | | Linux and Windows | Available | Available; licensing affects price | Azure wins on VM-family breadth, accelerators, autoscaling, Spot capacity, confidential computing, and specialized infrastructure. Raff offers a shorter decision path for ordinary application infrastructure. ### Networking | Feature | Raff | Azure Virtual Machines | |---|---|---| | Public internet transfer | Unmetered at 3 Gbps | Tiered egress after 100 GB/month | | Private networking | Available | Virtual Network, peering, Private Link, Virtual WAN | | Firewall | Included platform controls | Network Security Groups, Azure Firewall, policy tooling | | IPv4 and IPv6 | Available | Available; SKU and architecture details vary | | Load balancing | Not used as a Raff advantage in this comparison | Load Balancer, Application Gateway, Front Door available | | Hybrid connectivity | Standard VPN integration patterns | VPN Gateway and ExpressRoute | | Geography | One `us-east` region | More than 70 regions | Azure is the stronger global and hybrid network platform. Raff is the simpler option for a `us-east` application stack with predictable public transfer. ### Storage & Backups | Feature | Raff | Azure Virtual Machines | |---|---|---| | Base VM storage | Included NVMe capacity | Managed disk billed separately | | Additional block storage | Volumes at $0.08/GB-month | Standard HDD, Standard SSD, Premium SSD, Premium SSD v2, Ultra Disk | | Snapshots | $0.06/GB-month | Full and incremental snapshot products | | Protection baseline | Free backup-and-snapshot storage pool | Azure Backup or snapshot schedules configured separately | | Disaster recovery | Backup, snapshots, and application design | Azure Site Recovery and broader enterprise DR tooling | | Object storage | S3-compatible Object Storage | Azure Blob Storage | Azure offers more storage tiers, performance controls, redundancy options, and enterprise recovery products. Raff provides a simpler VM-storage and protection workflow. ### Platform Features | Feature | Raff | Azure | |---|---|---| | Managed Kubernetes | Available | Azure Kubernetes Service | | Managed databases | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | Azure SQL, PostgreSQL, MySQL, Cosmos DB, and more | | Functions | Raff Functions | Azure Functions | | Application platform | Raff Apps | App Service, Container Apps, AKS, Functions | | Identity | Focused platform access controls | Microsoft Entra ID and enterprise IAM ecosystem | | Analytics and AI | Focused infrastructure platform | Fabric, Azure AI, and broad data services | | API, CLI, Terraform | Available | Extensive ARM APIs, Azure CLI, Bicep, Terraform ecosystem | Azure clearly wins on specialized services and Microsoft enterprise integration. Raff covers a compact application stack for teams that do not need the wider Azure portfolio. ### Pricing & Billing | Feature | Raff | Azure Virtual Machines | |---|---|---| | Billing choices | Subscription terms plus hourly PAYG options | Pay-as-you-go, reservations, savings plans, Spot | | Disk in advertised VM price | Included | Usually separate | | Internet transfer | Unmetered | Tiered after free allowance | | Protection baseline | Free backup-and-snapshot storage pool | Separately configured and billed | | Windows licensing | Hosted Windows VM product | License-included PAYG or eligible Azure Hybrid Benefit | | Cost optimization | Published plan choices and longer terms | Reservations, savings plans, Spot, Hybrid Benefit, Advisor | Azure provides more optimization levers. Raff requires less optimization work to understand the ordinary monthly VM bill. ### Trust & Operations | Feature | Raff | Azure | |---|---|---| | Scale signal | 3,000+ customers; 15,000+ VMs | Global hyperscale cloud | | Public rating | Trustpilot 4.5/5; G2 4.6/5 | Broad enterprise review and partner ecosystem | | SLA | 99.9% | SLA depends on VM and availability architecture | | Support | Direct 24/7 support | Documentation, community, partners, and paid support plans | | Compliance scope | Focused provider program | Extensive global and industry certifications | Azure wins on enterprise history, compliance breadth, global partner coverage, and architecture options. Raff offers a more direct support and product relationship. ### Infrastructure | Feature | Raff | Azure | |---|---|---| | Public region model | One region named `us-east` | More than 70 regions | | Availability zones | Raff region model | Available across many Azure regions | | Global private backbone | Focused provider network | Microsoft global network | | Hybrid cloud | Standard integration patterns | Azure Arc, ExpressRoute, VPN, Azure Local, enterprise tooling | | Best fit | Predictable `us-east` VM and managed application workloads | Global, regulated, Microsoft-centric, hybrid, AI, and enterprise systems | ## Performance benchmarks: Raff vs Azure Virtual Machines Raff has not completed a controlled, matched Azure Virtual Machines benchmark within the last 90 days. This page therefore does **not** claim that Raff or Azure is faster. A valid benchmark would need to match: - Region and network test endpoints - Linux distribution and kernel - vCPU and RAM - Shared, burstable, or dedicated CPU behavior - Azure CPU-credit balance and baseline utilization - Disk type, capacity, caching, IOPS, throughput, and transaction settings - Raff General Purpose or CPU-Optimized class - At least three passes per test - CPU, memory, fio, database, HTTP, and network workloads - Full monthly price including Azure disk and transfer assumptions The Bsv2 family is especially unsuitable for a casual one-pass comparison because CPU credits affect sustained performance. `B2ls v2`, `B4ls v2`, and `B8ls v2` have a 30% baseline and can burst when credits are available. Raff General Purpose uses shared vCPU, while CPU-Optimized uses dedicated vCPU; selecting the wrong Raff class would also distort the result. Until a controlled test is completed, use this page for pricing and architectural fit rather than performance claims. ## When you should choose Azure Virtual Machines over Raff Choose Azure when: - You need more than 70 regions, availability zones, or country-specific deployment options. - Your company standardizes on Microsoft Entra ID, Azure Policy, Defender for Cloud, Azure Monitor, or Microsoft enterprise agreements. - You need Azure Hybrid Benefit for eligible Windows Server licenses. - The workload requires Azure Virtual Desktop, AKS, Azure SQL, Cosmos DB, App Service, Functions, Fabric, or Azure AI services. - You need Virtual Machine Scale Sets, Spot VMs, confidential computing, GPUs, or HPC. - ExpressRoute, Virtual WAN, Private Link, Front Door, or advanced hybrid networking is central to the design. - Azure Backup, Site Recovery, enterprise governance, or extensive compliance certifications are mandatory. - The workload must operate across multiple regions or zones. ## When you should choose Raff over Azure Virtual Machines Choose Raff when: - You want **2 vCPU / 4 GB / 80 GB NVMe for $13.99/month**. - You want **4 vCPU / 8 GB / 160 GB NVMe for $30.99/month**. - You want unmetered VM bandwidth rather than tiered public egress. - The current free backup-and-snapshot storage pool fits ordinary protection requirements. - Your application uses conventional VMs, managed databases, Kubernetes, Apps, Functions, and object storage rather than deep Azure-native dependencies. - Your users and compliance requirements fit `us-east`. - You prefer direct support and fewer billing dimensions. Compare nearby decisions with [Raff versus Google Cloud](/learn/compare/raff-vs-google-cloud), [Raff versus Oracle Cloud](/learn/compare/raff-vs-oracle-cloud), and [Raff versus AWS Lightsail](/learn/compare/raff-vs-aws-lightsail). :::cluster ## Migrating from Azure Virtual Machines to Raff 1. **Inventory the Azure estate.** Record VMs, size families, managed disks, disk caching, snapshots, public IPs, Virtual Networks, NSGs, load balancers, NAT, DNS, Entra ID dependencies, extensions, backup vaults, and managed-service connections. 2. **Classify portable and Azure-native components.** Standard Linux or Windows servers, application files, containers, and common databases are usually portable. AKS, Azure SQL, Cosmos DB, Managed Identity, Key Vault, Private Link, Azure Files, Service Bus, and Azure Virtual Desktop need replacement or hybrid planning. 3. **Choose the Raff compute class.** Use General Purpose for shared-vCPU workloads or CPU-Optimized where dedicated-vCPU allocation is required. Match RAM, usable storage, IP requirements, private networking, firewall exposure, and protection requirements. 4. **Move applications and data.** Redeploy from source control, transfer files with rsync or secure copy, migrate databases with native dump/restore or replication, and move compatible object data through S3 tools. Windows applications may require service, registry, scheduled-task, and license validation. 5. **Rebuild identity and secrets.** Replace Managed Identity, Key Vault references, domain assumptions, Azure extensions, metadata-service calls, and Entra-dependent authentication where they are not portable. 6. **Validate before cutover.** Test TLS, application health, RDP or SSH access, database consistency, storage mounts, scheduled jobs, outbound email, backups, restore procedures, monitoring, and third-party allowlists through a temporary hostname. 7. **Cut over and remove residual charges.** Lower DNS TTL, perform the final sync, update A and AAAA records, monitor production, retain Azure for rollback, then delete unused VMs, disks, snapshots, public IPs, load balancers, NAT resources, backup vault data, and monitoring resources. Operational gotchas: - Azure public IP addresses cannot move to Raff. Update DNS, security allowlists, payment providers, SMTP relays, VPN peers, and vendor integrations. - Azure managed-disk snapshots are not directly attachable to Raff. Use file-, image-, application-, or database-level migration. - Windows Server activation, RDS access, SQL Server licensing, and third-party application licenses must be checked separately. - Managed Identity, Key Vault, Azure VM extensions, and Instance Metadata Service calls can fail after migration. ## About Azure Virtual Machines [Azure Virtual Machines](https://azure.microsoft.com/en-us/products/virtual-machines) is Microsoft's IaaS compute service for Linux and Windows. It operates within Azure's global network of more than 70 regions and connects to Microsoft's networking, identity, storage, database, analytics, AI, hybrid, security, and management services. ## Conclusion: Azure Virtual Machines or Raff? Raff is more suitable for ordinary production servers when the workload fits `us-east` and predictable infrastructure economics matter more than global enterprise breadth. Azure is more suitable when global placement, Microsoft integration, specialized VM families, or hybrid architecture are central requirements. - **Linux VM pricing:** Raff 4 vCPU / 8 GB / 160 GB is $30.99; Azure `B4ls v2` is about $107.31 for compute alone before disk and transfer. - **Bandwidth:** Raff is unmetered on a standard 3 Gbps port; Azure includes 100 GB and then uses tiered internet-egress pricing. - **Protection:** Raff uses a free backup-and-snapshot storage pool; Azure Backup and snapshots are separately configured and billed. - **CPU model:** Raff General Purpose is shared-vCPU; Azure Bsv2 is CPU-credit burstable with a 30% baseline on the selected sizes. - **Platform:** Azure wins on more than 70 regions, Microsoft integration, hybrid networking, scale sets, accelerators, enterprise governance, and specialized services. - **Performance evidence:** no matched benchmark is available, so neither provider is declared faster. Choose Azure for global, regulated, hybrid, Microsoft-centric, AI, or deeply Azure-native systems. Choose Raff for `us-east` Linux and Windows servers that benefit from included NVMe capacity, unmetered bandwidth, managed databases, Kubernetes, Apps, Functions, and direct support. Continue with [the U.S. cloud server decision guide](/learn/guides/choose-us-cloud-server-latency-compliance) or review [Raff Windows VM](/products/windows-vm) and [Raff VM](/products/raff-vm). --- ### Vultr Kubernetes Engine Alternative 2026: Pricing, Features & Operations URL: https://rafftechnologies.com/learn/compare/vultr-kubernetes-alternative Description: Compare Vultr Kubernetes Engine and Raff on VKE pricing, $0 control planes, workers, storage, bandwidth, regions, networking, and operations. Raff is the stronger Vultr Kubernetes alternative when your workloads fit `us-east` and you want a known $13.99/month 2 vCPU / 4 GB worker price, $0 public egress, $0.08/GB-month Kubernetes storage, and a $30/month three-master HA option. Vultr Kubernetes Engine is stronger when broader geographic placement, a wider virtual-compute catalog, Cloud GPU workers, Vultr-native Load Balancers, or lower-cost HDD Block Storage are requirements. Both providers currently publish a $0 standard managed control plane, so the real decision is not the headline Kubernetes fee; it is the cost and operating model around workers, networking, storage, load balancing, and failure headroom. Choose Vultr when its regional and compute breadth solve requirements you can name; choose Raff when a smaller `us-east` footprint with unmetered 3 Gbps bandwidth and zero egress charges produces the simpler production bill. Vultr Kubernetes Engine (VKE) and Raff both remove routine control-plane administration while keeping workload design, resource requests, application availability, data protection, and recovery with the customer. Vultr's current VKE pricing documentation says the fully managed control plane is provided at no additional cost and charges only for provisioned resources such as worker nodes, Load Balancers, and Block Storage. Raff follows the same $0-standard-control-plane model but publishes its Kubernetes worker, HA, storage, and transfer prices directly on the Kubernetes product page. The providers diverge most clearly on geography and infrastructure breadth: Vultr operates a much larger global cloud footprint and supports multiple virtual compute families, including Cloud GPU, while Raff currently concentrates managed Kubernetes in one public `us-east` region. ## Vultr Kubernetes Engine vs Raff: which is right for you? Vultr Kubernetes Engine is the stronger choice if you need to place clusters nearer users outside Raff's public region, mix node pools across a broader compute catalog, run GPU-accelerated Kubernetes workloads, or use Vultr's native Load Balancer, Block Storage, DNS, API, CLI, and Terraform ecosystem. Raff is the stronger choice when `us-east` is acceptable and you want published worker pricing plus a cluster bill with $0 egress and a known $30 HA add-on. | Decision factor | Choose Raff | Choose Vultr Kubernetes Engine | |---|---|---| | Standard control plane | $0 | $0 | | 2 vCPU / 4 GB worker | $13.99/month | Uses Vultr regional Cloud Compute pricing for `vc2-2c-4gb` | | HA control plane | Three masters for $30/month | Optional HA; current VKE pricing docs do not publish a separate HA surcharge | | Public egress | $0, unmetered up to 3 Gbps | Plan bandwidth allowance, then $0.01/GB overage | | Private networking | Private VPC for every cluster | Existing VPC or automatically provisioned same-region VPC | | Persistent storage | $0.08/GB-month | HDD $0.025/GB-month; NVMe $0.10/GB-month | | Managed load balancing | Managed public endpoint included | Vultr Load Balancer starts at $10/month | | Geography | `us-east` | Much broader Vultr global cloud footprint | | Specialized compute | Smaller Kubernetes worker catalog | Cloud Compute, Optimized/High Frequency classes, Cloud GPU, VX virtual compute | A practical Raff comparison rule is to price the **production path**, not the Kubernetes control-plane headline. Workers, failure headroom, public traffic, load balancing, storage class, and backups explain more of a real cluster bill than whether the control plane itself is advertised as free. This article therefore avoids a misleading matched-worker dollar claim where Vultr's current price cannot be verified directly. Vultr's official VKE and provisioning docs identify `vc2-2c-4gb` as a 2 vCPU / 4 GB Cloud Compute plan and direct buyers to Vultr's live regional pricing for the current hourly or monthly rate. That live pricing page was not reliably retrievable during this review, so the comparison keeps the Vultr worker price dynamic rather than copying an older number. ## Vultr Kubernetes Engine overview [Vultr Kubernetes Engine](https://www.vultr.com/kubernetes/), or VKE, is Vultr's fully managed Kubernetes service. Vultr manages the Kubernetes control plane and reconciles worker-node pools while customers choose cluster versions, node-pool capacity, autoscaling policy, networking, storage, workload configuration, and application recovery. The current VKE pricing model is straightforward at the top level: the **managed control plane costs $0**, and customers pay for the cloud resources attached to the cluster. Vultr's April 2026 pricing documentation names worker nodes, Vultr Load Balancers, and Block Storage as the billable resource categories. VKE integrates with Vultr's Cloud Controller Manager and Container Storage Interface. Those integrations let Kubernetes request Vultr networking, managed Load Balancers, and persistent Block Storage without the operator building every cloud integration manually. The current VKE release line supports Kubernetes 1.36.x, and Vultr's June 2026 changelog records worker-node images on Ubuntu 24.04 LTS. VKE also supports multiple node pools and both manual and automatic node-pool scaling. For networking, a new cluster can attach to an existing same-region VPC; if none is selected, VKE provisions a new VPC in the region by default. Teams that want private-only worker placement can use VPC-focused deployment options rather than exposing every node directly to the public internet. Vultr's compute breadth is a genuine advantage. Current VKE documentation supports virtual worker instances across Cloud Compute classes and Cloud GPU, and Vultr provides preconfigured VKE applications for AMD and NVIDIA GPU tooling. VKE does **not** currently support Vultr Bare Metal servers as worker nodes, so GPU and specialized-compute advantages should be understood as virtual-compute options rather than unrestricted access to every Vultr infrastructure product. Vultr's broader platform also includes Load Balancers, Block Storage, DNS, registries and automation through the Vultr API, CLI, and Terraform provider. For teams already operating on Vultr, that existing provider surface can matter as much as the Kubernetes control plane itself. ## Raff overview [Raff Kubernetes](/products/kubernetes) is a managed Kubernetes service with a free standard control plane, optional three-master HA, node-pool autoscaling, multiple worker pools, built-in monitoring and logs, private-by-default networking, and a managed public endpoint. Current Raff Kubernetes worker tiers are: | Worker | vCPU | RAM | Monthly price | |---|---:|---:|---:| | K8s Starter | 1 | 2 GB | $9.99 | | K8s Standard | 2 | 4 GB | $13.99 | | K8s Performance | 4 | 8 GB | $30.99 | | K8s High Memory | 8 | 16 GB | $59.99 | | K8s Large | 8 | 32 GB | $115.99 | | K8s Scale | 16 | 64 GB | $229.99 | The standard control plane remains **$0 at every listed size**. Optional high availability promotes the control plane to three masters with etcd quorum for **$30/month**. Kubernetes storage is **$0.08/GB-month**, and public cluster bandwidth is truly unmetered at up to **3 Gbps with $0 egress fees**. Every Raff cluster gets its own VPC and a managed public endpoint. Nodes stay on the private network while intended public traffic enters through the managed edge. This is conceptually similar to VKE's ability to use or automatically provision a same-region VPC, although the products package and expose the workflow differently. Raff deliberately has a smaller public-region and worker-class catalog than Vultr. That is a limitation when geography, GPU capacity, or a particular Vultr compute family is required. The trade-off is a narrower decision surface with exact published Kubernetes worker prices, one public region to reason about, and transfer costs that do not change with public egress volume. Raff currently reports **15,000+ VMs** on its platform and publishes a **99.9% uptime SLA** for managed Kubernetes. Those signals do not replace architecture review: application availability still depends on replica count, worker capacity, disruption behavior, ingress, storage, and external dependencies. ## Vultr Kubernetes Engine pricing vs Raff pricing Both Raff and VKE currently publish a **$0 standard control plane**, so the most useful comparison starts with the surrounding resources. Vultr's VKE cost documentation says workers are billed according to the selected Vultr compute plan's current hourly or monthly rate. Current provisioning examples use the `vc2-2c-4gb` Cloud Compute plan for **2 vCPUs and 4 GB RAM**, but Vultr directs customers to its live regional pricing page for the exact current price. Because that price was not reliably retrievable in this review, this article does not turn an older cached rate into a 2026 claim. Raff's K8s Standard plan is explicitly published at **$13.99/month for 2 vCPU / 4 GB**. | Cost component | Raff Kubernetes | Vultr Kubernetes Engine | |---|---:|---:| | Standard managed control plane | $0 | $0 | | 2 vCPU / 4 GB worker | $13.99/month | Live regional rate for `vc2-2c-4gb` | | HA control plane | $30/month | Optional; no separate current surcharge published in VKE pricing docs | | Managed public traffic entry | Included managed endpoint | Vultr Load Balancer starts at $10/month if used | | 100 GB persistent storage — lower-cost tier | $8/month | $2.50/month HDD Block | | 100 GB persistent storage — performance tier | $8/month | $10/month NVMe Block | | Public egress overage | $0 | $0.01/GB after plan allowance | This table exposes an important point that a single “storage price” would hide. Vultr's **HDD Block Storage at $25/TB-month ($0.025/GB-month)** is cheaper per GB than Raff's Kubernetes storage, while Vultr's **NVMe Block Storage at $100/TB-month ($0.10/GB-month)** is more expensive per GB than Raff's $0.08/GB-month storage. The correct choice depends on the workload's latency, IOPS, throughput, and durability requirements rather than the lowest unit price alone. ### High-availability pricing is documented differently Raff publishes a clear **$30/month** price for its three-master HA control plane. Vultr documents VKE high availability as an optional cluster setting available through the console, API, CLI, and Terraform. Its current VKE pricing page continues to state that the fully managed control plane is available at no additional cost and lists worker nodes, Load Balancers, and Block Storage as chargeable resources. Because the pricing documentation does not expose a separate VKE HA line item, this article does not invent one. If a Vultr quote or console estimate shows an HA-specific charge for your region or account, use that live value instead of this article's generic pricing model. ### Load-balancer pricing can change the ingress model Vultr Load Balancers currently start at **$10/month per instance**. They are bandwidth-neutral themselves: traffic is accounted against attached backend instances, and outbound usage above the applicable compute-plan allowance is billed at the standard overage rate. Raff includes a managed public endpoint and automatic TLS with the cluster. That does not make every application ingress design identical to a Vultr Load Balancer, but it means teams should include ingress/LB resources when comparing actual deployment architectures rather than comparing only node counts. :::cta cluster Compare your production Kubernetes floor on Raff with a $0 standard control plane, published worker pricing, and $0 public egress. ::: ## Bandwidth and transfer policy Raff Kubernetes prices public egress at **$0** and includes truly unmetered bandwidth at up to **3 Gbps**. Same-platform traffic between a Raff cluster and Raff storage is also not metered. Vultr uses a quota model for compute-instance bandwidth. Each instance plan includes a monthly allowance, and outbound traffic above the account's applicable allocation is billed at **$0.01/GB**. Vultr Load Balancers do not add a second bandwidth charge; backend-instance egress remains the relevant meter. Vultr also documents a free account-level bandwidth allocation, but the amount available to a particular production estate depends on current plan and account rules. For that reason, a VKE cost model should use the actual node plan and account allocation shown in the Vultr console rather than assuming a generic transfer allowance from an older price table. This distinction matters differently by workload. A private internal API with little outbound traffic may never approach Vultr's allowance, making the bandwidth difference financially irrelevant. A public API, package distribution service, media workload, software update system, or customer-export pipeline can make predictable egress economics more valuable. The comparison should therefore be phrased precisely: **Raff removes the public-egress variable; Vultr includes bandwidth and charges $0.01/GB when applicable allowance is exceeded.** That is not the same as saying every VKE workload pays egress fees. ## Feature comparison: Vultr Kubernetes Engine vs Raff | Feature | Raff Kubernetes | Vultr Kubernetes Engine | |---|---|---| | Standard control plane | $0 | $0 | | Optional control-plane HA | Three masters, $30/month | Yes | | Multiple node pools | Yes | Yes | | Node-pool autoscaling | Yes | Yes | | Standard private networking | Per-cluster VPC | Existing or auto-created same-region VPC | | VPC-only/private worker options | Private-by-default Raff model | Supported VPC-focused deployment options | | Public endpoint / LB | Managed endpoint included | Vultr Load Balancer integration | | Managed LB entry price | Included endpoint | Starts at $10/month | | Persistent storage | $0.08/GB-month | HDD $0.025/GB-month; NVMe $0.10/GB-month | | Public egress | $0 | Included allowance, then $0.01/GB overage | | Public region model | `us-east` | Broader Vultr global cloud footprint | | GPU Kubernetes workers | No published GPU worker tier | Cloud GPU supported | | Bare Metal workers | No published Kubernetes Bare Metal tier | Not supported by current VKE | | Kubernetes version management | Managed control plane and cluster workflow | VKE upgrade workflow; worker upgrades require operator action in current docs | | Cloud integrations | Raff storage, VPC, apps, managed data services | Vultr LB, Block Storage, DNS, CCM/CSI integrations | | API / CLI / Terraform | Raff platform automation | Vultr API, CLI, Terraform | | Ingress controller included | One-click networking apps available | No preconfigured ingress controller | | Built-in monitoring/logs | Included in Raff dashboard | Vultr platform monitoring plus Kubernetes ecosystem tooling | Vultr wins on geographic breadth, virtual compute variety, GPU-capable Kubernetes infrastructure, a mature provider automation surface, and its lower-cost HDD storage tier. Raff wins on exact published Kubernetes worker pricing, $0 public egress, the $30 published HA option, included managed public endpoint, and a single-region operating model that can be simpler when `us-east` already satisfies the application. VKE's automatic VPC creation is also a meaningful operational strength. A team moving to VKE does not need to start with publicly exposed worker nodes simply because it has not pre-created a network. Raff similarly makes private networking the default, so this is closer to feature parity than a decisive difference. ## Features and reliability: Raff vs Vultr Kubernetes Engine This comparison includes **0 controlled Raff-versus-VKE workload benchmarks**, so it does not declare either platform faster. A defensible Kubernetes benchmark would need matched worker CPU classes, Kubernetes versions, node counts, Pod requests, storage class, CNI behavior, region, container image, traffic profile, and repeated test runs. ### VKE manages platform state but operators still own workload state Vultr's current documentation describes VKE as managing the control plane and worker-node lifecycle. If a worker is deleted outside the VKE dashboard, the platform detects the missing node and provisions a replacement to restore the desired node-pool size. That is useful infrastructure reconciliation, but replacement does not preserve application state that lived only on an ephemeral node disk. Raff follows the same managed-Kubernetes boundary. Control-plane operations and worker reconciliation reduce platform toil; they do not replace PersistentVolumes, database backups, object-storage durability, application replication, or tested restores. ### Upgrade workflows still require planning Vultr documents managed control-plane upgrades and states that worker nodes must be upgraded by the customer, individually or in batches, to align with the selected Kubernetes version. Its current VKE release line supports Kubernetes 1.36.x and uses Ubuntu 24.04 LTS worker images. That is not necessarily a disadvantage: explicit worker upgrade control can be valuable when teams want to choose disruption windows. It does mean that “managed Kubernetes” should not be interpreted as “no upgrade planning.” PodDisruptionBudgets, replica headroom, maintenance windows, and version-dependent operators remain customer concerns on either provider. ### Storage choices trade cost for performance Vultr gives VKE users two Block Storage performance tiers. HDD Block is the lower-cost capacity option; NVMe Block targets much higher IOPS and throughput. That choice is a real Vultr advantage for teams that want a cheaper bulk-capacity tier beside performance storage. Raff publishes one Kubernetes storage rate at $0.08/GB-month, reducing the number of storage billing choices. A simpler catalog can make cost review easier, but it does not beat Vultr HDD on raw dollars per GB. ## When you should choose Vultr Kubernetes Engine over Raff Choose Vultr Kubernetes Engine when: - **You need broader geographic placement.** Vultr operates a much larger global cloud footprint than Raff's current single public `us-east` region, although specific VKE/plan availability should still be checked before deployment. - **GPU workers are required.** Current VKE documentation supports Cloud GPU virtual instances and GPU-oriented applications; Raff does not publish a Kubernetes GPU worker tier. - **You need more virtual compute classes.** VKE can use several Vultr virtual compute families rather than a single small Kubernetes-specific catalog. - **Low-cost capacity storage matters.** Vultr HDD Block Storage is $25/TB-month, or about $0.025/GB-month, below Raff's $0.08/GB-month Kubernetes storage rate. - **Vultr-native networking and storage already exist in your estate.** VPC, Load Balancers, Block Storage, DNS, CCM, and CSI integrations can reduce migration work for teams already standardized on Vultr. - **API, CLI, and Terraform maturity are important.** Vultr exposes VKE provisioning and HA controls through all three automation paths. - **You want explicit VPC attachment or automatic same-region VPC creation.** VKE can attach an existing same-region VPC or provision one automatically when you do not select one. These are genuine reasons to stay on or select VKE. A lower Raff worker price or zero-egress model does not compensate for a missing region or GPU requirement when those are architectural constraints. ## When you should choose Raff over Vultr Kubernetes Engine Choose Raff Kubernetes when: - **You want an exact published Kubernetes worker price.** Raff lists 2 vCPU / 4 GB at $13.99/month directly on the Kubernetes page instead of requiring a separate regional compute-price lookup. - **Public egress should remain $0.** Raff removes outbound transfer overage from the cluster bill; Vultr charges $0.01/GB when applicable allowance is exceeded. - **You want a published HA add-on price.** Raff's three-master HA option is $30/month. Vultr supports HA, but its current VKE pricing documentation does not expose a separate HA surcharge. - **An included public endpoint fits the ingress model.** Raff includes a managed public endpoint and TLS; Vultr Load Balancers start at $10/month when used. - **The workload belongs in `us-east`.** Vultr's global footprint adds little value if one eastern-U.S. region already satisfies latency, residency, and resilience requirements. - **You prefer fewer infrastructure choices.** Raff's smaller worker and region catalog can make routine cluster sizing and cost review easier for small teams that do not need GPU or specialized compute. - **The storage workload fits Raff's single $0.08/GB-month tier.** That rate is below Vultr NVMe Block's $0.10/GB-month, although Vultr HDD remains cheaper for capacity-first storage. For the broader operating-model decision, read [Managed Kubernetes vs Self-Managed Kubernetes](/learn/guides/managed-vs-self-managed-kubernetes) before comparing provider line items in isolation. ## Migrating from Vultr Kubernetes Engine to Raff Moving from VKE to Raff is mainly a Kubernetes workload migration plus a provider-integration migration. Standard manifests and Helm charts are portable; Vultr-specific networking, storage, load-balancer behavior, registry credentials, and persistent data need deliberate replacement. 1. **Inventory the VKE cluster.** Record Kubernetes version, node pools, autoscaling ranges, Cloud Compute classes, GPU pools, namespaces, Helm releases, CRDs, NetworkPolicies, ingress controllers, Vultr Load Balancers, Block Storage claims, storage classes, VPC configuration, DNS, secrets, and backup jobs. 2. **Create the Raff target cluster.** Choose standard or HA control plane, worker plans, node counts, autoscaling bounds, private VPC, storage capacity, public endpoint, and monitoring requirements. 3. **Replace Vultr-specific integrations.** Review Vultr CCM behavior, Vultr CSI storage classes, Load Balancer annotations, VPC assumptions, GPU operators, and DNS automation. **Gotcha:** provider-specific annotations often remain in exported YAML even when the new provider ignores them. 4. **Move persistent data separately.** Kubernetes object definitions do not contain the data inside Vultr Block Storage or external databases. Use database-native replication/export, application-aware backup tools, or a verified data-copy process. 5. **Recreate ingress intentionally.** VKE does not ship with a preconfigured ingress controller, so document whether the source cluster uses NGINX, Traefik, Gateway API, direct LoadBalancer Services, or another controller before mapping public traffic to the Raff endpoint and in-cluster networking. 6. **Verify workload behavior.** Test readiness and liveness probes, autoscaling, PVC binding, DNS, NetworkPolicies, jobs, logs, external integrations, and restore procedures before any production traffic moves. 7. **Cut over with rollback.** Lower DNS TTL to **300 seconds** before the migration window, synchronize final state, update DNS and allowlists, monitor production, and keep VKE recoverable until the rollback window closes. If the application is also moving from Docker Compose into Kubernetes, separate those two changes where practical. The [Docker Compose to Managed Kubernetes Migration Checklist](/learn/guides/docker-compose-to-managed-kubernetes-migration) defines the state, health-check, configuration, cutover, and rollback gates before a provider move adds another variable. ## About Vultr Kubernetes Engine [Vultr Kubernetes Engine](https://docs.vultr.com/products/compute/kubernetes) is Vultr's managed Kubernetes product. It combines a managed control plane with worker-node pools on supported Vultr virtual compute, Vultr Cloud Controller Manager, Vultr CSI, VPC networking, autoscaling, Load Balancer integration, Block Storage, and provider automation. Vultr currently operates **33 global cloud data center regions** across its broader infrastructure footprint. VKE availability and the exact compute families available to a cluster can vary by region, so teams should verify the target location and plan before treating the full Vultr region map as guaranteed VKE coverage. The standard VKE control plane is published at **$0**. Workers use the selected Vultr compute plan and bill at its current regional hourly or monthly rate. Vultr Load Balancers start at **$10/month**, outbound bandwidth overage is **$0.01/GB** after applicable allowance, and Block Storage is available in HDD and NVMe tiers. VKE also supports optional high availability, multiple node pools, autoscaling, API/CLI/Terraform provisioning, and Cloud GPU workers. It does not currently support Vultr Bare Metal servers as VKE worker nodes. ## Conclusion: Vultr Kubernetes Engine or Raff? The Vultr-Kubernetes-versus-Raff decision is strongest when it is reduced to four concrete axes: geography and compute choice, known recurring cluster costs, transfer economics, and storage/ingress design. - **Geography and compute:** Vultr wins with a much broader global footprint and more virtual compute choices, including Cloud GPU. Raff currently operates managed Kubernetes in `us-east` with a smaller worker catalog. - **Published cluster costs:** both standard control planes are $0. Raff publishes 2 vCPU / 4 GB workers at $13.99/month and HA at $30/month; Vultr bills workers at current regional compute rates and does not expose a separate HA surcharge in its current VKE pricing documentation. - **Transfer:** Raff public Kubernetes egress is $0 with unmetered bandwidth up to 3 Gbps. Vultr includes plan bandwidth and charges $0.01/GB when applicable allowance is exceeded. - **Storage and ingress:** Vultr HDD Block is cheaper per GB than Raff storage, while Vultr NVMe Block is more expensive per GB; Vultr Load Balancers start at $10/month, while Raff includes a managed public endpoint. Choose VKE when its regions, compute classes, GPU support, lower-cost HDD tier, or Vultr-native integrations solve a real requirement. Choose Raff when `us-east` fits and published worker/HA pricing plus $0 egress make the production Kubernetes floor easier to forecast. Continue with [Kubernetes Cluster Sizing](/learn/guides/kubernetes-cluster-sizing), [Kubernetes Node Pools](/learn/guides/kubernetes-node-pools), and [Managed Kubernetes vs Self-Managed Kubernetes](/learn/guides/managed-vs-self-managed-kubernetes). --- ### Linode Kubernetes Engine Alternative 2026: Pricing, Features & Operations URL: https://rafftechnologies.com/learn/compare/linode-kubernetes-alternative Description: Considering Linode Kubernetes? Raff's 2 vCPU/4 GB worker is $13.99/mo, with $30 HA and $0 public egress in us-east. Raff wins on lower comparable worker pricing, a $30 HA control-plane add-on, $0 public egress, $0.08/GB-month cluster storage, and private VPC networking on its standard managed Kubernetes service. Linode Kubernetes Engine wins on broader regional availability, dedicated and high-memory worker choices, GPU support, mature Akamai Cloud tooling, and an Enterprise tier with a dedicated HA control plane. Choose LKE when geographic reach, specialized workers, or LKE Enterprise scale are requirements; choose Raff when `us-east` fits and predictable worker, HA, storage, and transfer costs matter more. Three 2 vCPU / 4 GB workers plus HA cost $71.97/month on Raff versus at least $132/month on standard LKE in North America before storage, NodeBalancers, and other attached services. Linode Kubernetes Engine and Raff both remove routine control-plane administration while leaving workload architecture, resource requests, policies, application availability, persistent data, and recovery with the customer. Standard LKE and Raff both advertise a $0 base control plane, but the production cost floor differs once worker nodes and HA are included: Akamai's current North America LKE table lists three Shared 4 GB workers at $72/month and its HA add-on starts at $60/month, while Raff prices three 2 vCPU / 4 GB workers at $41.97/month and three-master HA at $30/month. LKE offers a wider infrastructure and geographic surface; Raff focuses on `us-east`, lower published worker and storage prices, private-by-default cluster networking, and $0 public egress. ## Linode Kubernetes Engine vs Raff: which is right for you? Linode Kubernetes Engine is the stronger choice when your cluster needs Akamai's broader core-region footprint, dedicated CPU or GPU node options, or the Enterprise tier's dedicated HA control plane and higher cluster limits. Raff is the stronger fit when the workload belongs in `us-east` and you want a smaller managed Kubernetes cost surface with lower published worker, HA, storage, and transfer costs. | Decision factor | Choose Raff | Choose Linode Kubernetes Engine | |---|---|---| | 2 vCPU / 4 GB worker | $13.99/month | $24/month Shared CPU | | Three 2 vCPU / 4 GB workers | $41.97/month | $72/month | | HA control plane | $30/month | Starts at $60/month, region-dependent | | Standard private cluster network | Each cluster gets a private VPC | Standard LKE lists VPC-isolated networking as unavailable; Enterprise includes it | | Public egress | $0, unmetered up to 3 Gbps | Worker plans include transfer; Akamai lists overage pricing | | Persistent storage | $0.08/GB-month | Block Storage $0.10/GB-month | | Geography | `us-east` fits | You need LKE across Akamai core compute regions | | Specialized workers | Raff worker tiers are sufficient | Dedicated CPU, High Memory, or GPU nodes are required | | Enterprise Kubernetes | Standard managed Kubernetes is enough | LKE Enterprise's dedicated HA plane and higher limits are required | A practical comparison rule from Raff's infrastructure work is to separate the **free-control-plane headline** from the **production floor**. Worker nodes, HA, persistent storage, public traffic, load balancing, and surrounding services determine what a real cluster costs; the $0 control plane by itself does not. This comparison uses published service capabilities and prices. It does not treat equal vCPU and RAM counts as proof of equal compute performance because the providers do not publish an identical CPU-scheduling and hardware taxonomy for these Kubernetes worker tiers. ## Linode Kubernetes Engine overview [Linode Kubernetes Engine](https://techdocs.akamai.com/cloud-computing/docs/linode-kubernetes-engine), or LKE, is Akamai Cloud's managed Kubernetes service. Akamai manages the control plane while customers configure node pools, workloads, policies, application availability, storage, and recovery. Akamai currently offers two Kubernetes tiers: - **LKE** is the standard service. Its fully managed control plane uses shared resources and is provided at no additional charge. It is **not highly available by default**; HA is an optional paid add-on. - **LKE Enterprise** uses a dedicated HA control plane and adds enterprise-oriented networking, scaling, security, and load-balancing capabilities. It is available to approved customers in limited regions and costs **$300/month per cluster**, plus worker nodes and other consumed resources. Standard LKE supports up to **250 worker nodes and 1,000 Pods**. LKE Enterprise raises those published limits to **500 nodes and 5,000 Pods**, uses Cilium instead of standard LKE's Calico CNI, provides VPC-isolated pod networking, and can use Premium NodeBalancers. Both tiers support node-pool autoscaling, node-pool data encryption, automated Kubernetes version updates, GPU workers, and Akamai App Platform. For worker capacity, LKE can use Shared CPU, Dedicated CPU, and High Memory Linode plans, with GPU support also documented. This is one of LKE's clearest advantages over a smaller Kubernetes worker catalog: teams can choose among more compute classes when CPU isolation, memory density, or accelerators are architectural requirements. Akamai also exposes mature operational tooling around LKE through Cloud Manager, the Linode CLI, API access, and Terraform. That tooling matters for teams already standardized on Akamai Cloud automation. ## Raff overview [Raff Kubernetes](/products/kubernetes) is a managed Kubernetes service with a **$0 standard control plane**, optional three-master HA, node-pool autoscaling, multiple worker pools, built-in monitoring and logs, a managed public endpoint, and private-by-default cluster networking. Current Raff worker tiers are: | Worker | vCPU | RAM | Monthly price | |---|---:|---:|---:| | K8s Starter | 1 | 2 GB | $9.99 | | K8s Standard | 2 | 4 GB | $13.99 | | K8s Performance | 4 | 8 GB | $30.99 | | K8s High Memory | 8 | 16 GB | $59.99 | | K8s Large | 8 | 32 GB | $115.99 | | K8s Scale | 16 | 64 GB | $229.99 | The standard control plane remains **$0 at every listed worker size**. The HA option promotes the control plane to three masters with etcd quorum for **$30/month**. Dedicated cluster storage is **$0.08/GB-month**, and the current product page lists public bandwidth as truly unmetered at up to **3 Gbps with $0 egress fees**. Every Raff cluster gets a private VPC and a managed public endpoint for traffic that should be exposed. That differs from standard LKE's current feature table, which lists VPC-isolated networking as an Enterprise-only capability. Teams should still design Kubernetes NetworkPolicies, service exposure, ingress, secrets, and application-level controls deliberately; a private network is a foundation, not a complete security policy. Raff currently reports **15,000+ VMs** on its platform and publishes a **99.9% uptime SLA**. The product trade-off is straightforward: Raff exposes a narrower public-region and worker-class footprint than Akamai, but makes the standard small-team cluster model easier to price in `us-east`. ## Linode Kubernetes Engine pricing vs Raff pricing The cleanest LKE-to-Raff comparison starts with the standard managed control plane and worker floor, then adds HA and storage. Akamai's current North America pricing page lists the standard LKE control plane at no additional cost and three **Shared 4 GB** nodes at **$72/month total**. That Shared 4 GB plan corresponds to **2 vCPUs, 4 GB RAM, 80 GB storage, and 4 TB transfer per node**. The optional LKE HA control plane starts at **$60/month per cluster, depending on region**. Raff prices its K8s Standard worker at **$13.99/month for 2 vCPU / 4 GB**, so three workers total **$41.97/month**. Raff HA is **$30/month**. | Buying position | Raff Kubernetes | Linode Kubernetes Engine | Difference | |---|---:|---:|---:| | One 2 vCPU / 4 GB worker | $13.99/month | $24/month Shared CPU | Raff is $10.01 lower | | Three 2 vCPU / 4 GB workers | $41.97/month | $72/month | Raff is $30.03 lower | | HA control plane | $30/month | Starts at $60/month | Raff is at least $30 lower | | Three workers + HA | $71.97/month | At least $132/month | Raff is at least $60.03 lower | | Persistent storage | $0.08/GB-month | $0.10/GB-month | Raff is $0.02/GB-month lower | | LKE Enterprise control plane | No separate enterprise tier | $300/month plus resources | LKE adds a dedicated enterprise tier | **Comparison class:** these rows compare published resource shapes and prices, not measured application performance. Shared CPU scheduling, underlying hardware, CNI behavior, storage paths, Kubernetes versions, and cluster configuration can affect real workload results. The LKE Enterprise price is not directly comparable to Raff's $30 HA add-on because Enterprise includes a different control-plane and networking model. Its **$300/month** fee buys dedicated HA control-plane resources and enterprise capabilities rather than simply replicating the standard shared control plane. For small and midsize production clusters, the more useful comparison is standard LKE plus HA versus Raff plus HA. On that basis, three 2 vCPU / 4 GB workers produce a published monthly floor of **$71.97 on Raff** versus **at least $132 on LKE** before attached storage, load balancing, databases, or other services. ### Persistent storage cost Akamai Block Storage is currently **$0.10/GB-month** in North America: 100 GB costs $10/month. Raff Kubernetes storage is **$0.08/GB-month**, so 100 GB costs $8/month. Neither storage price is a backup policy. Persistent volumes survive Pod replacement, but databases and application state still need a backup schedule, consistency model, retention policy, and tested restore procedure. :::cta cluster Deploy a Raff Kubernetes cluster with a $0 standard control plane; add three-master HA for $30/month when your availability model requires it. ::: ## Bandwidth and transfer policy Raff Kubernetes currently includes truly unmetered public bandwidth at up to **3 Gbps** and prices public egress at **$0**. Same-platform cluster-to-storage traffic is also not metered. Akamai's Shared CPU plans include a transfer allowance with each worker. The current North America Shared 4 GB plan includes **4 TB of transfer per node**, and Akamai's regional pricing page lists outbound transfer overage at **$0.005/GB**. The exact invoice can depend on the account's eligible transfer pool and the mix of attached services, so a production estimate should be built from the actual node and service configuration rather than a single-node allowance alone. For a three-node Shared 4 GB LKE cluster, the pricing table lists **12 TB aggregate transfer** across those workers. That is a substantial included allowance and may be entirely sufficient for many workloads. Raff's advantage is not that LKE always produces a bandwidth bill; it is that Raff removes the public-egress variable from the Kubernetes bill altogether. This matters most for workloads with large or unpredictable outbound traffic: APIs with bursty responses, downloads, package distribution, media delivery, build artifacts, and data-heavy customer exports. For low-egress internal applications, the difference may be operationally irrelevant. ## Feature comparison: Linode Kubernetes Engine vs Raff | Feature | Raff Kubernetes | Linode Kubernetes Engine | |---|---|---| | Standard managed control plane | $0 | $0 | | HA control plane | Three masters, $30/month | Optional, starts at $60/month | | 2 vCPU / 4 GB worker | $13.99/month | $24/month Shared CPU | | Node-pool autoscaling | Yes | Yes | | Multiple node pools | Yes | Yes | | Dedicated CPU worker class | No separately published Kubernetes class | Yes | | GPU workers | No published Kubernetes GPU tier | Yes | | Standard private/VPC-isolated cluster model | Private VPC included | Standard LKE feature table: No; Enterprise: Yes | | Standard CNI | Standard Kubernetes networking managed by Raff | Calico | | Enterprise CNI | No separate enterprise tier | Cilium on LKE Enterprise | | Public region model | `us-east` | Most Akamai core compute regions | | Public egress | $0 | Included transfer, then applicable overage | | Persistent storage | $0.08/GB-month | Block Storage $0.10/GB-month | | Built-in monitoring/logs | Yes | Control-plane monitoring plus ecosystem tooling | | API / CLI / Terraform | Raff API, CLI, Terraform workflows | Cloud Manager, Linode CLI, API, Terraform | | Enterprise Kubernetes tier | No separate tier | LKE Enterprise, $300/month plus resources | | Published standard cluster scale | Size through Raff worker/node-pool model | Up to 250 nodes / 1,000 Pods | | Published enterprise scale | No separate enterprise limit | Up to 500 nodes / 5,000 Pods | LKE's strongest advantages are infrastructure breadth, geography, specialized compute, GPU support, and an Enterprise tier designed for larger deployments. Raff's strongest advantages are the lower published worker and HA examples above, lower storage unit price, private cluster networking in the standard service, and $0 public egress. The platforms also differ in how much product surface they ask a small team to choose from. Akamai offers more infrastructure classes and enterprise variants. Raff deliberately offers fewer Kubernetes worker tiers and one public region. Neither model is universally better: breadth is valuable when you need it, while a smaller decision surface can be useful when you do not. ## Features and reliability: Raff vs Linode Kubernetes Engine This comparison includes **0 controlled Raff-versus-Linode Kubernetes Engine workload benchmarks**, so it does not declare either service faster. A useful performance test would need matched Kubernetes versions, node counts, CPU classes, Pod requests, CNI configuration, storage paths, regions, images, traffic patterns, and repeated runs. ### Control-plane availability Standard LKE uses shared control-plane resources and is **not HA by default**. Akamai's HA add-on replicates etcd and the API server from one to three replicas and replicates other control-plane components, with the feature starting at $60/month. Akamai documents a **99.9% uptime guarantee for the control plane and worker-node API service** when HA is enabled. LKE Enterprise makes the control plane dedicated and highly available by default. That is a genuine advantage for teams that need a larger managed-Kubernetes operating envelope, and it is not the same product position as standard LKE. Raff's optional HA model also uses three masters with etcd quorum and costs $30/month. Raff publishes a **99.9% uptime SLA** for the Kubernetes service. In both cases, control-plane HA does not make an application automatically highly available: replicas, worker headroom, Pod disruption behavior, ingress, persistent data, and external dependencies still determine whether the workload survives failures. ### Allocatable worker capacity Akamai changed LKE resource allocation for clusters created on or after **April 21, 2026** by reserving some node CPU and memory for system daemons. Akamai notes that tightly packed workloads may need additional node capacity as a result. This is a useful reminder for both providers: size Kubernetes against **allocatable** worker capacity and failure headroom, not only the vCPU and RAM printed on the plan card. For Raff, use [Kubernetes Cluster Sizing](/learn/guides/kubernetes-cluster-sizing) to model allocatable worker capacity and [Kubernetes Node Pools](/learn/guides/kubernetes-node-pools) when workloads need distinct compute or scaling boundaries. ### Stateful recovery Both platforms separate managed control-plane operations from application data protection. Akamai continuously backs up control-plane metadata for recovery, but that does not replace customer backups for databases, PersistentVolumes, object data, manifests, and application state. Raff follows the same workload-responsibility principle: cluster availability and application recovery are related but separate concerns. ## When you should choose Linode Kubernetes Engine over Raff Choose Linode Kubernetes Engine when: - **Broader geographic placement is required.** Standard LKE is available across most Akamai core compute regions, while Raff currently exposes one public `us-east` region. - **Dedicated CPU workers matter.** LKE can use Dedicated CPU plans in addition to Shared CPU and High Memory workers. - **GPU workers are required.** Akamai documents GPU support for both LKE and LKE Enterprise; Raff does not currently publish a Kubernetes GPU worker tier. - **You need a larger published cluster envelope.** Standard LKE publishes limits of 250 nodes and 1,000 Pods, while Enterprise raises those to 500 nodes and 5,000 Pods. - **A dedicated enterprise control plane is required.** LKE Enterprise provides a dedicated HA control plane, Cilium, VPC-isolated pod networking, and enterprise load-balancing options. - **Your team already uses Akamai Cloud automation.** Cloud Manager, Linode CLI, API, Terraform, NodeBalancers, Block Storage, and App Platform can reduce integration work inside an existing Akamai estate. - **Included transfer covers your workload.** Three Shared 4 GB LKE workers list 12 TB of aggregate transfer, which can be enough for many applications without overage. These are substantive advantages. A team should not choose Raff simply because its comparable published worker price is lower if region placement, GPU capacity, dedicated CPU, or LKE Enterprise capabilities are hard requirements. ## When you should choose Raff over Linode Kubernetes Engine Choose Raff Kubernetes when: - **Published worker cost is a primary constraint.** The 2 vCPU / 4 GB Raff worker is $13.99/month versus $24/month for LKE's Shared 4 GB worker in North America. - **Production HA should stay inexpensive.** Raff three-master HA is $30/month; standard LKE HA starts at $60/month depending on region. - **You want $0 public egress.** Raff removes outbound-transfer overage from the Kubernetes bill instead of relying on a finite included allowance. - **Persistent storage unit cost matters.** Raff storage is $0.08/GB-month versus Akamai Block Storage at $0.10/GB-month in North America. - **Private networking should be part of the standard cluster model.** Raff places every cluster in a private VPC; Akamai's current comparison table reserves VPC-isolated networking for LKE Enterprise. - **The workload belongs in `us-east`.** Akamai's region breadth provides no practical benefit when one eastern-U.S. region already satisfies latency, residency, and resilience requirements. - **A smaller operational surface is preferable.** Raff's worker catalog and cluster workflow are narrower than Akamai's, which can make sizing and cost review simpler for ordinary small-team workloads. Raff currently reports **15,000+ VMs** and publishes a **99.9% uptime SLA**. For operating-model context before changing providers, read [Managed Kubernetes vs Self-Managed Kubernetes](/learn/guides/managed-vs-self-managed-kubernetes). ## Migrating from Linode Kubernetes Engine to Raff A Kubernetes migration is portable at the API level, but provider integrations and persistent data still require explicit work. Treat the move as an application and infrastructure migration rather than a `kubectl get -o yaml` exercise. 1. **Inventory the LKE cluster.** Record Kubernetes version, LKE tier, node pools, autoscaling ranges, namespaces, Helm releases, CRDs, NetworkPolicies, ingress, NodeBalancers, Block Storage claims, storage classes, secrets, DNS, external allowlists, CI/CD credentials, and backup workflows. 2. **Create the Raff target cluster.** Select the control-plane mode, worker sizes, node counts, autoscaling ranges, private VPC, persistent storage, public endpoint, and monitoring configuration. 3. **Replace provider-specific integrations.** Review Linode Cloud Controller Manager behavior, NodeBalancer annotations, Block Storage CSI classes, Akamai-specific load-balancer settings, and any App Platform assumptions. **Gotcha:** provider-specific annotations can survive an export and either fail or behave differently on the destination. 4. **Move persistent data separately.** Kubernetes manifests recreate resource definitions; they do not contain the data inside Block Storage volumes or external databases. Use database-native replication/export, application-aware backups, or a verified copy workflow appropriate to the state. 5. **Deploy and verify workloads.** Apply CRDs and operators before dependent resources, then verify Pods, Services, ingress, NetworkPolicies, PVCs, jobs, autoscaling, logs, readiness, and restore procedures. **Gotcha:** standard LKE uses Calico while LKE Enterprise uses Cilium, so policy and networking behavior deserve explicit validation. 6. **Cut over with a written rollback path.** Lower DNS TTL to **300 seconds** before the window, synchronize final state, update DNS and allowlists, monitor production, and keep the LKE environment recoverable until the rollback window closes. For workloads moving from Docker Compose into Kubernetes at the same time, do not combine both transitions blindly. Use the [Docker Compose to Managed Kubernetes Migration Checklist](/learn/guides/docker-compose-to-managed-kubernetes-migration) first so state, probes, configuration, traffic ownership, and rollback are explicit before provider migration adds another variable. ## About Linode Kubernetes Engine [Linode Kubernetes Engine](https://www.akamai.com/products/kubernetes) is the managed Kubernetes product within Akamai Cloud. Akamai acquired Linode in 2022 and continues to use the LKE product name across its current Kubernetes documentation and pricing. The standard LKE service provides a managed shared control plane at no additional charge, worker-node pools using eligible Linode compute plans, autoscaling, Kubernetes version management, Block Storage integration, NodeBalancer integration, and access through Cloud Manager, CLI, API, and Terraform workflows. LKE Enterprise is a distinct paid tier for approved customers. It adds a dedicated HA control plane, higher published node and Pod limits, VPC-isolated networking, Cilium, Premium NodeBalancer support, and more upgrade control. Current published pricing is **$300/month per Enterprise cluster plus consumed resources**. That product breadth is important when evaluating a Linode Kubernetes alternative: Raff competes most directly with **standard LKE for small and midsize managed clusters**, not with every capability in the Enterprise tier. ## Conclusion: Linode Kubernetes Engine or Raff? The Linode-Kubernetes-versus-Raff decision comes down to four practical axes: worker and HA cost, geographic and compute breadth, networking/transfer economics, and the scale of the Kubernetes operating model. - **Cluster cost:** three 2 vCPU / 4 GB workers plus HA total **$71.97/month on Raff** versus **at least $132/month on standard LKE in North America** before storage and attached services. - **Infrastructure breadth:** LKE offers broader regions, Dedicated CPU, High Memory, GPU support, and an Enterprise tier; Raff exposes a smaller worker catalog in `us-east`. - **Networking and transfer:** Raff includes a private VPC in the standard cluster model and $0 public egress; standard LKE uses included worker transfer and reserves VPC-isolated networking for Enterprise in its current feature table. - **Storage:** Raff cluster storage is **$0.08/GB-month** versus **$0.10/GB-month** for Akamai Block Storage in North America. Choose LKE when geographic reach, specialized compute, Akamai-native integrations, or the Enterprise tier solve a requirement you can name. Choose Raff when `us-east` is sufficient and lower published worker, HA, storage, and transfer costs make the production floor easier to forecast. Continue with [Managed Kubernetes vs Self-Managed Kubernetes](/learn/guides/managed-vs-self-managed-kubernetes), [Kubernetes Cluster Sizing](/learn/guides/kubernetes-cluster-sizing), and [Kubernetes Node Pools](/learn/guides/kubernetes-node-pools). --- ### Heroku Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-heroku Description: Considering Heroku? Raff Apps starts at $3/mo with $0 public egress; Heroku starts at $5 Eco with a mature PaaS ecosystem. Raff wins on fixed application tiers, $0 public egress, full Docker Compose import, first-party managed data services, and a spend cap enabled by default. Heroku wins on its mature add-on ecosystem, Pipelines and Review Apps, 12 published runtime-region choices across Common Runtime and Private Spaces, dedicated Performance dynos, and Salesforce enterprise integration. Choose Heroku when its established delivery workflow, Private Spaces, ecosystem, or Salesforce alignment are requirements; choose Raff when `us-east`, predictable service ceilings, Compose portability, and transfer simplicity fit the workload. Raff Apps starts at $3/month, while Heroku starts at $5/month for the Eco plan or $7/month for an always-on Basic dyno. Heroku and Raff Apps are both managed application platforms, so this is a direct PaaS comparison rather than a PaaS-versus-VM comparison. Heroku packages applications around dynos, process types, buildpacks, Pipelines, Review Apps, add-ons, and its Common Runtime or Private Spaces. Raff Apps packages web services, private services, workers, cron jobs, previews, managed data, persistent volumes, and container workflows around published service ceilings and $0 public application egress. ## Heroku vs Raff: which is right for you? Choose Heroku when the application already depends on Heroku conventions or when its ecosystem reduces more engineering work than a lower infrastructure bill would save. Choose Raff when the team wants a smaller operating surface, clear service ceilings, Docker Compose portability, and fewer variable transfer costs. | Decision factor | Choose Raff Apps | Choose Heroku | |---|---|---| | Entry app price | $3/month Micro ceiling | $5/month Eco or $7/month Basic | | Billing preference | Per-second runtime to a published monthly ceiling | Wall-clock dyno usage; Eco uses a pooled 1,000-hour plan | | Geography | One public `us-east` region fits | US/EU Common Runtime or one of 10 Private Spaces regions is required | | Deployment artifact | Docker Compose, Dockerfile, image, GitHub, or buildpack portability matters | Procfile/buildpack conventions and Heroku-native workflows matter | | Delivery workflow | Raff previews and immutable revisions are enough | Pipelines and mature Review Apps are central | | Ecosystem | First-party Raff cloud products fit | Heroku add-ons reduce integration work | | Public transfer | $0 public app egress matters | Heroku's 2 TB soft per-app bandwidth limit fits the workload | A practical decision rule from Raff's product and customer work is to price the whole application stack, not one web process. Web services, workers, previews, databases, durable storage, outbound traffic, and platform-specific integrations usually explain more of the long-term cost than the smallest runtime card. For the broader deployment decision, read [Cloud VM vs App Platform for Startups](/learn/guides/cloud-vm-vs-app-platform-startups). ## Heroku overview [Heroku](https://www.heroku.com/) is a managed cloud application platform operated by Salesforce. Applications run in dynos, Heroku's managed application containers, and teams deploy through source-based build workflows or container-based paths depending on the runtime generation and application configuration. Current Common Runtime pricing starts with **Eco at $5/month** for a shared pool of **1,000 dyno hours**. Eco dynos have 512 MB RAM and sleep after 30 minutes of inactivity. **Basic costs $7/month** for an always-on 512 MB dyno. Production Common Runtime tiers include **Standard-1X at $25/month**, **Standard-2X at $50/month**, and **Performance-M at $250/month** with dedicated compute. Heroku bills non-Eco dynos by wall-clock runtime and prorates usage to the second. A dyno accrues usage while scaled above zero whether or not the application is actively handling requests. Review Apps and one-off dynos also accrue usage while running. Heroku's delivery workflow is one of its clearest strengths. Pipelines model development, review, staging, and production stages, while Review Apps can create disposable applications for pull requests. The platform also provides release history, rollback, logs, metrics on eligible tiers, add-ons, managed data products, and mature developer documentation. Geography is another substantive advantage. Heroku currently lists **2 Common Runtime regions** — United States and Europe — plus **10 Private Spaces regions**: Dublin, Frankfurt, London, Montreal, Mumbai, Oregon, Singapore, Sydney, Tokyo, and Virginia. Private Spaces provide isolated network environments for enterprise workloads. Heroku is also moving from its Cedar generation toward Fir. Fir Private Spaces are generally available, but generation-specific feature differences still matter during deployment and migration, so teams should verify whether an application depends on Cedar-only behavior before moving runtimes. ## Raff overview [Raff Apps](/products/app-platform) is Raff's managed application platform for deploying source code and containers without administering the operating system underneath the service. It supports GitHub push-to-deploy, buildpacks, Dockerfiles, existing container images, and full Docker Compose imports. Raff Apps supports public web services, private services, long-running workers, timezone-aware cron jobs, one-off jobs, pull-request previews, persistent application volumes, immutable revisions, one-click rollback, and scale-to-zero behavior. Applications can connect to Raff Managed Databases for PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, along with object storage, VMs, Kubernetes, Functions, and private networking. | Raff Apps tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Runtime is billed per second against the published monthly ceiling. Public application egress costs **$0**, Apps team seats cost **$0**, and the spend cap is enabled by default. Raff Apps currently exposes one public region, `us-east`. That is a real limitation versus Heroku for teams that require Europe, Asia-Pacific, Canada, or U.S. West placement. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. On August 17, 2026, Raff's Trustpilot profile showed **4.5/5**, while G2 showed **4.6/5**. ## Heroku pricing vs Raff pricing Heroku and Raff price managed application runtime differently enough that the comparison should use buying positions rather than pretend the resource classes are identical. | Buying position | Raff Apps | Heroku | Decision signal | |---|---:|---:|---| | Personal / intermittent app | Micro — $3 ceiling, 0.25 vCPU / 512 MB | Eco — $5 for 1,000 shared dyno hours / 512 MB | Raff has the lower paid ceiling; Heroku's pooled Eco hours can cover several sleeping personal apps | | Small always-on app | Starter — $6.99 ceiling, 0.5 vCPU / 1 GB | Basic — $7 maximum / 512 MB | Similar monthly price; Raff publishes more memory and a vCPU allocation | | Production baseline | Standard — $16.99 ceiling, 1 vCPU / 2 GB | Standard-1X — $25 maximum / 512 MB | Raff has the lower published ceiling; Heroku brings mature production workflow features | | Larger service | Pro — $27.99 ceiling, 2 vCPU / 4 GB | Standard-2X — $50 maximum / 1 GB | Raff publishes more resources at a lower ceiling; compute classes are not performance-equivalent | | Higher performance position | Pro Max — $61.99 ceiling, 4 vCPU / 8 GB | Performance-M — $250 maximum / 2.5 GB dedicated compute | Heroku wins on a documented dedicated-compute class; Raff has the lower general Apps ceiling | **Comparison class:** these rows compare published buying positions, not matched performance. Heroku does not publish directly comparable vCPU allocations for its shared Common Runtime dynos, and Performance-M uses dedicated compute. Heroku's non-Eco dynos are prorated based on wall-clock usage, with the listed monthly amount acting as the maximum for a dyno that runs continuously through the billing period. Eco is different: the $5 subscription provides 1,000 dyno hours shared across Eco apps in the account. Raff Apps also prorates running services per second, but each tier exposes a monthly ceiling. That makes the upper bound visible for the selected app service before traffic arrives. ### Preview and worker cost Heroku Review Apps and one-off dynos consume billable runtime while active. A production architecture with web dynos, workers, review environments, scheduled jobs, and add-ons can therefore have several independently active resources. Raff previews, web services, workers, cron jobs, and one-off workloads also need to be included in architecture cost. The key difference is the pricing presentation: Raff uses published service ceilings, while Heroku uses dyno runtime and separate attached services. ### Data-service cost Neither app-runtime price includes every production dependency. Heroku Postgres, Key-Value Store, and third-party add-ons have their own plans. Raff Managed Databases and object storage are also separate products. Compare the application plus database, durable storage, backups, preview environments, and traffic rather than treating a single dyno or app service as the production bill. :::cta Deploy an App Now Deploy web services, workers, cron jobs, and Docker Compose stacks on Raff Apps with published service ceilings. ::: ## Bandwidth and transfer policy Raff Apps prices public application egress at **$0**. This removes a per-GB public application-transfer line item from the Apps runtime bill. Heroku does not publish a standard per-GB egress price for ordinary dyno application traffic. Instead, Heroku currently documents a **2 TB soft network-bandwidth limit per app per month**. Teams approaching or exceeding platform limits should review their architecture and Heroku requirements rather than treating the soft limit as an unlimited-transfer promise. The connected data path still matters on both platforms. Add-ons, external databases, object storage, cross-region services, logging providers, backups, and third-party APIs can have their own transfer policies. For Raff, $0 Apps public egress applies to the application platform. It should not be generalized to every connected product without checking that product's current pricing model. Heroku's model is workable when application traffic stays within its operating limits and connected-service transfer is modest. Raff is simpler to forecast for applications where public response traffic is large or uneven and `us-east` already satisfies placement requirements. ## Feature comparison: Heroku vs Raff | Feature | Raff Apps | Heroku | |---|---|---| | Entry app price | $3/month ceiling | $5 Eco / $7 Basic | | Billing model | Per second to fixed tier ceiling | Wall-clock dyno usage; pooled Eco hours | | Public regions | 1 — `us-east` | 2 Common Runtime + 10 Private Spaces regions | | Public app egress | $0 | No standard per-GB dyno rate; 2 TB soft bandwidth limit per app | | Git deployment | Yes | Yes | | Buildpacks | Yes | Yes | | Dockerfile / image workflow | Yes | Yes, subject to runtime-generation workflow | | Docker Compose | Full stack import | No direct whole-stack Compose execution model | | Web and worker processes | Yes | Yes | | Cron / scheduled work | Yes | Scheduler and related workflows | | Pull-request previews | Yes | Review Apps | | Release rollback | Immutable revisions / one-click rollback | Release history / rollback | | Persistent application volumes | Yes | Dyno filesystem is ephemeral; durable state uses data/add-on services | | Managed data | PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | Heroku Postgres, Key-Value Store, add-on ecosystem | | Dedicated app compute tier | No separate Apps class in this comparison | Performance dynos | | Enterprise isolated runtime | Raff platform/private-networking model | Private Spaces and Shield options | | Default spend cap | Yes | No equivalent default app-spend-cap positioning | Heroku wins on geography, dedicated Performance dynos, Pipelines, Review Apps, Private Spaces, and add-on depth. Raff wins on fixed service ceilings, $0 public app egress, Docker Compose import, first-party managed data breadth, and default spend protection. ## Features and reliability: Raff vs Heroku This comparison contains **0 controlled Raff-versus-Heroku application benchmarks**, so it does not declare either platform faster. A valid application benchmark would need matched runtime class, region, application image, database location, cache behavior, concurrency, persistent storage path, and repeated test windows. ### Deployment and delivery workflow Heroku Pipelines remain a mature continuous-delivery model. A pipeline can group development, review, staging, and production apps, and Review Apps can automatically create disposable environments for pull requests. This workflow is a genuine Heroku advantage for teams already standardized on it. Raff provides pull-request previews, immutable revisions, and one-click rollback. Its differentiator is broader deployment-artifact portability: GitHub source, buildpacks, Dockerfiles, container images, and full Docker Compose imports can feed the same Apps workflow. ### Runtime and scaling choices Heroku provides several Common Runtime dyno classes and dedicated Performance dynos. Performance-M starts at $250/month and uses dedicated compute, which Raff Apps does not claim to match with a separately published dedicated application-runtime class. Raff publishes explicit vCPU, memory, and ephemeral-disk ceilings from the $3 Micro tier through the $119.99 Scale tier. Scale-to-zero can reduce runtime cost for suitable services, but service cold-start behavior should be tested against the application's latency requirements. ### Platform generations Heroku is actively operating both Cedar and Fir platform generations. Fir Private Spaces are generally available, but some workflows and compatibility details differ from Cedar. Teams should evaluate generation-specific support for build, container, networking, compliance, and migration requirements rather than treating every Heroku runtime as identical. Raff presents a smaller runtime surface. That reduces platform-generation choice but also removes one category of migration decision for teams that do not need Heroku's enterprise runtime options. ### Persistent state and recovery Heroku dyno filesystems are ephemeral. Durable state normally belongs in Heroku Postgres, Key-Value Store, an add-on, or an external service. Application release rollback does not restore database state. Raff Apps supports persistent volumes plus first-party managed databases and object storage. Raff application revisions are also release controls rather than a substitute for database backups, object protection, or tested recovery procedures. ### Geography and operating evidence Heroku lists **12 runtime-region choices** across Common Runtime and Private Spaces, versus Raff Apps' **1 public region**. Heroku is the stronger choice when regional placement or enterprise network isolation is mandatory. Raff publishes a **99.9% platform SLA** and reports **3,000+ customers and 15,000+ production VMs**. Its current Trustpilot profile is **4.5/5**, with G2 at **4.6/5**. Heroku has a much longer specialized PaaS operating history, which remains a genuine maturity advantage. ## When you should choose Heroku over Raff Choose Heroku when: - **Your application is already Heroku-native.** Procfiles, buildpacks, add-ons, Pipelines, Review Apps, and release workflows can make migration cost more important than runtime price. - **The add-on ecosystem matters.** Heroku's mature marketplace can reduce integration and procurement work. - **More regions are required.** Heroku publishes 2 Common Runtime and 10 Private Spaces regions versus Raff Apps' single public `us-east` region. - **Private Spaces are required.** Heroku provides isolated enterprise runtime environments with network controls and multiple regional choices. - **Dedicated app compute matters.** Performance dynos provide a documented dedicated-compute class. - **Salesforce alignment matters.** Heroku operates inside Salesforce's enterprise product and procurement environment. - **Pipelines and Review Apps are established team standards.** Replacing a mature delivery workflow can outweigh infrastructure savings. ## When you should choose Raff over Heroku Choose Raff Apps when: - **A lower published app ceiling matters.** Raff starts at $3/month and Standard is $16.99/month for 1 vCPU and 2 GB RAM. - **Docker Compose is the source of truth.** Raff can import a connected Compose stack rather than requiring each service to be remodeled around a Heroku application workflow. - **Public application transfer is material.** Raff Apps prices public egress at $0. - **Cost protection should be on by default.** Raff enables the Apps spend cap before a team has to react to an unexpected usage increase. - **First-party data services fit the architecture.** Raff offers managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka alongside Apps. - **`us-east` is sufficient.** Heroku's regional advantage has less value when one eastern-U.S. region already meets latency and placement needs. - **Published resource allocations matter.** Raff exposes vCPU and RAM directly across its Apps tiers. Raff currently reports **3,000+ customers and 15,000+ production VMs**. For adjacent app-platform decisions, compare [Railway and Raff](/learn/compare/raff-vs-railway), [Render and Raff](/learn/compare/render-alternative), and [DigitalOcean App Platform and Raff](/learn/compare/digitalocean-app-platform-alternative). ## Migrating from Heroku to Raff 1. **Inventory the Heroku application.** Record dyno types, Procfile processes, buildpacks, container settings, config vars, add-ons, databases, domains, Scheduler jobs, Pipelines, Review Apps, release-phase commands, regions, and external allowlists. 2. **Choose the Raff deployment path.** Use GitHub/buildpacks for conventional source deployments, a Dockerfile or existing image for packaged services, or Docker Compose when the application already has a multi-service definition. 3. **Map process types and environments.** Convert Heroku web processes to Raff web services, internal services to private services, workers to workers, scheduled tasks to cron jobs, and administrative commands to one-off jobs. Recreate development, preview, staging, and production behavior intentionally rather than assuming Pipeline semantics transfer automatically. 4. **Move configuration and integrations.** Recreate secrets and environment variables, then replace Heroku-specific add-ons, callback URLs, log drains, trusted IP assumptions, and platform APIs where required. **Gotcha:** an add-on can look like a simple environment variable while hiding provider-specific networking or lifecycle behavior. 5. **Move persistent state.** Export databases with engine-native tools and move uploaded files or other durable data to persistent volumes, managed databases, or object storage. **Gotcha:** the Heroku dyno filesystem is ephemeral and should never be treated as migration source-of-truth storage. 6. **Verify and cut over.** Test builds, health checks, workers, cron jobs, previews, database connectivity, restore procedures, and external integrations on a temporary hostname. Lower DNS TTL to **300 seconds**, perform the final data sync, switch DNS and callbacks, monitor production, and retain Heroku until the rollback window closes. The most difficult part of a Heroku migration is usually not application source code. Add-ons, buildpack assumptions, Pipeline behavior, Review Apps, scheduled work, networking, and durable data require the most deliberate mapping. ## About Heroku [Heroku](https://www.heroku.com/) is a Salesforce cloud application platform that runs applications in managed dynos and supports buildpacks, container workflows, Pipelines, Review Apps, managed data products, add-ons, Common Runtime regions, and enterprise Private Spaces. Heroku currently operates both Cedar and Fir platform generations, with Fir Private Spaces generally available. Heroku pricing, runtime, region, Pipeline, and bandwidth claims in this comparison were rechecked against Heroku's official pricing and Dev Center documentation on August 17, 2026. ## Conclusion: Heroku or Raff? The Heroku-versus-Raff decision resolves across four measured axes: cost model, delivery ecosystem, geography/runtime choice, and deployment portability. - **Cost model:** Raff Apps starts at **$3/month** with fixed service ceilings and $0 public egress; Heroku starts at **$5 Eco** or **$7 Basic** and bills active dynos by wall-clock runtime outside the Eco pool. - **Delivery ecosystem:** Heroku has mature Pipelines, Review Apps, add-ons, and Salesforce enterprise integration; Raff provides a smaller first-party cloud surface with previews and immutable revisions. - **Geography and runtime choice:** Heroku publishes **12 runtime-region choices** across Common Runtime and Private Spaces and operates Cedar plus Fir; Raff Apps currently exposes one public `us-east` region. - **Deployment portability:** Raff supports full Docker Compose import along with source and container paths; Heroku is strongest when the application already follows Heroku process, buildpack, and add-on conventions. Choose Heroku when regional choice, Private Spaces, dedicated Performance dynos, add-on depth, Pipelines, or Salesforce alignment are hard requirements. Choose Raff when `us-east` is sufficient and fixed service ceilings, $0 public egress, Compose portability, first-party managed data, and default spend protection make the application easier to budget and operate. Raff currently reports **3,000+ customers, 15,000+ production VMs, Trustpilot 4.5/5, G2 4.6/5, and a 99.9% platform SLA**. --- ### Kamatera Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-kamatera Description: Considering Kamatera? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe against Kamatera Type A at $22 with 5 TB traffic. Kamatera is a cloud provider that sells servers by configuration rather than by plan: you pick cores, RAM, disk and region in a calculator and it prices the result. Raff Technologies is a US cloud provider where the virtual machine is one product among several, alongside managed databases, object storage, Functions and Kubernetes on the same account. Both run NVMe storage and both offer shared and dedicated CPU. At a matched 2 cores, 4 GB and 80 GB in New York, Kamatera's budget Type A configuration is $22/month and Raff General Purpose is $13.99/month. ## Kamatera VPS and Raff at a glance **Kamatera** has no fixed plan list. Every server is configured from four CPU types, 256 MB to 128 GB of RAM, 20 GB to 4 TB of NVMe storage, and 21 data centers. The four types are its own descriptions: - **Type A — Availability**, the budget tier - **Type B — General Purpose**, marked Recommended, where "CPU threads are dedicated with reserved resources guaranteed" - **Type T — Burstable**, for spiky workloads - **Type D — Dedicated**, the high-performance tier Every configuration includes **5 TB of traffic**, with additional transfer at $0.01/GB and additional storage at $0.05/GB-month. Billing is hourly, charged by the minute, with no long-term contract. Kamatera also sells cPanel, Plesk and Microsoft SQL Server licensing as add-ons, offers Windows Server and Windows Desktop images, and has optional managed service and extended daily backup. Its footprint is wide: Sydney, Toronto, Hong Kong, Frankfurt, Tel Aviv, Milan, Tokyo, Bucharest, Singapore, Madrid, Stockholm, Amsterdam, London, and eight US locations including New York, Chicago, Dallas, Los Angeles and Santa Clara. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.90% monthly uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Past the VM, Raff sells S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Kamatera VPS pricing vs Raff pricing Because Kamatera prices per configuration, the comparison has to be built by matching a shape and reading the total. The figures below were configured on Kamatera's own calculator on 2026-08-20, New York, Ubuntu Server, with the included 5 TB of traffic. **Class matters here.** Raff General Purpose is shared vCPU with no CPU guarantee, which matches **Type A**. Raff CPU-Optimized is dedicated vCPU, which matches **Type B and Type D** — Kamatera describes Type B as giving each vCPU a dedicated CPU thread with reserved resources. ### Shared vCPU: Raff General Purpose against Kamatera Type A | Shape | Raff General Purpose | Kamatera Type A | |---|---|---| | 2 cores / 4 GB / 80 GB | **$13.99** — unmetered, 3 Gbps | $22 — 5 TB included | | 4 cores / 8 GB (≈150 GB) | **$30.99** at 160 GB | $47 at 150 GB | Raff is **34% to 36% cheaper** at both shapes, with more disk at the larger one and no transfer cap. ### Dedicated vCPU: Raff CPU-Optimized against Kamatera Type B and D | Shape | Raff CPU-Optimized | Kamatera Type B | Kamatera Type D | |---|---|---|---| | 2 cores / 4 GB / 80 GB | **$27.99** | $45 | $70 | | 4 cores / 8 GB | **$49.99** at 120 GB | $95 at 150 GB | — | Raff is **38% to 47% cheaper than Type B** and **60% cheaper than Type D** at the matched shape. *Kamatera prices configured on kamatera.com on 2026-08-20 for the New York data center with Ubuntu Server and the included 5 TB traffic allowance; add-on licensing, managed service and extended backup excluded. Storage steps differ between the two providers, so the 150 GB and 160 GB rows are the closest available match rather than identical.* Raff is cheaper at every CPU class Kamatera sells. That is the whole pricing story, and it holds whether you compare budget against budget or dedicated against dedicated. ### What Kamatera charges for separately Two rates are worth knowing before configuring. Transfer beyond the included 5 TB is **$0.01/GB**, so an extra 5 TB adds $50/month. Storage beyond the configured disk is **$0.05/GB-month**, which is more than half again what Raff charges for block volumes at $0.08/GiB-month once you account for the units. Raff includes unmetered transfer on every plan, so there is no equivalent line to calculate. ### Automated backups Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. Kamatera offers extended daily backup as a paid add-on at configuration time, so price it in rather than assuming it is included. ## Kamatera VPS performance vs Raff This is a clean pairing: both machines are shared-CPU, both are 2 cores with 4 GB, and both sit in the same region — Kamatera in New York, Raff in us-east. ### Methodology Raff figures are internal, measured March–May 2026 on a General Purpose 2 vCPU / 4 GB instance in us-east. Kamatera figures are third-party, from VPSBenchmarks, on an "Availability 4GB 2 cores" configuration in New York running Ubuntu 26.04, trial started 24 June 2026 — a Type A server, which Kamatera's own spec sheet marks as neither dedicated nor burstable, the same shared-CPU basis as Raff General Purpose. The benchmarked Kamatera configuration lists at $19.00/month with 40 GB of disk. ### Results | Metric | Raff General Purpose | Kamatera Type A | Notes | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,126 | Raff 2.01x higher | | Geekbench 6 multi-core | **4,057** | 1,979 | Raff 2.05x higher | | fio 4K read, 50/50 mix | **48,670 IOPS** | 46,691 IOPS | Level, Raff 4% higher | | fio 1M sequential read | 2,491 MB/s | **2,985 MB/s** | Kamatera 1.20x higher | | fio 1M sequential write | 1,257 MB/s | **3,183 MB/s** | Kamatera 2.53x higher | | iperf3 to NYC, upload | 9,574 Mbps | 9,626 Mbps | Level | | iperf3 to NYC, download | 3,635 Mbps | **9,523 Mbps** | Kamatera 2.62x higher | | Processor | AMD EPYC, DDR5 ECC | Intel Xeon Sapphire Rapids | | ### What the results tell us **Raff is roughly twice as fast per core.** 2,266 against 1,126 on Geekbench 6 single-core, and 4,057 against 1,979 multi-core, on the same shared-CPU basis in the same region. For anything bound by application logic — API workers, rendering, request handling, queue consumers — that is the number that decides throughput, and it is not close. Raff also costs less: $13.99/month with 80 GB against the benchmarked $19.00 with 40 GB. **Kamatera wins on sequential disk and download.** Sequential 1M write measured 3,183 MB/s against Raff's 1,257, and download to New York 9,523 Mbps against 3,635. The download figure reflects a real capability difference rather than a measurement artifact: Raff publishes a 3 Gbps port, and the Kamatera box is clearly on a faster interface. If your workload is dominated by large sequential writes or by pulling large volumes of data inbound, Kamatera's configuration is the stronger one in this test. **Random I/O is level.** 48,670 IOPS against 46,691 on the same 50/50 4K job — within noise, and the pattern most databases actually run. Read it as a trade: Raff for CPU-bound work at lower cost, Kamatera for sequential throughput and inbound bandwidth. ## Kamatera vs Raff: features and reliability ### Compute Kamatera configures from 1 to 104 cores and 256 MB to 128 GB of RAM across four CPU classes — a far wider range than Raff's 16 vCPU and 32 GB ceiling, and finer-grained at the bottom. Raff offers General Purpose from $4.99/month and CPU-Optimized from $9.99/month, on AMD EPYC with DDR5 ECC memory, and resizes on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. Kamatera includes 5 TB of traffic per server with additional transfer at $0.01/GB, and offers multiple public IPs at configuration time. ### Storage Both use NVMe. Kamatera lets you configure the boot disk from 20 GB to 4 TB and attach up to four additional volumes at $0.05/GB-month. Raff separates storage into VM disk, block volumes at $0.08/GiB-month that resize independently, and S3-compatible object storage at $7/month for 100 GB with 1 TB of egress. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines, through the same queue. Kamatera offers an optional paid managed service tier, so confirm what is included at your service level before buying. ### Platform and licensing This is where the two catalogs diverge, and each has something the other lacks. Kamatera sells **licensed software as part of the server**: cPanel in three sizes, Plesk in three sizes, Microsoft SQL Server from Express to Enterprise per vCPU, Microsoft Office Standard per user, plus Windows Server 2016 through 2025 and Windows Desktop images. Raff covers most of that list through its SPLA program: Windows Server Standard at **$15.00/month per instance**, multi-user RDP licensed with **RDS User SALs at $8.00/month per user**, and SQL Server and Office licensing on the same bill. Bring-your-own-licence is supported at create time. What Kamatera adds that Raff does not sell is **cPanel and Plesk** hosting control panels, and Windows Desktop images. Raff sells **managed services around the server**: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds per month, Raff Apps from $3/month, and managed Kubernetes with a free control plane. They connect over private networking, share one API, one CLI and one bill. The distinction is straightforward: Kamatera helps you build a bigger server, Raff helps you build a smaller one with managed pieces beside it. ## When you should choose Kamatera over Raff - **Users outside the United States** — 21 data centers across Europe, Asia, Australia, the Middle East and North America against Raff's single us-east region - **cPanel or Plesk on one bill** — hosting control panels configured into the server, plus Windows Desktop images; Raff licenses Windows Server, RDS, SQL Server and Office but not these - **Sequential-throughput and inbound-heavy workloads** — measured 2.53x higher 1M sequential write and 2.62x higher download to New York in third-party testing - **Very large or very small servers** — up to 104 cores and 128 GB RAM, or down to 256 MB, against Raff's 16 vCPU / 32 GB ceiling and 1 GB floor - **Exact configurations** — cores, RAM and disk chosen independently, rather than fitting a workload to a fixed plan - **Short-lived workloads** — hourly billing charged by the minute makes brief tests and burst capacity cheap - **Burstable workloads** — the Type T tier has no Raff equivalent ## When you should choose Raff over Kamatera - **CPU-bound applications** — measured 2.01x faster single-core and 2.05x faster multi-core than a same-class Kamatera Type A server in the same region ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **Lower cost at every CPU class** — 34% to 36% below Type A on shared vCPU, 38% to 47% below Type B and 60% below Type D on dedicated - **Egress-heavy applications** — unmetered transfer on a 3 Gbps port against 5 TB included and $0.01/GB after - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month over private networking, instead of self-hosting and licensing your own ([VPS for databases](/learn/guides/vps-for-databases)) - **Stacks that outgrow one server** — object storage at $7/month, Functions with a free monthly tier, Raff Apps from $3/month and managed Kubernetes with a free control plane - **Backups without an add-on** — Daily and Weekly schedules on a free storage pool with 1 to 365 day retention, against extended daily backup priced as an option - **24/7 human support at no extra tier** — live chat to the same engineers at any account size, first response typically under 10 minutes ## Migrating from Kamatera to Raff 1. **Match the CPU class, not the core count** — a Kamatera Type A core and a Type D core are different products. Type A maps to Raff General Purpose, Type B and D to CPU-Optimized. 2. **Check your region requirement** — Raff serves us-east only. If you are running in Frankfurt, Tokyo or Tel Aviv for latency or data residency, this migration will not preserve that. 3. **Inventory your licences first** — licences bought through Kamatera do not transfer. Raff relicenses Windows Server at $15.00/month per instance, RDS User SALs at $8.00/month per user, and SQL Server and Office through the same SPLA program; cPanel and Plesk it does not sell, so price those separately. 4. **Right-size on utilisation, and test sequential paths** — Kamatera configurations are often built larger than needed because the calculator makes it easy. Measure actual usage first, and if your workload is dominated by large sequential writes, benchmark it on Raff before committing. 5. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then static assets to object storage. Keep the Kamatera server running throughout. 6. **Cut over and stop the clock** — lower DNS TTL beforehand, switch, then terminate the Kamatera server rather than stopping it, since hourly billing continues while resources are allocated. ## About Kamatera Kamatera is a cloud infrastructure provider offering configurable cloud servers, block storage, load balancers, private networking and managed services from 21 data centers across North America, Europe, Asia, Australia and the Middle East. Servers are priced by configuration rather than by fixed plan, starting at $4/month. See [Kamatera pricing](https://www.kamatera.com/pricing/) for current rates and the configuration calculator. ## Conclusion: Kamatera or Raff? The comparison resolves across four axes: - **Price** — Raff wins at every CPU class: 34–36% below Type A, 38–47% below Type B, 60% below Type D at matched shapes - **Performance** — split: Raff 2.01x faster per core on the same class in the same region; Kamatera 2.53x higher sequential write and 2.62x higher download - **Reach** — Kamatera wins, 21 data centers against Raff's single us-east region - **Configurability** — Kamatera wins, with independent core/RAM/disk selection, a 104-core ceiling, and cPanel and Plesk on the same bill; both providers license Windows Server, RDS, SQL Server and Office - **Managed services** — Raff wins, with managed databases from $7.99/month, object storage, Functions, Apps and Kubernetes on one account over private networking If your users are outside the United States, you need cPanel or Plesk bundled into the server bill, or you want a server shape Raff does not sell, choose Kamatera. If your users are in North America and you want lower cost per server plus managed databases and storage beside it, choose Raff. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.90% monthly uptime SLA in writing. --- ### DigitalOcean Alternative 2026: Pricing & Performance URL: https://rafftechnologies.com/learn/compare/raff-vs-digitalocean Description: Considering DigitalOcean? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe against a $24 Basic Droplet with identical specs. DigitalOcean is one of the best-known developer clouds, with Droplets, managed databases, Kubernetes, App Platform, Spaces object storage, Functions and GPU instances, backed by a documentation library most providers cannot match. Raff Technologies runs the same shape of platform — VMs, managed databases, Kubernetes, object storage, Functions and Apps on one account — from a single us-east region. The two are close enough in scope that the comparison comes down to price per unit and which parts of the catalog you actually need. At the matched shape, a DigitalOcean Basic Droplet with 2 vCPU, 4 GB and 80 GB is $24/month; the identical Raff plan is $13.99. ## DigitalOcean VPS and Raff at a glance **DigitalOcean** sells four Droplet families. **Basic** uses shared vCPU from $4/month; **CPU-Optimized**, **General Purpose** and **Memory-Optimized** all use dedicated vCPU at different memory ratios. Every Droplet includes a metered transfer allowance — 500 GB at the entry plan rising to 11 TB — with overage at **$0.01 per GiB**. Around the Droplet sits a deep catalog: Spaces object storage from $5/month with a built-in CDN, App Platform from $0/month, Managed Databases from $15/month covering PostgreSQL, MySQL, Valkey, MongoDB, Kafka and OpenSearch, Kubernetes from $12/month with a free control plane, Functions with 90,000 GiB-seconds free per month, block storage volumes, load balancers, and GPU Droplets. DigitalOcean also operates data centers across North America, Europe and Asia, and its tutorial library is a genuine asset that no comparison should pretend away. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.90% monthly uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with **unmetered** transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Raff's catalog covers managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## DigitalOcean VPS pricing vs Raff pricing DigitalOcean Basic Droplets use shared vCPU, which matches Raff General Purpose. The dedicated families match Raff CPU-Optimized. Both tables below compare like with like. ### Shared vCPU: Raff General Purpose against DigitalOcean Basic | Shape | Raff General Purpose | DigitalOcean Basic | |---|---|---| | 1 vCPU / 1 GB | **$4.99** — 25 GB, unmetered | $6.00 — 25 GB, 1 TB transfer | | 1 vCPU / 2 GB | **$6.99** — 50 GB, unmetered | $12.00 — 50 GB, 2 TB transfer | | 2 vCPU / 2 GB | **$8.49** — 40 GB, unmetered | $18.00 — 60 GB, 3 TB transfer | | 2 vCPU / 4 GB | **$13.99** — 80 GB, unmetered | $24.00 — 80 GB, 4 TB transfer | | 4 vCPU / 8 GB | **$30.99** — 160 GB, unmetered | $48.00 — 160 GB, 5 TB transfer | | 8 vCPU / 16 GB | **$59.99** — 320 GB, unmetered | $96.00 — 320 GB, 6 TB transfer | Three of those rows are **identical on disk as well as cores and memory** — 80 GB, 160 GB and 320 GB — which makes them unusually clean comparisons. Raff is **35% to 53% cheaper** across the range. ### Dedicated vCPU: Raff CPU-Optimized against DigitalOcean CPU-Optimized | Shape | Raff CPU-Optimized | DigitalOcean CPU-Optimized | |---|---|---| | 2 vCPU / 4 GB | **$27.99** — 80 GB | $42.00 — 25 GB | | 4 vCPU / 8 GB | **$49.99** — 120 GB | $84.00 — 50 GB | | 8 vCPU / 16 GB | **$89.99** — 180 GB | $168.00 — 100 GB | Raff is **33% to 46% cheaper** on dedicated vCPU, with two to three times the included disk at every shape. *DigitalOcean prices read from digitalocean.com on 2026-08-20. DigitalOcean also sells General Purpose and Memory-Optimized Droplets at higher memory ratios — from $63/month at 2 vCPU / 8 GB and $84/month at 2 vCPU / 16 GB — where Raff's closest plans are $27.99 and, above 32 GB, nothing at all.* ### Bandwidth cost math This is where the two models diverge most. DigitalOcean meters transfer per Droplet and bills **$0.01 per GiB** beyond the allowance. Raff includes unmetered transfer on a 3 Gbps port. | Monthly egress on a 2 vCPU / 4 GB VM | Raff | DigitalOcean Basic (4 TB included) | |---:|---|---| | 2 TB | $13.99 | $24.00 | | 4 TB | $13.99 | $24.00 | | 8 TB | **$13.99** | $24.00 + $40.96 = **$64.96** | | 20 TB | **$13.99** | $24.00 + $163.84 = **$187.84** | At 20 TB the DigitalOcean bill is more than thirteen times Raff's. Below the allowance the gap is just the plan price; above it, the gap compounds. DigitalOcean does pool allowances across Droplets in an account, which softens this for fleets — but the per-GiB rate still applies once the pool is exhausted. ### Automated backups DigitalOcean sells Droplet backups as an add-on priced as a percentage of the Droplet cost, and snapshots per GB. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. ## DigitalOcean VPS performance vs Raff ### Methodology The only head-to-head data Raff holds against DigitalOcean is from **May 2026**, and it compared a **dedicated-vCPU** Raff benchmark VM against a **shared-vCPU** DigitalOcean Basic Droplet in a different region, single-pass. That class mismatch is disqualifying for a provider-level claim, so the numbers below are published as a record of that test window rather than as evidence that Raff General Purpose outperforms DigitalOcean Basic today. A matched re-run is outstanding. ### Historical results — May 2026 | Benchmark | Raff (dedicated vCPU) | DigitalOcean Basic (shared vCPU) | |---|---:|---:| | sysbench CPU 1-thread | 1,663 events/s | 364 events/s | | sysbench CPU 2-thread | 3,338 events/s | 744 events/s | | Memory sequential read | 131,925 MiB/s | 36,709 MiB/s | | Memory sequential write | 37,231 MiB/s | 16,449 MiB/s | | Disk 4K random read QD32 | 74,562 IOPS | 40,679 IOPS | | Disk 4K random write QD32 | 52,450 IOPS | 11,241 IOPS | | Disk 1M sequential read | 2,376 MiB/s | 2,224 MiB/s | | Redis SET | 157,356 req/s | 61,538 req/s | | SQLite inserts | 331,110/s | 172,398/s | ### What the results tell us Read the gaps as what they are: a dedicated core will beat a shared core, and most of the CPU and Redis spread above is that difference rather than a platform difference. The one row worth attention is **1M sequential read at 2,376 against 2,224 MiB/s** — nearly level, which suggests the two platforms' sequential disk throughput is comparable even when the CPU classes are not. If you are choosing on measured performance, benchmark your own workload on both. Raff's General Purpose line is the honest comparison against a Basic Droplet, and that pairing has not been tested. ## DigitalOcean vs Raff: features and reliability ### Droplets and compute DigitalOcean scales far past Raff: up to 48 vCPU and 96 GB on CPU-Optimized, 40 vCPU and 160 GB on General Purpose, and 32 vCPU with 256 GB on Memory-Optimized, plus GPU Droplets. Raff stops at 16 vCPU and 32 GB. Below that ceiling Raff resizes on demand — stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking and bandwidth Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. DigitalOcean includes metered transfer pooled across the account at $0.01/GiB overage, VPC, cloud firewalls, and load balancers from $12/month. Raff does not charge separately for load balancing. ### Storage and object storage Raff separates storage into VM disk, block volumes at **$0.08/GiB-month**, and S3-compatible object storage at **$7/month for 100 GB with 1 TB of egress**. DigitalOcean Spaces is **$5/month for 250 GiB with 1 TiB of transfer**, with additional storage at $0.02/GiB and transfer at $0.01/GiB — and a **built-in CDN at no extra charge**. On object storage DigitalOcean is straightforwardly the better deal: more storage, lower price, and a CDN Raff does not offer. ### Managed databases Raff runs PostgreSQL, MySQL, Valkey, ClickHouse and Kafka **from $7.99/month**. DigitalOcean runs PostgreSQL, MySQL, Valkey, MongoDB, Kafka and OpenSearch **from $15/month**, with free daily backups and automated failover. Raff is roughly 47% cheaper at entry and adds ClickHouse. DigitalOcean adds MongoDB and OpenSearch, which Raff does not offer at all. ### Kubernetes and App Platform Both offer managed Kubernetes with a **free control plane** — DigitalOcean from $12/month for worker capacity, Raff from $9.99/month. App Platform is a real DigitalOcean advantage: it starts at **$0/month** with a free tier for static sites, against Raff Apps from $3/month. If you deploy small apps and static sites, DigitalOcean's free tier is not something Raff matches. ### Functions DigitalOcean Functions includes **90,000 GiB-seconds per month free**, then $0.0000185 per GiB-second, with invocations not billed separately and a **100 ms minimum billed runtime** per invocation. Raff Functions meters memory and active CPU separately, with a free tier of **100,000 GB-seconds and 10,000 vCPU-seconds per month**, and bills warm invocations at 30% of the standard rate. The free tiers are close, and the metering differs — DigitalOcean charges a flat GiB-second rate with a 100 ms floor, while Raff separates memory from CPU time and discounts warm starts. **The real difference is how long a function may run.** DigitalOcean caps execution at **15 minutes**, including initialization, with memory from 128 MB to 1 GB. Raff Functions permit runs of up to **24 hours**. That is not a pricing difference, it is a capability one: batch imports, ETL jobs, media transcoding, large report generation and long-running scrapes cannot be written as DigitalOcean Functions at all, and have to become a Droplet or a Kubernetes job instead. On Raff they stay serverless. ### Support and documentation Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines. DigitalOcean's advantage here is not the ticket queue — it is the **documentation and tutorial library**, which is among the best in the industry and frequently the reason developers pick it. Raff has nothing comparable in breadth, and that is worth weighing if your team leans on published guides. ## When you should choose DigitalOcean over Raff - **Object storage and CDN workloads** — Spaces is $5/month for 250 GiB with 1 TiB transfer and a built-in CDN, against Raff's $7 for 100 GB and no CDN - **Free-tier app hosting** — App Platform starts at $0/month; Raff Apps start at $3 - **MongoDB or OpenSearch** — both managed on DigitalOcean, neither offered by Raff - **Large or GPU workloads** — up to 48 vCPU, 256 GB RAM and GPU Droplets, against Raff's 16 vCPU / 32 GB ceiling - **Multi-region deployment** — data centers across North America, Europe and Asia against Raff's single us-east region - **Teams that learn from documentation** — DigitalOcean's tutorial library is a genuine and hard-to-replicate asset ## When you should choose Raff over DigitalOcean - **Lower cost on equivalent VMs** — 35% to 53% below Basic Droplets on shared vCPU and 33% to 46% below CPU-Optimized, at identical disk on three matched shapes ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **Egress-heavy applications** — unmetered transfer on a 3 Gbps port against $0.01/GiB overage; at 20 TB a month the DigitalOcean bill is over thirteen times higher - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month against $15 ([VPS for databases](/learn/guides/vps-for-databases)) - **Block-storage-heavy workloads** — $0.08/GiB-month, below DigitalOcean's volume pricing - **Backups without an add-on** — Daily and Weekly schedules on a free storage pool with 1 to 365 day retention, against backups priced as a percentage of Droplet cost - **Long-running serverless jobs** — Raff Functions run up to 24 hours against DigitalOcean's 15-minute cap, so batch imports, ETL and transcoding stay serverless instead of needing a Droplet - **Kubernetes at lower cost** — free control plane on both, with Raff workers from $9.99/month against $12 ## Migrating from DigitalOcean to Raff 1. **Check your egress profile first** — this is usually the largest single saving. If you are paying overage on Droplet transfer, that line disappears entirely on Raff. 2. **Match the Droplet family to the right Raff line** — Basic maps to General Purpose, CPU-Optimized and General Purpose Droplets map to Raff CPU-Optimized. Matching by price rather than class will mislead you. 3. **Check the ceiling** — Raff stops at 16 vCPU and 32 GB. Anything above that has no Raff equivalent. 4. **Plan Spaces and MongoDB separately** — Spaces is cheaper than Raff object storage and includes a CDN, and Raff has no managed MongoDB or OpenSearch. Decide whether those stay on DigitalOcean. 5. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then assets to object storage. Keep the Droplet running throughout. 6. **Cut over and destroy, don't power off** — lower DNS TTL beforehand, switch, then destroy the Droplet. A powered-off Droplet still bills. ## About DigitalOcean DigitalOcean Holdings, Inc. is a US cloud infrastructure provider headquartered in New York, founded in 2012 and listed on the NYSE, serving developers and small-to-medium businesses with Droplets, managed databases, Kubernetes, App Platform, Spaces object storage, Functions and GPU instances from data centers across North America, Europe and Asia. See [DigitalOcean pricing](https://www.digitalocean.com/pricing) for current rates. ## Conclusion: DigitalOcean or Raff? The comparison resolves across four axes: - **VM price** — Raff wins, 35% to 53% below Basic Droplets and 33% to 46% below CPU-Optimized, at identical disk on three matched shapes - **Bandwidth** — Raff wins, unmetered on a 3 Gbps port against $0.01/GiB overage past the allowance - **Catalog breadth** — DigitalOcean wins, with MongoDB, OpenSearch, GPU Droplets, a free App Platform tier, cheaper object storage with a CDN, and multiple regions - **Managed databases** — Raff wins on price, from $7.99/month against $15, and adds ClickHouse If you need MongoDB, OpenSearch, GPU capacity, a free app tier, cheap object storage with a CDN, or a region outside the United States, choose DigitalOcean — and it is a genuinely strong platform, not a straw man. If your users are in North America and your bill is dominated by VMs, egress and managed databases, choose Raff: the same workload costs materially less. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.90% monthly uptime SLA in writing. --- ### Railway Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-railway Description: Considering Railway? Raff Apps starts at $3/mo with $0 public egress; Railway Hobby is $5/mo plus metered resource usage. Raff wins on fixed service ceilings, $0 public egress, full Docker Compose import, and first-party managed data services. Railway wins on four deployment regions, usage-based compute, PR environments, native volume backups, and broader per-service scaling. Choose Railway when global placement and pay-for-actual-use economics matter; choose Raff when `us-east`, predictable monthly ceilings and Compose portability fit the workload. Raff Apps starts at $3/month, while Railway Hobby is $5/month with $5 of included resource usage before metered CPU, memory, storage, and egress. Railway and Raff are now a direct app-platform comparison rather than a PaaS-versus-VM mismatch. Railway charges $20 per vCPU-month, $10 per GB-month of RAM, $0.15 per GB-month of volume storage, and $0.05 per GB of egress, with subscription fees credited toward usage. Raff Apps publishes fixed service ceilings from $3 to $119.99 per month and charges $0 for public app egress and team seats. The practical decision is whether variable usage pricing and four deployment regions are more valuable than fixed resource tiers, direct Compose imports, and a single `us-east` operating model. ## Railway vs Raff: which is right for you? Choose Railway when you want a usage-metered PaaS with four deployment regions, automatic GitHub deployment workflows, PR environments, native scheduled volume backups, replicas, and service sleeping. Choose Raff when you want fixed monthly service ceilings, $0 public egress, full Docker Compose import, persistent app volumes, and first-party managed databases alongside the application platform. | Decision factor | Choose Raff Apps | Choose Railway | |---|---|---| | Entry app price | You want a fixed $3/month Micro ceiling | You want a $0 Free plan or $5 Hobby subscription credited toward usage | | Billing model | Fixed service tiers with per-second billing to a monthly ceiling | Metered CPU, RAM, volume, and egress usage | | Geography | One public `us-east` region fits the workload | You need California, Virginia, Amsterdam, or Singapore | | Egress | You want $0 public app egress | $0.05/GB is acceptable or traffic is modest | | Deployment artifact | Full Docker Compose import matters | GitHub, local source, or Docker image service mapping fits | | Preview workflow | Raff pull-request previews fit the team | Railway PR Environments and focused previews are preferred | | Durable state | Raff persistent volumes plus managed data services fit | Native Railway volume backups and database templates are preferred | For Raff's app-platform decisions, the useful comparison is the steady operating bill rather than the smallest plan card. We separate runtime, outbound traffic, and durable state because those three costs behave differently as a SaaS workload grows. A platform can look inexpensive at idle and become expensive at sustained CPU, memory, or egress; the reverse is also true when a fixed tier sits mostly unused. ## Railway overview [Railway](https://railway.com) is a deployment platform from Railway Corporation. It runs long-lived services, cron jobs, and single-file TypeScript functions, with deployments from GitHub repositories, local source, or Docker images. Railway also provides environments, variables, private networking, replicas, persistent volumes, database templates, logs, metrics, deployment rollback, and a template marketplace. Railway's current subscription structure is Free at **$0/month**, Hobby at **$5/month**, Pro at **$20/month**, and Enterprise at custom pricing. The Free plan includes **$1 of monthly resource credit**, Hobby includes **$5**, and Pro includes **$20**. On paid plans, the subscription amount is credited against resource usage rather than added on top of the same amount of usage. Current metered rates are **$20/vCPU-month**, **$10/GB-month of RAM**, **$0.15/GB-month for volumes**, and **$0.05/GB of network egress**. Compute is billed by the minute. Railway's [pricing documentation](https://docs.railway.com/pricing) is explicit that the final bill depends on actual resource consumption. Railway currently exposes four standard deployment regions: California, Virginia, Amsterdam, and Singapore. Services can use horizontal replicas, and Railway's Serverless mode can put an inactive service to sleep after more than 10 minutes without outbound traffic, then wake it on the next incoming request. Railway is particularly strong for teams that want service-level automation rather than fixed instance sizing. GitHub autodeploys, PR Environments, focused PR previews, deployment rollback, native volume backup schedules, and cross-region deployment controls are integrated into the platform workflow. ## Raff overview [Raff Apps](/products/app-platform) is Raff's managed application platform for deploying source code and containers without administering the operating system underneath them. It supports GitHub push-to-deploy, buildpacks, Dockerfiles, existing container images, and full Docker Compose imports. Raff Apps supports public web services, private services, long-running workers, timezone-aware cron jobs, one-off jobs, pull-request previews, persistent application volumes, immutable revisions, one-click rollback, and scale-to-zero behavior. Applications can connect to Raff Managed Databases for PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka as well as object storage, VMs, Kubernetes, Functions, and private networking. | Raff Apps tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Runtime is billed per second against the published monthly ceiling. Public application egress and Apps team seats cost **$0**, and the spend cap is enabled by default. Raff currently exposes one public Apps region, `us-east`, which is a real limitation for teams that need geographic placement elsewhere. Raff reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. On August 17, 2026, Raff's Trustpilot profile was **4.5/5**, with G2 at 4.6/5. ## Railway pricing vs Raff pricing Railway and Raff price application compute differently. Railway meters CPU and memory actually consumed, while Raff publishes resource tiers with a monthly ceiling. The right comparison therefore needs both the plan entry points and a few clearly labeled full-utilization examples. | Buying position | Raff Apps | Railway | Decision signal | |---|---:|---:|---| | Entry platform | Micro — 0.25 vCPU / 512 MB — $3 ceiling | Free — $0 with $1 monthly resource credit | Railway wins for experimentation at $0 | | Personal paid baseline | Starter — 0.5 vCPU / 1 GB — $6.99 ceiling | Hobby — $5 with $5 usage included | Different models; Railway meters actual use | | Production/team baseline | Standard — 1 vCPU / 2 GB — $16.99 ceiling | Pro — $20 with $20 usage included | Raff has lower fixed tier; Railway includes platform usage credit | | Full-month 1 vCPU + 2 GB use | $16.99 Standard ceiling | $40 if 1 vCPU and 2 GB were continuously consumed | Railway can be lower when actual CPU use is far below the full-month assumption | | Full-month 2 vCPU + 4 GB use | $27.99 Pro ceiling | $80 if 2 vCPU and 4 GB were continuously consumed | Raff has the lower ceiling under sustained full utilization | **Comparison class:** Railway does not sell fixed 1 vCPU / 2 GB or 2 vCPU / 4 GB instances at those monthly totals. The $40 and $80 Railway rows are arithmetic examples using its published $20/vCPU-month and $10/GB-month rates under continuous full-month consumption. Real Railway CPU usage may be substantially lower, especially for idle or bursty services. Railway's subscription is credited against usage. A Pro workspace with $40 of resource usage pays $40 total for the usage/subscription portion, not $60. Pro seats are currently $0, so neither Railway nor Raff adds a per-seat charge for the standard team workflow. ### Bandwidth cost math Railway charges **$0.05/GB** for network egress. Raff Apps public application egress is **$0**. | Monthly public egress | Raff Apps | Railway egress charge | |---:|---:|---:| | 100 GB | $0 | $5.00 | | 500 GB | $0 | $25.00 | | 1 TiB (1,024 GB) | $0 | $51.20 | | 2 TiB (2,048 GB) | $0 | $102.40 | | 5 TiB (5,120 GB) | $0 | $256.00 | These figures isolate public egress only. Railway recommends private networking for service-to-service communication inside a project to avoid unnecessary public-network charges. ### Automated backups Railway has a meaningful native advantage for volume-backed services. Railway volumes support manual backups and automated **daily, weekly, and monthly** schedules. Daily backups are retained for **6 days**, weekly backups for **1 month**, and monthly backups for **3 months**. Backup storage is incremental and billed at the same **$0.15/GB-month** rate as volumes for data unique to the backup. Raff Apps application revisions and one-click rollback are release controls, not a substitute for data backup. Raff's current canonical Apps specification does not claim an equivalent native volume-backup schedule, so this comparison does not invent one. Stateful Raff Apps workloads should place recoverable data in an appropriate managed database, object storage, or another verified backup path and test restoration separately from application rollback. ### Variable-cost boundaries Railway lets workspace admins set compute usage alerts and hard limits. Hitting a hard limit takes workloads offline to stop additional compute charges. Raff Apps instead publishes a monthly ceiling for each service tier and enables a spend cap by default. Railway provides finer pay-for-use economics; Raff gives a more visible upper bound for the selected app tier. :::cta Deploy an App Now Deploy web services, workers, cron jobs, and Docker Compose stacks on Raff Apps. ::: ## Bandwidth and transfer policy Railway meters public network egress at **$0.05/GB**. Private networking connects services inside a project environment over Railway's internal network, which can avoid public egress for internal service communication. The cost model therefore rewards architectures that keep app-to-database and service-to-service traffic private. Raff Apps charges **$0 for public application egress**. That removes outbound transfer as a variable line item for APIs, media delivery, downloads, package distribution, and workloads with seasonal or unpredictable traffic. The trade-off is geography. Railway currently has **four standard deployment regions** across the United States, Europe, and Southeast Asia; Raff Apps exposes **one public region, `us-east`**. Railway can reduce user-to-app distance for geographically distributed audiences, while Raff is easier to forecast when one eastern-U.S. placement is sufficient and transfer volume is material. ## Feature comparison: Railway vs Raff | Feature | Raff Apps | Railway | |---|---|---| | Entry price | $3/month ceiling | $0 Free; $5 Hobby | | Billing model | Per second to fixed tier ceiling | Metered CPU, RAM, storage, egress | | Public regions | 1 — `us-east` | 4 — California, Virginia, Amsterdam, Singapore | | Public egress | $0 | $0.05/GB | | Source deployment | GitHub, buildpacks, Dockerfile, existing image | GitHub, local source, Docker image | | Docker Compose | Full stack import | Compose services must be translated into Railway services | | Public web services | Yes | Yes | | Private services/networking | Yes | Yes | | Long-running workers | Yes | Yes | | Cron jobs | Yes | Yes | | Scale-to-zero / sleeping | Yes | Serverless sleep after >10 minutes without outbound traffic | | PR preview environments | Yes | Yes, including focused PR environments | | Persistent volumes | Yes | Yes, $0.15/GB-month | | Native volume backup schedule | Not claimed in current Apps specification | Daily / weekly / monthly | | Deployment rollback | Immutable revisions, one-click rollback | Previous deployment rollback within plan retention | | Horizontal replicas | Platform-managed service model | Up to 6 Hobby / 42 Pro by current plan limits | | Team seats | $0 | $0 on Pro/Enterprise | | Managed data model | First-party PostgreSQL, MySQL, Valkey, ClickHouse, Kafka | Database services/templates including PostgreSQL, MySQL, Redis, MongoDB | | Published standard SLA | 99.9% platform SLA | Pro explicitly excludes SLOs; Enterprise can negotiate an SLA | Railway wins on region choice, native scheduled volume backups, explicit replica controls, its $0 Free plan, and usage-based economics for low-duty-cycle services. Raff wins on fixed tier ceilings, $0 public egress, direct Compose import, and a first-party managed-data portfolio that is separate from app containers. ## Features and reliability: Raff vs Railway This comparison includes **0 controlled Raff-versus-Railway application benchmarks**, so it does not declare either platform faster. A valid test would need matched CPU scheduling, memory, region, application image, database placement, storage path, concurrency, caching, and repeated test windows. ### Usage-based compute versus fixed ceilings Railway's billing can be efficient for bursty workloads because CPU and memory are metered rather than sold as fixed instance sizes. Railway Serverless can also stop an inactive service after more than 10 minutes without outbound traffic, reducing compute usage while it sleeps. The first request wakes the service and can experience a cold-start delay. Raff Apps also supports scale-to-zero, but its commercial model is easier to cap: each tier has a published monthly ceiling. The trade-off is that a fixed ceiling does not automatically mean it is cheaper for a lightly used service. Railway's metered model can win when the application spends most of the month idle. ### Regions and replicas Railway exposes four standard deployment regions and lets services run horizontal replicas. Current plan limits allow up to **6 replicas on Hobby** and **42 on Pro**. Railway also supports changing regions, although a service with an attached volume needs a volume migration and can experience downtime during that move. Raff Apps exposes only `us-east`. Teams with users concentrated in eastern North America may not benefit from extra placement choices, but teams with latency or data-location requirements in Europe, Asia-Pacific, or the U.S. West should treat Railway's region map as a substantive advantage. ### Release safety and previews Both platforms provide pull-request preview workflows and deployment rollback. Railway PR Environments can clone an environment for a GitHub pull request and remove it when the PR closes; focused PR environments can deploy only services whose watched paths changed. Raff Apps provides pull-request previews, immutable revisions, and one-click rollback. Railway's current rollback retention is **24 hours on Free/Trial, 72 hours on Hobby, 120 hours on Pro, and 360 hours on Enterprise**. Raff's immutable revision model is not a database restore mechanism either, so both platforms still require a separate data-recovery plan. ### Data recovery Railway's scheduled volume backups are one of its clearest operational strengths. The platform can retain daily, weekly, and monthly volume backups and restore them into the same project and environment. Railway also documents PostgreSQL point-in-time recovery for eligible Postgres deployments. Raff Apps supports persistent volumes, but this comparison does not claim a native Apps-volume backup schedule that is absent from the current canonical specification. For teams that want database operations separated from application runtime, Raff provides first-party Managed Databases for **five engines: PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka**. ### Trust and support Railway's current Trustpilot profile shows **2.9/5**; the profile is marked as merged, so that signal should be interpreted cautiously rather than treated as a clean product benchmark. Railway's own support documentation says its Central Station community has **1.8 million+ users and developers**, a much larger public community signal than Raff's current customer count. Raff's current Trustpilot profile is **4.5/5**, and Raff reports **3,000+ customers and 15,000+ production VMs**. Raff publishes a **99.9% platform SLA**. Railway Pro support usually targets responses within 72 hours but explicitly excludes SLOs; Railway can provide Business Class SLOs and negotiate a contractual SLA for Enterprise customers. ## When you should choose Railway over Raff Choose Railway when: - **You need more regions.** Railway exposes **4 standard deployment regions** versus Raff Apps' single public `us-east` region. - **Usage-based billing matches the workload.** Railway meters CPU at **$20/vCPU-month** and RAM at **$10/GB-month**, which can suit low-duty-cycle services better than a fixed tier. - **Native volume backups are important.** Railway supports daily, weekly, and monthly schedules with retention up to **3 months** on the monthly schedule. - **PR infrastructure is central to development.** Railway can provision full or focused PR Environments automatically from GitHub pull requests. - **You want explicit replica controls.** Current plan limits allow up to **6 replicas on Hobby** and **42 on Pro**. - **A $0 experimentation tier matters.** Railway Free includes **$1 of resource usage per month**. - **Railway's deployment canvas and templates fit the team.** GitHub, Docker images, databases, volumes, variables, and services are modeled in one project workflow. ## When you should choose Raff over Railway Choose Raff Apps when: - **A fixed cost ceiling matters.** Raff Apps starts at **$3/month** and publishes ceilings through **$119.99/month** rather than leaving CPU and RAM fully variable. - **Public egress is material.** Raff Apps charges **$0** for public app egress versus Railway's **$0.05/GB**. - **Docker Compose is the deployment artifact.** Raff imports a **full Compose stack**; Railway maps Compose services into separate Railway services instead of running the Compose file directly. - **First-party managed data should be separate from app containers.** Raff provides **5 managed data engines**: PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka. - **One public eastern-U.S. region is sufficient.** Railway's four-region advantage has less value when `us-east` already satisfies latency and architecture needs. - **A published standard SLA matters.** Raff publishes a **99.9% platform SLA**, while Railway's Pro support documentation explicitly excludes SLOs. - **Predictable team pricing matters.** Raff Apps seats cost **$0**, and the spend cap is enabled by default. Raff currently reports **3,000+ customers and 15,000+ production VMs**. For adjacent app-platform decisions, compare [Render and Raff](/learn/compare/render-alternative), [DigitalOcean App Platform and Raff](/learn/compare/digitalocean-app-platform-alternative), and [Fly.io and Raff](/learn/compare/flyio-alternative). ## Migrating from Railway to Raff 1. **Inventory the Railway project.** Record services, GitHub repositories, Docker images, build and start commands, variables, private-network dependencies, public domains, replicas, regions, cron jobs, functions, volumes, database services, backup schedules, and PR Environment behavior. 2. **Map Railway services to Raff Apps.** Move public HTTP workloads to web services, internal APIs to private services, queue consumers to workers, schedules to cron jobs, and administrative tasks to one-off jobs. **Gotcha:** a Railway project can contain service relationships that are implicit in reference variables and internal DNS, so document them before migration. 3. **Choose the deployment source.** Use GitHub, a Dockerfile, an existing image, buildpacks, or Docker Compose on Raff. If the original architecture started from Compose, this is the point to restore the Compose file as the source of truth rather than maintaining a Railway-specific service translation. 4. **Move durable state.** Export Railway PostgreSQL, MySQL, Redis, MongoDB, or other database data with native tools and copy volume data through an application-safe workflow. **Gotcha:** Railway deployment rollback restores code/image and variables, not a database; volume backups must be restored or exported separately. 5. **Recreate configuration and verify.** Add secrets, private service bindings, domains, health checks, persistent volumes, managed data services, callbacks, and external allowlists. Test startup ordering, background workers, cron behavior, cold-start expectations, restore procedures, and a temporary hostname before cutover. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, freeze writes where required, run the final data sync, update DNS and callback URLs, monitor production, and retain the Railway environment until the rollback window closes. Stateless GitHub or container services are generally the easiest part of a Railway-to-Raff migration. Stateful volumes, database recovery, Railway reference variables, PR-environment assumptions, multi-region placement, internal DNS, and provider-specific deployment settings create most of the migration risk. ## About Railway [Railway](https://railway.com) is a deployment platform operated by **Railway Corporation**, with its legal contact address in San Francisco, California. It provides application services, cron jobs, functions, databases, volumes, private networking, deployment regions, GitHub automation, PR environments, observability, and usage-based billing for developers and production teams. Railway pricing, region, backup, deployment, and support claims in this comparison were verified against Railway's official documentation on August 17, 2026. ## Conclusion: Railway or Raff? The Railway-versus-Raff decision resolves across four measured axes: cost model, geographic/scaling reach, deployment portability, and data/reliability operations. - **Cost model:** Raff Apps starts at **$3/month** with fixed service ceilings and $0 public egress; Railway starts at $0, then meters CPU at **$20/vCPU-month**, RAM at **$10/GB-month**, and egress at **$0.05/GB**. - **Geographic and scaling reach:** Railway exposes **4 regions** and up to **42 Pro replicas**; Raff Apps exposes one public `us-east` region and a simpler fixed-tier operating model. - **Deployment portability:** Raff supports full Docker Compose import, while Railway translates Compose services into Railway services; both support GitHub and container workflows. - **Data and reliability operations:** Railway has native scheduled volume backups and Enterprise SLA options; Raff publishes a **99.9% platform SLA** and separates application runtime from five first-party managed data engines. Choose Railway when global placement, explicit replicas, native volume backup schedules, PR environments, or pay-for-actual-use economics are the deciding requirements. Choose Raff when `us-east` is sufficient and fixed service ceilings, $0 public egress, Compose portability, and first-party managed data make the app bill and architecture easier to reason about. Raff currently reports **3,000+ customers, 15,000+ production VMs, Trustpilot 4.5/5, G2 4.6/5, and a 99.9% platform SLA**. Railway's public Trustpilot profile currently shows **2.9/5**, while Railway reports a Central Station community of **1.8 million+ users and developers**; the different sample sizes and profile structures make review scores context rather than a substitute for technical due diligence. --- ### Netlify Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/netlify-alternative Description: Considering Netlify? Raff Apps starts at $3/mo with $0 public egress; Netlify starts free and Pro begins at $20/mo. Raff Apps wins on fixed service resources, full Docker Compose import, long-running workers, private services, and $0 public application egress. Netlify wins on its $0 plan, global CDN, unlimited deploy previews, Edge Functions, framework-aware delivery, and mature frontend collaboration workflow. Choose Netlify when global frontend delivery and edge-native workflows are requirements; choose Raff when the application is a portable service stack with explicit compute and transfer boundaries. Raff Apps starts at $3/month, while Netlify starts at $0 and Pro now ranges from $20 for 3,000 credits to $126 for 20,000 credits. Raff Apps is a Netlify alternative for teams whose production workload looks more like connected application services than a frontend delivery project. Netlify packages deploys, compute, bandwidth, requests, database usage, and AI activity into credits, while Raff Technologies prices application services through published vCPU/RAM tiers with per-second billing and monthly ceilings. Netlify has the stronger built-in global delivery layer; Raff has the more explicit model for workers, private services, persistent volumes and Docker Compose stacks. ## Netlify vs Raff: which is right for you? Choose based on workload shape first, then pricing. Netlify is strongest when the deployment workflow, CDN, edge execution, previews, and frontend tooling are part of the product architecture. Raff is strongest when the application is a set of portable services that should remain understandable as compute, data, storage, and networking components. | Decision factor | Choose Raff Apps | Choose Netlify | |---|---|---| | Primary workload | APIs, containers, workers, cron jobs, private services, and multi-service stacks | Static sites, framework frontends, Functions, Edge Functions, and globally cached web applications | | Entry path | Micro from $3/month with explicit resources | Free at $0 with 300 credits | | Team plan | No workspace or seat fee | Pro starts at $20/month with 3,000 credits and unlimited members | | Public transfer | $0 application egress | 20 credits per GB of bandwidth | | Deployment package | GitHub, buildpacks, Dockerfile, container image, Docker Compose | Git, CLI, API, framework builds, Functions, Edge Functions | | Data layer | Managed PostgreSQL, MySQL, Valkey, ClickHouse, Kafka, object storage, persistent volumes | Netlify Database, Netlify Blobs, and integrations | | Global delivery | Add an external CDN when required | Global CDN and worldwide Edge Function execution are built in | Our product decision at Raff was to put cost boundaries in place before traffic arrives: each service has a published monthly ceiling, public app egress is $0, and the spend cap starts enabled. That matters for small teams running several persistent processes because the bill does not depend on combining deploy, request, bandwidth, function, and team-seat meters after launch. For the broader architecture decision, review [Cloud VM vs App Platform: What Startups Should Know](/learn/guides/cloud-vm-vs-app-platform-startups). ## Netlify overview [Netlify](https://www.netlify.com/) is a managed web development platform for deploying and serving modern web applications. It connects to source repositories, creates production and preview deployments, serves content through a global CDN, runs Functions and Edge Functions, manages domains and TLS, and provides observability and collaboration features around the deployment lifecycle. Current [Netlify pricing](https://www.netlify.com/pricing/) uses credits for new standard-plan accounts: - **Free — $0/month:** 300 credits and a hard monthly credit limit. - **Personal — $9/month:** 1,000 credits with optional additional credit packs or auto recharge. - **Pro — $20 to $126/month:** five monthly credit tiers from 3,000 to 20,000 credits, all with unlimited members. - **Enterprise — custom:** adds a 99.99% SLA, enterprise network tier, SSO, SCIM, log drains, organization management, and dedicated support. The current Pro tiers are **3,000 credits for $20**, **5,000 for $33**, **10,000 for $63**, **15,000 for $95**, and **20,000 for $126**. Pro tiers with 5,000 credits or more can roll unused monthly credits into the next billing cycle; the base 3,000-credit tier does not roll over. Netlify converts platform usage into a shared credit balance. Production deploys cost **15 credits each**, compute costs **10 credits per GB-hour**, bandwidth costs **20 credits per GB**, and web requests cost **2 credits per 10,000 requests**. Deploy previews and branch deploys do not consume production-deploy credits, although their traffic and compute can still consume the relevant meters. Netlify's genuine strengths are global frontend delivery, unlimited deploy previews, framework-aware builds, Edge Functions, instant cache behavior, integrated web observability, and a permanent $0 entry plan. Its trade-off is that the same credit balance is consumed by several workload dimensions, so production cost depends on how the application deploys, computes, transfers data, and receives requests. ## Raff overview [Raff Apps](/products/app-platform) deploys source code and containers without requiring teams to administer the operating system. It supports GitHub push-to-deploy, Dockerfiles, existing container images, automatic buildpacks, full Docker Compose imports, immutable revisions, one-click rollback, pull-request preview environments, persistent volumes, and scale-to-zero behavior. Raff Apps supports public web services, private services, background workers, timezone-aware cron jobs, and one-off jobs. Applications can connect to managed PostgreSQL, MySQL, Valkey, ClickHouse, and Kafka, plus object storage, VMs, private networking, Kubernetes, and Functions. Current Raff Apps tiers are: | Tier | vCPU | RAM | Ephemeral disk | Monthly ceiling | |---|---:|---:|---:|---:| | Micro | 0.25 | 512 MB | 2 GB | $3.00 | | Starter | 0.5 | 1 GB | 5 GB | $6.99 | | Standard | 1 | 2 GB | 10 GB | $16.99 | | Pro | 2 | 4 GB | 20 GB | $27.99 | | Pro Max | 4 | 8 GB | 40 GB | $61.99 | | Scale | 8 | 16 GB | 80 GB | $119.99 | Compute is billed per second against the published monthly ceiling. Public application egress and team seats are priced at $0, and the spend cap is enabled by default. Raff currently reports **3,000+ customers, 15,000+ production VMs, and a 99.9% platform SLA**. Raff Technologies was verified at **4.5/5** on August 16, 2026, and G2 is 4.6/5. Raff is geographically narrower than Netlify; its advantage is the explicit service model and a single cloud account for app, database, object storage, VM, private network, Kubernetes, and Functions workloads. ## Netlify pricing vs Raff pricing Netlify and Raff charge for different units. Raff prices continuously running application services by fixed vCPU/RAM tiers. Netlify charges a plan price that includes a shared credit allowance, then consumes those credits across production deploys, compute, bandwidth, web requests, database activity, and AI usage. The closest useful buying positions are: | Buying position | Raff Apps | Netlify | Decision signal | |---|---:|---:|---| | Free evaluation | Micro $3 — 0.25 vCPU / 512 MB | Free $0 — 300 credits | Netlify wins when a hard-limited $0 frontend plan is enough | | Personal production | Starter $6.99 — 0.5 vCPU / 1 GB | Personal $9 — 1,000 credits | Raff publishes resources; Netlify publishes a shared usage allowance | | Small team | Standard $16.99 — 1 vCPU / 2 GB | Pro $20 — 3,000 credits and unlimited members | Netlify includes team frontend tooling; Raff includes fixed application compute | | Higher-credit team | Pro $27.99 — 2 vCPU / 4 GB | Pro $126 — 20,000 credits with one-cycle rollover | Different buying models; compare actual deploy, compute, transfer, and request usage | | 5 TB public bandwidth | $0 app-egress line; compute separate | About $670 in extra Pro credit packs on the base plan, plus the $20 plan, if all monthly credits otherwise go to bandwidth | Bandwidth-heavy workloads can diverge sharply | **Comparison class:** these are planning positions, not performance-equivalent instances. Netlify Functions and Raff application services use different execution, scaling, caching, host, and network models, so matching price points does not prove equal throughput or latency. ### Bandwidth cost math Netlify consumes **20 credits per GB** of bandwidth. On the base Pro plan, 3,000 monthly credits are included and additional credits can be purchased in **1,500-credit packs for $10**. The following examples assume all 3,000 monthly credits are available for bandwidth and ignore deploy, compute, request, database, form, and AI usage: | Monthly public bandwidth | Raff Apps public egress | Netlify base Pro credit cost | |---:|---:|---:| | 1 TB | $0 | About $120 extra credits + $20 Pro | | 5 TB | $0 | About $670 extra credits + $20 Pro | | 10 TB | $0 | About $1,350 extra credits + $20 Pro | | 50 TB | $0 | About $6,810 extra credits + $20 Pro | Higher Pro credit tiers can reduce the effective per-credit price and unused monthly credits can roll for one billing cycle on tiers of 5,000 or more. The table therefore illustrates the base-plan transfer economics, not the lowest possible Netlify price for every traffic pattern. ### Automated backups [Netlify Database backup and recovery](https://docs.netlify.com/build/data-and-storage/netlify-database/backup-and-recovery/) is more specific than the old comparison implied. Netlify automatically backs up the production database **daily at midnight UTC** and also takes a backup whenever a production deploy is published for a project with a database. Retention depends on plan: Free retains scheduled backups for **3 days** and the most recently published deploy backup; Personal retains scheduled backups for **7 days** and the last **3** deploy backups; Pro and Enterprise retain scheduled backups for **30 days** and the last **10** deploy backups. Restoring replaces the production branch with the selected backup, so application teams should account for data created after that backup. Raff Apps likewise separates application deployment rollback from durable-data recovery. Ephemeral app storage is not a backup; production state should live in managed databases, object storage, or persistent volumes with recovery procedures tested independently from application deploy rollback. ### Credit controls and hidden cost drivers Netlify auto recharge is disabled by default. When enabled, Personal purchases **500 credits for $5** as needed and Pro purchases **1,500 credits for $10** as needed. Purchased credits do not expire. If auto recharge stays disabled, a paid account can instead purchase credit packs manually; Free has a hard limit and no recharge option. The main cost drivers to model are production deploy frequency, function/database compute GB-hours, web and database bandwidth, web requests, and AI inference. A low-traffic static site can remain inexpensive, while an application with high traffic, frequent server-side execution, or database activity can consume the same shared credit balance quickly. :::cta Deploy an App Now Deploy web services, workers, cron jobs, and Docker Compose stacks with explicit monthly ceilings. ::: ## Bandwidth and transfer policy Raff Apps charges **$0 for public application egress**. Netlify consumes **20 credits per GB** for bandwidth sent to the internet, including web content, assets, image delivery, downloads, function responses, and database bandwidth where applicable. Netlify's global CDN can reduce origin work and improve delivery latency, so its bandwidth meter should not be evaluated separately from the value of built-in caching and edge delivery. A static or heavily cached international site can benefit from Netlify's architecture even when the billing model is more complex than a flat transfer policy. For dynamic APIs, downloads, media delivery, package distribution, or other workloads where public transfer is large and difficult to predict, Raff's $0 app-egress line is easier to budget. The key difference is not that one platform has bandwidth and the other does not; it is that Netlify converts bandwidth into shared credits while Raff does not meter public Apps egress separately. ## Feature comparison: Netlify vs Raff | Feature | Raff Apps | Netlify | |---|---|---| | Primary deployment model | Long-running services and containers | Frontend deployments, Functions, and Edge Functions | | Git deployment | GitHub | Git providers, CLI, API, and agent workflows | | Dockerfile / existing image | Yes | Not the primary general-service model | | Full Docker Compose import | Yes | No native whole-stack Compose import | | Deploy previews | Pull-request previews | Unlimited deploy previews and branch deploys | | Global CDN | External CDN can be added | Built in | | Edge execution | Application/external edge layer | Edge Functions run on worldwide edge locations | | Always-on worker | Yes | Not a general worker-container product | | Private service | Yes | Not a general private-service product | | Cron jobs | Timezone-aware jobs | Scheduled Functions | | Persistent mounted volume | Yes | Data products rather than a general mounted filesystem | | Managed PostgreSQL | First-party Raff managed database | Netlify Database | | Managed MySQL | First-party Raff managed database | No first-party managed MySQL product listed | | Redis-compatible managed service | Valkey | External integration | | Object storage | Raff Object Storage | Netlify Blobs | | Team seats | $0 | Unlimited on Pro | | Public app bandwidth | $0 | 20 credits per GB | | Rollback | Immutable revisions and one-click rollback | Production deploy rollback | Netlify wins on global CDN delivery, Edge Functions, deploy previews, framework-aware frontend workflow, web observability, and a permanent free tier. Raff wins on containers, Docker Compose, long-running workers, private services, explicit vCPU/RAM tiers, mounted persistent volumes, managed MySQL, and $0 public app egress. ## Features and reliability: Raff vs Netlify This comparison includes **0 controlled Raff-versus-Netlify application benchmarks**, so it does not declare either platform faster. A credible test would need the same application code, cache behavior, function or service resources, datastore location, request mix, concurrency, and client regions. ### Global frontend delivery Netlify's CDN is distributed across regions worldwide, and Edge Functions run from the worldwide edge location closest to the user. That gives Netlify the stronger default architecture for globally distributed static content, cached frontends, request rewriting, and edge personalization. Raff Apps currently exposes one public `us-east` region. A team can place a CDN in front of a Raff service, but that is an additional architectural component. For international frontend delivery with minimal infrastructure assembly, Netlify has a genuine advantage. ### Application process model Raff exposes explicit service resources and persistent process types. A Standard service provides 1 vCPU and 2 GB RAM; workers, private services, cron jobs, and web services can run as distinct components. Netlify Functions and Edge Functions fit request-driven and frontend-adjacent logic. They remove server-process management but do not represent the same operating model as a continuously available container or background worker. ### Deployment and data recovery Netlify production deploys can be rolled back, and Netlify Database provides scheduled and publish-triggered backups with plan-specific retention. Those are separate recovery layers: rolling back code does not automatically restore application data. Raff also separates application revisions from durable-data recovery. Production teams should test both code rollback and state restoration, including database exports/restores, object recovery, secrets, DNS, and external callbacks. ### Operating trust Netlify's official company page reports **$212 million raised**, and Enterprise includes a **99.99% SLA**. Raff reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. These are different trust signals. Netlify has the longer specialized frontend-platform history and larger funding base; Raff provides a smaller cloud with public customer, VM, SLA, and review metrics. ## When you should choose Netlify over Raff Choose Netlify when: - **A permanent $0 plan matters.** Netlify Free includes 300 monthly credits; Raff Apps starts at $3/month. - **The project is frontend-first.** Framework builds, CDN delivery, previews, cache behavior, and web observability are integrated. - **Worldwide edge execution is required.** Edge Functions run from Netlify's worldwide edge locations close to users. - **Every branch needs a review environment.** Deploy previews and branch deploys do not consume production-deploy credits. - **The team wants unlimited Pro members.** Netlify Pro starts at $20/month and no longer uses per-seat pricing for team members. - **Built-in Postgres branching and deploy-linked backups fit the workflow.** Netlify Database backs up daily and on production publish, with Pro retention up to 30 days. - **Enterprise frontend controls are required.** Netlify Enterprise adds a 99.99% SLA, enterprise network tier, SSO, SCIM, log drains, and dedicated support. ## When you should choose Raff over Netlify Choose Raff Apps when: - **The application is container-first.** Raff accepts Dockerfiles, existing images, buildpacks, and full Docker Compose stacks. - **Long-running processes are required.** Web services, private services, workers, cron jobs, and one-off jobs map directly to persistent service types. - **Compute should be explicit.** Raff Standard is $16.99 for 1 vCPU / 2 GB and Raff Pro is $27.99 for 2 vCPU / 4 GB. - **Public egress is substantial.** Raff app egress is $0, while Netlify consumes 20 credits for every GB of metered bandwidth. - **Managed MySQL is required.** Raff provides managed MySQL alongside PostgreSQL, Valkey, ClickHouse, and Kafka. - **Mounted persistent storage is required.** Raff Apps supports persistent volumes for state that must survive deployments and restarts. - **Docker Compose portability matters.** A multi-service development stack can be imported instead of translated into several frontend-platform primitives. ## Migrating from Netlify to Raff 1. **Inventory the Netlify project.** Record the framework, build command, publish directory, Functions, Edge Functions, Scheduled Functions, redirects, headers, forms, Blobs, Database, environment contexts, domains, analytics, and deploy-preview behavior. 2. **Choose the Raff deployment package.** Use a buildpack for a conventional app, a Dockerfile for reproducible builds, an existing image for a prebuilt artifact, or Docker Compose for a multi-service stack. **Gotcha:** Netlify project configuration does not map one-to-one to a container definition. 3. **Map execution units.** Convert HTTP Functions into web-service routes, background work into workers, schedules into cron jobs, and internal APIs into private services where appropriate. **Gotcha:** Edge Functions can rely on edge-specific runtime behavior that must be recreated in application middleware or another edge layer. 4. **Move persistent state.** Export Netlify Database through PostgreSQL-compatible tooling, copy Netlify Blobs data to Raff Object Storage where appropriate, recreate secrets, and replace any platform-specific form or identity dependencies before cutover. 5. **Rebuild delivery behavior and test.** Recreate redirects, headers, caching, image delivery, custom domains, preview rules, and an external CDN when global edge delivery remains necessary. Test database restore, object access, webhooks, OAuth callbacks, and client latency. 6. **Cut over with rollback.** Lower DNS TTL to **300 seconds**, perform the final data sync, switch DNS and external callbacks, monitor production, and keep the Netlify project available until the rollback window closes. Stateless frontend assets and portable application code are usually the easiest parts to move. Edge behavior, platform-specific Functions, redirects, Blobs, database branches, forms, identity dependencies, and global cache behavior create most migration risk. ## About Netlify [Netlify](https://www.netlify.com/about/) is operated by Netlify, Inc., a web development platform company founded in 2014 and headquartered in San Francisco. It provides Git and API deployments, a global CDN, deploy previews, Functions, Edge Functions, Netlify Database, Netlify Blobs, observability, security controls, and enterprise web-delivery capabilities. Netlify reports $212 million raised. ## Conclusion: Netlify or Raff? The Netlify-versus-Raff decision resolves across four measured axes: delivery model, application process model, pricing model, and data portability. - **Delivery model:** Netlify includes global CDN and edge execution; Raff Apps exposes `us-east` application compute and can use an external CDN when required. - **Application model:** Netlify centers frontend deploys, Functions, and Edge Functions; Raff centers containers, workers, private services, cron jobs, and Docker Compose stacks. - **Pricing model:** Netlify starts at $0 and Pro ranges from $20/3,000 credits to $126/20,000 credits; Raff Apps starts at $3 with explicit service-resource ceilings. - **Data portability:** Netlify provides Database and Blobs within its frontend workflow; Raff connects Apps to managed databases, object storage, persistent volumes, VMs, Kubernetes, and Functions. Choose Netlify when global frontend delivery, previews, edge execution, and its credit-based web workflow remove more operating work than the usage model adds. Choose Raff when the production system is a portable service stack and explicit compute, process, storage, and transfer boundaries are more important than a built-in global edge network. Raff currently reports **3,000+ customers, 15,000+ production VMs, a 99.9% platform SLA, Trustpilot 4.5/5, and G2 4.6/5**. For adjacent decisions, review [Render Alternative 2026](/learn/compare/render-alternative), [Vercel Alternative 2026](/learn/compare/vercel-alternative), and [Railway comparison](/learn/compare/raff-vs-railway). --- ### Netcup Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-netcup Description: Considering Netcup? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe from us-east, with no setup fee and 24/7 support. Netcup is a German hosting provider with a reputation for selling more hardware per euro than almost anyone in Europe. Raff Technologies is a US cloud provider where the virtual machine is one product among several, alongside managed databases, object storage, Functions and Kubernetes on the same account. On raw specifications this is not a close comparison: Netcup VPS 500 G12 lists 2 vCores, 4 GB DDR5 ECC and 128 GB NVMe for €5.91/month including VAT, while the closest Raff plan is $13.99/month with 80 GB. Both offer US hosting, both use DDR5 ECC and NVMe. What differs is what runs beside the server, and who operates it. ## Netcup VPS and Raff at a glance **Netcup** sells two server lines. **VPS** uses shared vCores and is the volume product; **Root Server** provides dedicated cores. Alongside them it sells web hosting, domains and related services. The current VPS generation is the G12 series, running from VPS 500 G12 at 2 vCores, 4 GB DDR5 and 128 GB NVMe up to VPS 8000 G12 at 16 vCores, 64 GB and 2 TB. Every plan includes traffic, copy-on-write snapshots and a remote console, on DDR5 ECC memory and NVMe storage. Netcup operates data centers in **Vienna, Nuremberg, Amsterdam, Manassas (USA) and Singapore** — a wider footprint than Raff's single us-east region, including a US East presence. The location is chosen on the product page before ordering, and Netcup does not list a location surcharge: the same plan costs the same in Manassas as in Nuremberg. Billing is either a 12-month term or hourly with no minimum commitment, and listed prices **include 19% German VAT**; the rate varies by the country you select. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from its us-east region, with a 99.9% uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access, with no setup fee and no term. Past the VM, Raff sells S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Netcup VPS pricing vs Raff pricing Netcup VPS uses shared vCores, so the like-for-like Raff line is General Purpose. | Shape | Netcup VPS G12 | Netcup ex-VAT | Raff General Purpose | |---|---|---|---| | 2 cores / 4 GB | **€5.91** — VPS 500, 128 GB NVMe | €4.97 ≈ **$5.76** | **$13.99** — 2 vCPU / 4 GB / 80 GB NVMe | | 4 cores / 8 GB | **€10.37** — VPS 1000, 256 GB NVMe | €8.71 ≈ **$10.10** | **$30.99** — 4 vCPU / 8 GB / 160 GB NVMe | | 8 cores / 16 GB | **€19.25** — VPS 2000, 512 GB NVMe | €16.18 ≈ **$18.75** | **$59.99** — 8 vCPU / 16 GB / 320 GB NVMe | | 12 cores / 32 GB | **€32.41** — VPS 4000, 1 TB NVMe | €27.24 ≈ **$31.57** | **$90.99** — 12 vCPU / 24 GB / 480 GB NVMe | | 16 cores / 64 GB | **€47.95** — VPS 8000, 2 TB NVMe | €40.29 ≈ **$46.71** | **$129.99** — 16 vCPU / 32 GB / 640 GB NVMe | *Raff General Purpose against Netcup VPS — both shared vCores. Raff CPU-Optimized from $9.99/mo is the match for Netcup Root Server. Netcup list prices read 2026-08-18 and include 19% German VAT; the ex-VAT column is the figure a customer outside the EU is more likely to pay, converted at €1 = $1.1593 (ECB, 2026-08-17). Confirm your own VAT position with Netcup.* **Netcup wins on price and on specifications, decisively.** Comparing ex-VAT, Raff is 143% to 220% more expensive — and Netcup ships more of everything: 128 GB against 80 GB at the entry shape, 2 TB against 640 GB at the top, and 64 GB of RAM at 16 cores where Raff sells 32 GB at any price. There is no reading of this table where Raff is the value option, and this page will not pretend otherwise. The rest of the comparison is about what the extra money buys, and for a large share of readers the honest answer will be "nothing you need." ### Netcup's Root Server line for reference Netcup also sells **Root Server**, with dedicated cores rather than shared vCores. The like-for-like Raff line there is CPU-Optimized, and the gap is wider than on the shared comparison: | Shape | Netcup Root Server | Netcup ex-VAT | Raff CPU-Optimized | |---|---|---|---| | 4 dedicated / 8 GB | **€12.79** — RS 1000, 256 GB NVMe | ≈ **$12.46** | **$38.99** at 4 vCPU / 4 GB / 80 GB | | 8 dedicated / 16 GB | **€21.43** — RS 2000, 512 GB NVMe | ≈ **$20.88** | **$89.99** at 8 vCPU / 16 GB / 180 GB | | 12 dedicated / 32 GB | **€39.92** — RS 4000, 1 TB NVMe | ≈ **$38.89** | no Raff plan at 32 GB | | 16 dedicated / 64 GB | **€71.36** — RS 8000, 2 TB NVMe | ≈ **$69.52** | **$183.99** at 16 vCPU / 32 GB / 360 GB | Dedicated cores on Netcup cost less than shared vCPU on Raff. If guaranteed CPU allocation is what you are buying, Netcup Root Server is the cheaper way to buy it, and by a wide margin. ### Term and billing Netcup offers a 12-month term or hourly billing with no minimum commitment, and lists prices including 19% German VAT — the applicable rate depends on the country you select at checkout. Raff bills monthly in USD with no term, no VAT calculation, and a 14-day money-back guarantee. Confirm any setup or one-off fees with Netcup at checkout for the term you choose. ### Bandwidth Neither provider meters standard outbound transfer. Netcup includes traffic on its VPS plans; Raff includes unmetered transfer on a 3 Gbps port. Netcup does not publish a per-plan port speed on its VPS page, so this is not a comparison worth resting anything on. ### Automated backups Netcup includes snapshots on VPS plans. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. Confirm Netcup's current backup scheduling and retention options directly, as they differ from snapshot-only workflows. ## Netcup VPS performance vs Raff ### Methodology Raff figures are internal, measured March–May 2026 on a 2 vCPU / 4 GB shared instance. Netcup figures are third-party, from VPSBenchmarks, on an RS 1000 G12 with four **dedicated** cores in Manassas, Virginia — same region as Raff's us-east. Netcup states its VPS line carries no CPU guarantee, so a VPS would be expected to score at or below these numbers. ### Results | Metric | Raff GP (2 shared vCPU) | Netcup RS 1000 G12 (4 dedicated) | Notes | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,630 | Raff 39% higher | | Geekbench 6 multi-core | 4,057 (2 vCPU) | **5,130** (4 cores) | Netcup higher with twice the cores | | fio 4K read, 50/50 mix | **48,670 IOPS** | 37,250 IOPS | Raff 31% higher | | fio 1M sequential read | **2,491 MB/s** | 1,441 MB/s | Raff 73% higher | | fio 1M sequential write | 1,257 MB/s | **1,538 MB/s** | Netcup 22% higher | | iperf3 to NYC download | **3,635 Mbps** | 2,417 Mbps | Raff 50% higher | | iperf3 to NYC upload † | **9,574 Mbps** | 2,796 Mbps | Raff 3.4x higher | | iperf3 to Los Angeles download | **3,430 Mbps** | 2,099 Mbps | Raff 63% higher | † Raff publishes a 3 Gbps port on 10 Gbps host uplinks; 9,574 Mbps is a peak across parallel streams. ### What this tells you **Raff's shared vCPU scores 39% higher single-core than Netcup's guaranteed dedicated cores.** That is the most useful line in the table, because Netcup's VPS line — the one priced against Raff above — carries no CPU guarantee at all. If a Root Server measures 1,630, a VPS on the same platform is unlikely to exceed it. Raff also leads on random IOPS by 31% on the same 50/50 job, on sequential read by 73%, and on network by 50% to 3.4x within the same region. **Netcup leads on sequential write by 22%**, and on multi-core aggregate because it ships twice the cores at a third of the price. None of which changes the arithmetic. Netcup RS 1000 G12 is €12.79 including VAT — about $12.46 ex-VAT — for four dedicated cores, 8 GB and 256 GB. The closest Raff CPU-Optimized plan is $49.99. Raff is faster per core and faster on the network; Netcup is roughly four times cheaper and gives you twice the cores and twice the disk. **Location matters more than any of it.** Netcup offers Manassas at the same price as its German locations, so a US buyer should choose Manassas. Measured from a *German* Netcup host, throughput to US cities falls to 93 Mbps to New York and 35 Mbps to Los Angeles against 898 Mbps to Paris — picking the default European location will cost more performance than every CPU difference on this page combined. ## Netcup vs Raff: features and reliability ### Compute Netcup VPS offers five shared-vCore shapes from 2 to 16 cores and 4 to 64 GB DDR5, with more memory per core than Raff sells at any tier. Netcup Root Server offers dedicated cores for workloads that need them. Raff offers General Purpose from $4.99/month and CPU-Optimized dedicated vCPU from $9.99/month, on AMD EPYC with DDR5 ECC memory, scaling to 16 vCPU and 32 GB, with on-demand resize: stop the VM, switch plan, restart, with the difference settled to your account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking Raff includes a 3 Gbps port, private networking, VPC, firewall controls and site-to-site VPN gateways. Netcup includes traffic on its VPS plans; port speed is not published per plan. ### Storage Netcup includes substantially more local NVMe at every tier — 128 GB against Raff's 80 GB at the entry shape, 2 TB against 640 GB at the top. Raff separates storage into VM disk, block volumes at $0.08/GiB-month that resize independently of the VM, and S3-compatible object storage at $7/month for 100 GB and 1 TB of egress. ### Support and billing Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines, through the same queue. Billing is in USD with no VAT calculation and no setup fee. Netcup's prices include 19% German VAT and its standard term is 12 months, so the number you compare depends on your VAT position and how long you commit. Confirm Netcup's current support channels and response targets directly. ### Platform A VM is rarely the whole requirement. An application needs a database, somewhere to put uploads, background jobs, and eventually a way to scale past one server. On Raff those are products on the same account: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds per month, Raff Apps from $3/month, and managed Kubernetes with a free control plane. They connect over private networking, share one API, one CLI and one bill. Netcup sells servers, hosting and domains — a database, a queue and an object store are yours to assemble and operate. The honest counter-argument is strong here: a 32 GB Netcup VPS at €32.41 will run Postgres, Redis and your application together with room to spare, for a third of what the equivalent Raff stack costs. What you are then operating is backups, restore testing, failover, point-in-time recovery and version upgrades. If that work sits inside your team's capability and time budget, Netcup is the better buy and it is not close. ## When you should choose Netcup over Raff - **Wider choice of regions** — Vienna, Nuremberg, Amsterdam, Manassas in the US and Singapore, against Raff's single us-east - **Maximum specifications per euro** — 128 GB NVMe at the entry shape, 2 TB at the top, and 64 GB RAM at 16 cores that Raff does not sell at any price - **Memory-heavy and storage-heavy workloads** — self-hosted media, backup targets, analytics, large dev and CI fleets - **Teams comfortable operating their own data services** — a single large VPS running database, cache and application is genuinely cheaper - **Committed 12-month budgets** — the 12-month term carries no setup fee and the lowest monthly rate ## When you should choose Raff over Netcup - **Managed data services beside the VM** — PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month with backups, point-in-time recovery and failover operated for you - **Stacks that outgrow one server** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions and Kubernetes on the same account over private networking ([VPS for databases](/learn/guides/vps-for-databases)) - **Teams without database operations capacity** — managed engines with backups, PITR and failover handled, instead of self-hosting on a large VPS - **Buyers who want simple monthly billing** — USD, no term, no VAT position to work out, and a 14-day money-back guarantee - **Simple USD billing** — no VAT position to work out, no exchange-rate variance on the invoice - **24/7 human support** — live chat to the same engineers at any account size, first response typically under 10 minutes ## Migrating from Netcup to Raff 1. **Ask what you are actually buying** — if you want a cheap capable server, Netcup already sells one in the US. This migration only makes sense if you want the managed services beside it. 2. **Right-size on utilisation, not specifications** — Netcup ships far more RAM and disk than most workloads use. Measure actual consumption before matching 64 GB with 64 GB, because you cannot: Raff's ceiling is 32 GB. 3. **Plan the storage gap** — Netcup includes 128 GB to 2 TB locally. Decide what belongs on VM disk, what moves to block volumes at $0.08/GiB-month, and what belongs in object storage. 4. **Provision and harden** — create the Raff VM on the same distribution, apply firewall rules, attach private networking before moving data. 5. **Move data in order** — files with rsync or SCP, then database dumps, then static assets to object storage. Keep the Netcup VPS running throughout. 6. **Cut over and check the term** — lower DNS TTL beforehand, switch, then confirm your Netcup contract. A 12-month term continues after you migrate. ## About Netcup Netcup is a German hosting provider offering VPS, Root Server, web hosting, domains and related infrastructure services, serving customers from data centers in Vienna, Nuremberg, Amsterdam, Manassas in the United States and Singapore. It is known for high memory and storage allocations at low monthly prices. See [Netcup VPS](https://www.netcup.com/en/server/vps) for current plans and terms. ## Conclusion: Netcup or Raff? The comparison resolves across four axes: - **Price and specifications** — Netcup wins decisively: €5.91 (about $5.76 ex-VAT) against $13.99 at the entry shape, with more RAM and more disk at every tier - **Regions** — Netcup wins: Vienna, Nuremberg, Amsterdam, Manassas in the US and Singapore, against Raff's single us-east - **Platform** — Raff adds managed databases, object storage, Functions, Apps and Kubernetes on one account; Netcup sells servers, hosting and domains - **Billing** — Raff is USD, monthly, no term; Netcup is VAT-inclusive with a 12-month term or hourly billing If you want the most hardware per euro, a choice of regions, and you are comfortable running your own data services, choose Netcup — it is the better buy on price, specifications and geography, and the gap is large. Choose Raff only if you want managed databases, object storage and Functions operated for you beside the VM, with 24/7 support and no VAT or term to work out. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.9% uptime SLA in writing. --- ### Hostinger Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-hostinger Description: Considering Hostinger? Raff is $27.99/mo for 2 vCPU, 8 GB and 160 GB NVMe with unmetered transfer on a 3 Gbps port. Hostinger is one of the largest hosting companies in the world, selling shared hosting, WordPress hosting, domains, email and a four-plan VPS line to millions of customers. Raff Technologies is a US cloud provider where the virtual machine is one product among several, alongside managed databases, object storage, Functions and Kubernetes on the same account. Both sell shared-vCPU VMs on AMD EPYC with NVMe storage, so the comparison is a fair one: Hostinger KVM 2 lists at $24.49/month for 2 vCPU and 8 GB, and the closest Raff plan is $27.99/month. The interesting differences are not in the server — they are in the transfer policy, the disk, and what happens when one machine is no longer enough. ## Hostinger VPS and Raff at a glance **Hostinger** sells four KVM VPS plans, all on AMD EPYC with NVMe storage and a 1 Gbps network. KVM 1 is 1 vCPU, 4 GB RAM, 50 GB and 4 TB of transfer; KVM 8 is 8 vCPU, 32 GB, 400 GB and 32 TB. Every plan includes free weekly backups, firewall management, public API access, an AI-assisted web terminal, and a free domain for the first year. Pricing runs on three levels, and it matters which one you compare. The **list price** is what the plan costs without a term — $19.49, $24.49, $42.99 and $73.99. The **advertised price** is a 24-month promotional rate at 63–70% off. After that term the plan **renews** at a third price: $11.99, $14.99, $28.99 and $49.99. This page compares list prices, with promo and renewal shown alongside. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from its us-east region, with a 99.9% uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Past the VM the catalogs diverge. Raff sells S3-compatible object storage at $7/month for 100 GB and 1 TB of egress, managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. Hostinger bundles the things a website needs — a domain, email, a control panel. ## Hostinger VPS pricing vs Raff pricing Hostinger KVM plans use shared vCPU cores, so the like-for-like Raff line is General Purpose. | Shape | Hostinger KVM list | Hostinger 24-mo promo → renewal | Raff General Purpose | |---|---|---|---| | 1 vCPU / 4 GB | **$19.49** — KVM 1, 50 GB NVMe, 4 TB, 1 Gbps | $6.49 → $11.99 | **$13.99** — 2 vCPU / 4 GB / 80 GB NVMe, unmetered, 3 Gbps | | 2 vCPU / 8 GB | **$24.49** — KVM 2, 100 GB NVMe, 8 TB, 1 Gbps | $8.99 → $14.99 | **$27.99** — 2 vCPU / 8 GB / 160 GB NVMe, unmetered, 3 Gbps | | 4 vCPU / 16 GB | **$42.99** — KVM 4, 200 GB NVMe, 16 TB, 1 Gbps | $12.99 → $28.99 | **$52.99** — 4 vCPU / 16 GB / 320 GB NVMe, unmetered, 3 Gbps | | 8 vCPU / 32 GB | **$73.99** — KVM 8, 400 GB NVMe, 32 TB, 1 Gbps | $25.99 → $49.99 | **$115.99** — 8 vCPU / 32 GB / 640 GB NVMe, unmetered, 3 Gbps | *Raff General Purpose against Hostinger KVM — both shared AMD EPYC on NVMe. Hostinger publishes no dedicated-vCPU VPS line, so every row above is shared against shared. Hostinger list, promotional and renewal prices read from Hostinger's live pricing page on 2026-08-18; the promotional rate requires a 24-month term.* At list price the two are close, and at the smallest shape Raff is cheaper: $13.99 buys 2 vCPU, 4 GB and 80 GB against KVM 1's $19.49 for 1 vCPU, 4 GB and 50 GB — twice the cores and 60% more disk for less money. Against the 24-month promotional rate Hostinger is substantially cheaper at every tier, and against the renewal rate it stays cheaper from KVM 2 upward. Hostinger also ships more RAM per core across the range. ### Bandwidth cost math Hostinger meters transfer; Raff does not. There is no per-GB overage to calculate, because Hostinger does not bill overage — it throttles. Once a plan reaches its monthly cap the connection drops to **10 Mbps for the remainder of the month**, then resets. | Monthly transfer | Raff 2 vCPU / 8 GB | Hostinger KVM 2 (8 TB cap) | |---:|---|---| | 1 TB | $27.99 · 3 Gbps | $24.49 · full 1 Gbps | | 5 TB | $27.99 · 3 Gbps | $24.49 · full 1 Gbps | | 8 TB | $27.99 · 3 Gbps | at cap | | 10 TB | $27.99 · 3 Gbps | **throttled to 10 Mbps** for the rest of the month | | 25 TB | $27.99 · 3 Gbps | **throttled to 10 Mbps** for the rest of the month | The cost of exceeding the cap is not money, it is a 100x reduction in port speed until the calendar turns. For a media-heavy site, a backup target, or an API with a traffic spike, that is a harder failure than an overage line on an invoice. Hostinger's own guidance is to monitor usage in hPanel and upgrade the plan if the cap is reached repeatedly. The allowances are generous for most websites — 8 TB covers the large majority of small-business traffic. This matters at the tail, not the median. ### Automated backups Hostinger includes free weekly backups on VPS plans. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — and you choose the schedule: Daily, Weekly, or both running together, with retention from 1 to 365 days and uncapped snapshots. Storage above the pool is $0.06/GB-month. Weekly-only backups mean a worst-case recovery point of seven days. Match the schedule to how much work you can afford to lose. ## Hostinger VPS performance vs Raff This is the only comparison on this site backed by a paid head-to-head test rather than third-party data, and it does not flatter Raff on every axis. ### Methodology Measured 13 April 2026 on Ubuntu 24.04, single-pass: Raff General Purpose 2 vCPU / 4 GB in us-east against Hostinger KVM 2 in Boston, which carried roughly twice the RAM. Paid at standard rates by Raff Technologies, with no sponsorship or rebate from Hostinger. † † Raff publishes a 3 Gbps port on 10 Gbps host uplinks; 9,574 Mbps is a peak across parallel streams. ### Results | Benchmark | Raff GP 2 vCPU | Hostinger KVM 2 | Notes | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,976 | Raff 15% higher | | Geekbench 6 multi-core | **4,057** | 3,583 | Raff 13% higher | | sysbench CPU single-thread | **2,171 events/s** | 1,677 events/s | Raff 29% faster | | sysbench CPU multi-thread | **4,320 events/s** | 3,350 events/s | Raff 29% faster | | sysbench memory read | **17.79 GiB/s** | 11.15 GiB/s | Raff 59% faster | | sysbench memory write | **11.42 GiB/s** | 4.60 GiB/s | Raff 2.5x faster | | sysbench memory write 1MB block | 47.08 GiB/s | **48.42 GiB/s** | Hostinger 3% higher | | fio 4K random read | 48.67k IOPS | **60.5k IOPS** | Hostinger 24% faster | | fio 4K random write | 48.80k IOPS | **60.7k IOPS** | Hostinger 24% faster | | fio 64K random read | 22.81k IOPS | **49.59k IOPS** | Hostinger 2.2x faster | | fio 64K random write | 22.93k IOPS | **49.85k IOPS** | Hostinger 2.2x faster | | sysbench fileio random read 4K | 52.31 MiB/s | **143.42 MiB/s** | Hostinger 2.7x faster | | sysbench fileio sequential read 128K | 1,730 MiB/s | **2,616 MiB/s** | Hostinger 51% faster | | sysbench fileio sequential write 128K | 664.85 MiB/s | **990.77 MiB/s** | Hostinger 49% faster | | iperf3 to NYC download | **3,635 Mbps** | 1,024 Mbps | Raff 3.5x faster | | iperf3 to NYC upload | **9,574 Mbps** | 1,034 Mbps | Raff 9.3x faster | | iperf3 to London download | **2,693 Mbps** | 959 Mbps | Raff 2.8x faster | | iperf3 to Los Angeles download | **3,430 Mbps** | 962 Mbps | Raff 3.6x faster | | Rails saturation point | ≈60–70 req/s | ≈60–70 req/s | Comparable | | Rails timeouts at 70 req/s | **729 of 20,801** | 1,365 of 21,000 | Raff fewer errors at saturation | ### What this tells you The split is clean, and it runs both ways. **Raff wins CPU, memory and network.** 29% faster sysbench CPU on both single and multi-threaded runs, 2.5x faster default-block memory write, and 3.5x to 9.3x higher iperf3 throughput. The network gap tracks the published port speeds — 3 Gbps against 1 Gbps — so it is structural rather than tuning. **Hostinger wins disk, and not marginally:** 24% higher 4K random IOPS, 2.2x at 64K, 2.7x on sysbench fileio random read, and roughly 50% higher sequential read and write. That is architecture, not hardware quality. Hostinger attaches local NVMe directly to the host, so a small write lands and is done. Raff runs distributed block storage across an NVMe cluster, so the same write crosses the network and is replicated before it is acknowledged. No amount of tuning on Raff closes that particular gap. What the distributed model buys is everything around the disk: data replicated rather than pinned to one machine, snapshots and backups taken at the storage layer, and a VM that changes plan by stopping and restarting rather than being rebuilt and restored. At application level the two saturated at the same point, around 60–70 requests per second on a database-heavy Rails workload, with Raff returning about half the timeouts at saturation. Read it as a trade: Raff for CPU, memory and egress-heavy work; Hostinger for disk-bound work. ## Hostinger vs Raff: features and reliability ### Compute Hostinger offers four shared-vCPU KVM shapes from 1 to 8 cores and 4 to 32 GB RAM, shipping more RAM per core at every tier — 4 GB on a single core, 32 GB on eight. Raff offers General Purpose from $4.99/month and CPU-Optimized dedicated vCPU from $9.99/month, on AMD EPYC with DDR5 ECC memory, scaling to 16 vCPU and 32 GB, and pairs cores with memory more evenly. Raff plans resize on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. Hostinger includes a 1 Gbps network with metered transfer and firewall management. ### Storage Both use NVMe, in the two different arrangements described in the benchmark section — Hostinger local, Raff distributed. Hostinger includes 50 to 400 GB by plan; Raff includes 80 to 640 GB on the matched shapes, and separates storage into VM disk, block volumes at $0.08/GiB-month that resize independently, and S3-compatible object storage at $7/month for 100 GB and 1 TB of egress. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines, through the same queue. ### Platform A VM is rarely the whole requirement. An application needs a database, somewhere to put uploads, background jobs, and eventually a way to scale past one server. On Raff those are products on the same account: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds per month, Raff Apps from $3/month, and managed Kubernetes with a free control plane. They connect over private networking, share one API, one CLI and one bill. Hostinger's VPS bundles hosting-account conveniences instead — a free domain for the first year, an AI web terminal, hPanel — which are genuinely useful if the VPS is hosting websites rather than backing an application. The honest counter-argument is that you can run Postgres on the VPS itself for free. You can, and on a 32 GB KVM 8 it will run well. What you are then operating is backups, restore testing, failover, point-in-time recovery and version upgrades. If that work sits inside your team's capability and time budget, Hostinger is cheaper. If it does not, the question is not which VM costs less this month. ## When you should choose Hostinger over Raff - **Disk-bound databases and write-heavy queues** — 24% higher 4K random IOPS and 2.2x at 64K in paid head-to-head testing - **Websites with a domain, email and panel in one place** — a free domain for the first year, hPanel and an AI web terminal, none of which Raff offers ([VPS for web hosting](/learn/guides/vps-for-web-hosting)) - **Memory-heavy single servers on a budget** — 32 GB at 8 cores for $73.99 list, or $25.99 on a 24-month term - **Teams willing to commit two years** — promotional pricing at 63–70% off is genuinely cheaper than Raff at every tier ## When you should choose Raff over Hostinger - **Egress-heavy applications** — 9.3x higher measured iperf3 upload, unmetered on a 3 Gbps port, against a cap that throttles to 10 Mbps ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **CPU and memory-bound services** — 29% faster sysbench CPU and 2.5x faster memory write, which is what caches, queues and API workers are bound by - **Stacks that outgrow one server** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions and Kubernetes on the same account over private networking ([VPS for databases](/learn/guides/vps-for-databases)) - **Workloads needing a tighter recovery point** — Daily and Weekly schedules together with 1–365 day retention, against weekly-only backups - **Buyers who will not prepay two years** — monthly billing with a 14-day money-back guarantee, and no renewal step-up - **24/7 human support** — live chat to the same engineers at every account size, first response typically under 10 minutes ## Migrating from Hostinger to Raff 1. **Check your transfer profile first** — if you are near a Hostinger cap, that is the strongest single reason to move; if you use 200 GB a month, it is not a factor at all. 2. **Right-size on utilisation, not RAM** — Hostinger ships more memory per core. Measure what the workload actually uses before matching 32 GB with 32 GB. 3. **Provision and harden** — create the Raff VM on the same distribution, apply firewall rules, attach private networking before moving data. 4. **Move data in order** — files with rsync or SCP, then database dumps, then uploads and static assets to object storage. 5. **Test disk-bound paths explicitly** — Hostinger measured faster on small-block random I/O, and that is architectural rather than tunable. If your application is disk-bound, benchmark it on Raff before committing. 6. **Cut over and check the term** — lower DNS TTL beforehand, switch, then confirm your Hostinger billing term. A 24-month promotional term continues after migration, and the free domain is tied to that account. ## About Hostinger Hostinger is a hosting provider founded in 2004 and headquartered in Kaunas, Lithuania, offering shared hosting, WordPress hosting, domains, email and a four-plan KVM VPS line from data centers across several regions. See [Hostinger VPS hosting](https://www.hostinger.com/vps-hosting) for current plans and terms. ## Conclusion: Hostinger or Raff? The comparison resolves across four measured axes: - **Disk** — Hostinger wins, 24% higher 4K random IOPS and 2.2x at 64K - **CPU, memory and network** — Raff wins, 29% faster sysbench CPU, 2.5x memory write, 9.3x iperf3 upload - **Transfer** — Raff unmetered at 3 Gbps; Hostinger capped at 4–32 TB then throttled to 10 Mbps until the month resets - **Price** — Hostinger is cheaper on promotional and renewal pricing; at list price the two are close, and Raff is cheaper at the smallest shape, $13.99 for 2 vCPU / 4 GB / 80 GB against $19.49 for 1 vCPU / 4 GB / 50 GB If your workload is disk-bound, or you want a website, domain and panel on one bill and will commit to two years, choose Hostinger. If your workload is CPU, memory or egress-bound, or it will need a managed database, object storage or Functions next to the VM, choose Raff. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.9% uptime SLA in writing. --- ### Linode Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-linode Description: Considering Linode? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe against an identical $24 Linode Shared CPU plan. Linode is now Akamai Cloud, having been acquired in 2022 and folded into Akamai's edge network. It sells Shared CPU and Dedicated CPU compute, managed databases, Kubernetes, object storage and a large regional footprint, with the developer documentation and community that made Linode's name. Raff Technologies runs the same shape of platform — VMs, managed databases, Kubernetes, object storage, Functions and Apps on one account — from a single us-east region. At the matched shape, a Linode Shared CPU plan with 2 vCPU, 4 GB and 80 GB is $24/month; the identical Raff plan is $13.99. ## Linode VPS and Raff at a glance **Akamai Cloud** sells two compute lines. **Shared CPU** runs from $5/month for 1 vCPU, 1 GB and 25 GB, up to $576/month at 20 vCPU and 96 GB — and Akamai's own pricing page labels this line **"Legacy Hardware."** **Dedicated CPU** is the current G8 generation, from $50.40/month for 2 vCPU, 4 GB and 40 GB. Every plan includes a generous transfer allowance — 1 TB at the entry plan rising to 20 TB — with overage at **$0.005 per GB**, half what most competitors charge. Around the compute sit managed MySQL and PostgreSQL from $16/month, Kubernetes with an optional HA control plane at $60 per cluster per month, and object storage at **$0.02/GB** with the first 1 TB of egress free each month. Behind all of it is Akamai's global edge network, which no independent provider can match. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.90% monthly uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Raff's catalog covers managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, S3-compatible object storage at $7/month for 100 GB with 1 TB of egress, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Linode VPS pricing vs Raff pricing Linode Shared CPU matches Raff General Purpose; Linode Dedicated CPU matches Raff CPU-Optimized. ### Shared vCPU: Raff General Purpose against Linode Shared CPU | Shape | Raff General Purpose | Linode Shared CPU | |---|---|---| | 1 vCPU / 1 GB | **$4.99** — 25 GB, unmetered | $5.00 — Nanode 1 GB, 25 GB, 1 TB | | 1 vCPU / 2 GB | **$6.99** — 50 GB, unmetered | $12.00 — Linode 2 GB, 50 GB, 2 TB | | 2 vCPU / 4 GB | **$13.99** — 80 GB, unmetered | $24.00 — Linode 4 GB, 80 GB, 4 TB | | 4 vCPU / 8 GB | **$30.99** — 160 GB, unmetered | $48.00 — Linode 8 GB, 160 GB, 5 TB | | 8 vCPU / 16 GB | **$59.99** — 320 GB, unmetered | $96.00 — Linode 16 GB, **6 vCPU**, 320 GB, 8 TB | | 8 vCPU / 32 GB | **$115.99** — 640 GB, unmetered | $192.00 — Linode 32 GB, 640 GB, 16 TB | Four of those rows are **identical on cores, memory and disk** — 25 GB, 80 GB, 160 GB and 640 GB. Raff runs **35% to 42% cheaper** across them, and at the 16 GB shape Raff gives 8 vCPU against Linode's 6 for 38% less. ### Dedicated vCPU: Raff CPU-Optimized against Linode Dedicated CPU (G8) | Shape | Raff CPU-Optimized | Linode Dedicated G8 | |---|---|---| | 2 vCPU / 4 GB | **$27.99** — 80 GB | $50.40 — 40 GB | | 4 vCPU / 8 GB | **$49.99** — 120 GB | $100.80 — 80 GB | | 8 vCPU / 16 GB | **$89.99** — 180 GB | $194.40 — 160 GB | Raff is **44% to 54% cheaper** on dedicated vCPU, with more included disk at every shape. *Akamai Cloud prices read from the North America pricing page on 2026-08-20. Akamai labels the Shared CPU line "Legacy Hardware"; the Dedicated CPU line is the current G8 generation.* ### The hardware-generation caveat That "Legacy Hardware" label matters, and it cuts both ways. The Shared CPU line is the one priced against Raff General Purpose above, and Akamai is signalling it runs on older hosts. If you are buying shared vCPU from Akamai today, you are buying a line the vendor itself marks as legacy — but it is also the line where the transfer allowances are largest, and none of that tells you how a given workload performs. ### Bandwidth cost math Linode's transfer allowances are the most generous in this comparison set — 1 TB to 20 TB by plan, pooled across the account — and overage is **$0.005/GB**, half DigitalOcean's rate. Raff includes unmetered transfer on a 3 Gbps port. | Monthly egress on a 2 vCPU / 4 GB VM | Raff | Linode (4 TB included) | |---:|---|---| | 4 TB | $13.99 | $24.00 | | 8 TB | **$13.99** | $24.00 + $20.48 = $44.48 | | 20 TB | **$13.99** | $24.00 + $81.92 = $105.92 | At 20 TB Linode costs about seven and a half times Raff. But at typical volumes the allowance covers it, and $0.005/GB is a fair overage rate — this axis matters less against Linode than against providers charging twice that. ### Automated backups Linode sells Backups as a per-plan add-on. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. ## Linode VPS performance vs Raff This is a clean pairing: both machines are shared-CPU with no dedicated or burstable allocation, both are 2 cores with 4 GB and 80 GB, and both sit in US East — Linode in Cedar Knolls, New Jersey, Raff in us-east. ### Methodology Raff figures are internal, measured March–May 2026 on a General Purpose 2 vCPU / 4 GB instance in us-east. Linode figures are third-party, from VPSBenchmarks, on a **Shared 4GB** plan ($24.00/month, 2 cores / 4 GB / 80 GB, KVM) in New Jersey running Ubuntu 24.04, trial started **17 October 2025** — older than Raff's run, and worth weighing accordingly. ### Results | Metric | Raff General Purpose | Linode Shared 4GB | Notes | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,245 | Raff 1.82x higher | | Geekbench 6 multi-core | **4,057** | 2,222 | Raff 1.83x higher | | fio 4K read, 50/50 mix | **48,670 IOPS** | 32,269 IOPS | Raff 1.51x higher | | fio 1M sequential read | **2,491 MB/s** | 2,206 MB/s | Raff 1.13x higher | | fio 1M sequential write | 1,257 MB/s | **2,353 MB/s** | Linode 1.87x higher | | iperf3 to NYC, upload | **9,574 Mbps** | 4,506 Mbps | Raff 2.12x higher | | iperf3 to NYC, download | 3,635 Mbps | **8,049 Mbps** | Linode 2.21x higher | | Processor | AMD EPYC, DDR5 ECC | **AMD EPYC 7542** (Zen 2, 2019) | | | Monthly price | **$13.99** | $24.00 | | ### What the results tell us **Raff is roughly 1.8x faster per core**, on the same shared-CPU basis, at the same shape, in the same region — and for 42% less money. **The processor line explains why, and it corroborates Akamai's own label.** The benchmarked Linode host runs an **AMD EPYC 7542**, a Zen 2 part launched in 2019. That is consistent with Akamai marking the Shared CPU line "Legacy Hardware": the plans are priced against current-generation shared vCPU elsewhere but run on older silicon. It is also a reason to treat the CPU gap as a hardware-generation gap rather than a permanent platform difference — Akamai could refresh the line. **Linode wins two axes, and both are real.** Sequential 1M write measured 2,353 MB/s against Raff's 1,257, and download to New York 8,049 Mbps against 3,635. The download figure reflects capability rather than measurement noise: Linode publishes a 4,000 Mbps maximum network speed on this plan against Raff's 3 Gbps port. If your workload pulls large volumes inbound or writes large sequential files, Linode's configuration is the stronger one. **Random I/O and sequential read favour Raff** — 1.51x on the 4K mixed job, which is the pattern most databases actually run. Read it as a trade: Raff for CPU-bound work and small-block I/O at lower cost, Linode for sequential writes and inbound bandwidth. ## Linode vs Raff: features and reliability ### Compute Linode scales to 20 vCPU and 96 GB on Shared CPU and well beyond on Dedicated, against Raff's ceiling of 16 vCPU and 32 GB. Below that ceiling Raff resizes on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking and bandwidth Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. Linode includes 1–20 TB of pooled transfer with $0.005/GB overage, private networking, cloud firewalls and NodeBalancers — and sits on Akamai's edge network, which is a genuine advantage for globally distributed delivery. ### Storage and object storage Raff separates storage into VM disk, block volumes at $0.08/GiB-month, and S3-compatible object storage at $7/month for 100 GB with 1 TB of egress. Linode object storage is **$0.02/GB-month with the first 1 TB of egress free** and $0.005/GB after. On object storage Linode is substantially cheaper — roughly $0.02/GB against Raff's effective $0.07/GB at the entry tier. If your workload is storage-heavy rather than compute-heavy, that difference can outweigh the VM saving. ### Managed databases Raff runs PostgreSQL, MySQL, Valkey, ClickHouse and Kafka **from $7.99/month**. Linode runs managed MySQL and PostgreSQL **from $16/month** for a single shared 1 GB node. Raff is roughly 50% cheaper at entry and covers five engines against two. ### Kubernetes Both offer managed Kubernetes. Raff provides a free control plane with workers from $9.99/month and an HA add-on at $30. Linode's LKE HA control plane is **$60 per cluster per month**. For a production cluster needing high availability, Raff's HA option is half the price. ### Support and ecosystem Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines. Linode's advantage is the ecosystem around it: a documentation and tutorial library built over two decades, an active community, and since the Akamai acquisition, integration with one of the largest edge and security networks in the world. Raff has none of that reach, and no comparison should pretend otherwise. ## When you should choose Linode over Raff - **Object-storage-heavy workloads** — $0.02/GB-month with 1 TB of free egress, against Raff's $7 for 100 GB - **Global delivery** — Akamai's edge network and a regional footprint spanning North America, Europe and Asia-Pacific against Raff's single us-east region - **Very large instances** — up to 20 vCPU and 96 GB on Shared CPU and further on Dedicated, against Raff's 16 vCPU / 32 GB ceiling - **Inbound-heavy and sequential-write workloads** — measured 2.21x higher download to New York and 1.87x higher 1M sequential write, on a 4,000 Mbps port - **Large monthly transfer within allowance** — 4 TB to 20 TB included by plan, with a low $0.005/GB overage - **Teams that rely on documentation and community** — two decades of Linode guides and an active forum ## When you should choose Raff over Linode - **Lower cost on equivalent VMs** — 35% to 42% below Shared CPU and 44% to 54% below Dedicated G8, at identical disk on four matched shapes ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **Current hardware on the shared line** — Akamai labels its Shared CPU plans "Legacy Hardware", and the benchmarked host runs a 2019-era EPYC 7542; Raff measured 1.82x faster single-core at the same shape - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month against $16 for two engines ([VPS for databases](/learn/guides/vps-for-databases)) - **Highly available Kubernetes** — $30 for the HA add-on against $60 per cluster per month - **Egress-heavy applications** — unmetered transfer on a 3 Gbps port, with no allowance to track - **Backups without an add-on** — Daily and Weekly schedules on a free storage pool with 1 to 365 day retention ## Migrating from Linode to Raff 1. **Match the line, not the price** — Linode Shared CPU maps to Raff General Purpose, Dedicated G8 to Raff CPU-Optimized. Mapping by monthly cost will land you in the wrong class. 2. **Check the ceiling** — Raff stops at 16 vCPU and 32 GB. Larger Linode instances have no equivalent. 3. **Price object storage separately** — Linode is cheaper per GB. If you hold significant object data, consider leaving it where it is rather than assuming the whole account should move. 4. **Check what the edge network is doing for you** — if Akamai's CDN or security services are in your delivery path, moving compute does not move those, and you may still need them. 5. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then assets to object storage. Keep the Linode instance running throughout. 6. **Cut over and delete, don't power off** — lower DNS TTL beforehand, switch, then delete the Linode. A powered-off instance still bills. ## About Linode Linode is a cloud computing provider founded in 2003 and headquartered in Philadelphia, acquired by Akamai Technologies in 2022 and now operating as Akamai Cloud. It offers Shared CPU and Dedicated CPU compute, managed databases, Kubernetes, object storage and NodeBalancers from regions across North America, Europe and Asia-Pacific, integrated with Akamai's global edge platform. See [Akamai Cloud pricing](https://www.akamai.com/cloud/pricing) for current rates. ## Conclusion: Linode or Raff? The comparison resolves across four axes: - **VM price** — Raff wins, 35% to 42% below Shared CPU and 44% to 54% below Dedicated G8, at identical disk on four matched shapes - **Object storage** — Linode wins, $0.02/GB-month with 1 TB free egress against Raff's $7 for 100 GB - **Reach** — Linode wins, with Akamai's edge network and regions across three continents against Raff's single us-east - **Managed services** — Raff wins, five database engines from $7.99/month against two from $16, and HA Kubernetes at $30 against $60 If you need global reach, cheap object storage at scale, instances above 16 vCPU, or Akamai's edge and security services, choose Linode. If your users are in North America and your bill is dominated by VMs and managed databases, choose Raff — the same workload costs 35% to 54% less. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.90% monthly uptime SLA in writing. --- ### Hetzner Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-hetzner Description: Considering Hetzner? Raff is $13.99/mo for 2 vCPU, 4 GB and 80 GB NVMe against CPX22 at €19.99, about $23.17. Hetzner built its reputation on being the cheapest credible cloud in Europe, and for years it was. That has changed. After the current pricing round, Raff Technologies is cheaper than Hetzner Cloud at every matched shared-vCPU shape — including five where the cores, memory and disk are identical. Hetzner Regular Performance CPX22 is €19.99/month for 2 vCPU, 4 GB and 80 GB; the identical Raff plan is $13.99. ## Hetzner VPS and Raff at a glance **Hetzner Cloud** sells three tiers, and the names are misleading if you read them quickly: - **Cost-Optimized** (CX) — shared, and currently marked **"Currently not available"** on Hetzner's own site - **Regular Performance** (CPX) — shared vCPU on AMD, from €11.99/month - **General Purpose** (CCX) — **dedicated** vCPU, from €43.49/month That third name is the trap. **Hetzner's "General Purpose" is its dedicated line**, while Raff's General Purpose is shared. Matching the two by name would compare Raff's shared vCPU against Hetzner's dedicated vCPU and get the answer badly wrong. The like-for-like pairing is Raff General Purpose against **Hetzner Regular Performance**, and Raff CPU-Optimized against **Hetzner General Purpose**. Hetzner runs from eu-central (Falkenstein, Nuremberg, Helsinki), us-east (Ashburn), us-west (Hillsboro) and ap-southeast (Singapore). Prices are quoted excluding VAT, so a US buyer pays the listed figure. Hetzner Cloud Backups cost **20% of the server's monthly price** and provide seven backup slots. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.90% monthly uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month, scaling to 16 vCPU and 32 GB. Every plan includes a 3 Gbps port with unmetered transfer, automated Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Raff's catalog covers managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, S3-compatible object storage at $7/month for 100 GB with 1 TB of egress, managed Kubernetes with a free control plane and workers from $9.99/month, Functions with a free monthly tier, block volumes at $0.08/GiB-month, and Raff Apps from $3/month. ## Hetzner VPS pricing vs Raff pricing Raff General Purpose against Hetzner Regular Performance — both shared vCPU on AMD. | Shape | Raff General Purpose | Hetzner Regular Performance | |---|---|---| | 1 vCPU / 2 GB | **$6.99** — 50 GB NVMe | CPX12 — €11.99 ≈ $13.90, 40 GB | | 2 vCPU / 4 GB / 80 GB | **$13.99** | CPX22 — €19.99 ≈ **$23.17** | | 4 vCPU / 8 GB / 160 GB | **$30.99** | CPX32 — €35.99 ≈ **$41.72** | | 8 vCPU / 16 GB / 320 GB | **$59.99** | CPX42 — €69.99 ≈ **$81.14** | | 12 vCPU / 24 GB / 480 GB | **$90.99** | CPX52 — €100.99 ≈ **$117.08** | | 16 vCPU / 32 GB / 640 GB | **$129.99** | CPX62 — €130.49 ≈ **$151.28** | *Hetzner prices read 2026-08-20 from the Regular Performance page, excluding VAT, converted at €1 = $1.1593 (ECB, 2026-08-17). Hetzner lists us-east (Ashburn) and us-west (Hillsboro) among available locations; confirm regional pricing at checkout.* **Five of those rows are identical on cores, memory and disk** — 80 GB, 160 GB, 320 GB, 480 GB and 640 GB. Raff is **14% to 40% cheaper** across them, and at the entry shape gives 50 GB against 40 GB for half the price. This is the finding that matters on this page. Hetzner's reputation is built on being the cheapest option that still works properly, and against Raff that is no longer the case at any shape in the shared line. ### If you are on the old CPX line, change plans before changing providers Hetzner still lists a previous CPX generation, and it is now priced well above the current one for the same or worse hardware: | Legacy plan | Spec | Price | Current equivalent | |---|---|---|---| | CPX21 | 3 vCPU / 4 GB / 80 GB | €32.49 | CPX22 — €19.99 | | CPX31 | 4 vCPU / 8 GB / 160 GB | €62.99 | CPX32 — €35.99 | | CPX41 | 8 vCPU / 16 GB / **240 GB** | €120.99 | CPX42 — €69.99 with **320 GB** | | CPX51 | 16 vCPU / 32 GB / **360 GB** | €238.49 | CPX62 — €130.49 with **640 GB** | CPX51 costs €238.49 for 16 vCPU, 32 GB and 360 GB. CPX62 gives the same cores and memory with **640 GB for €130.49** — 45% less money for 78% more disk. If you are running on the older line, the first thing to do is not switch providers, it is switch plans. That advice costs Raff a sale and is still the right advice. ### Dedicated vCPU Hetzner's dedicated line, confusingly named General Purpose, starts at **€43.49/month** (about $50.42). Raff CPU-Optimized starts at **$9.99/month** for 1 vCPU, 1 GB and 25 GB, and runs $27.99 at 2 vCPU / 4 GB / 80 GB. The full Hetzner CCX ladder is not reproduced here because the per-plan figures were not verified in this session — compare the specific shape you need directly rather than relying on entry prices. ### Automated backups Hetzner Cloud Backups cost **20% of the server's monthly price** and provide seven backup slots. On a CPX42 at €69.99, that is roughly €14/month for backups alone. Raff includes a free backup and snapshot storage pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules you configure, retention from 1 to 365 days, and uncapped snapshots. Storage above the pool is $0.06/GB-month. ## Hetzner VPS performance vs Raff ### Methodology The available head-to-head data is from **May 2026** — older than 90 days and no longer a current performance claim. It compared a Raff 2 vCPU / 4 GB benchmark VM against a Hetzner CPX test VM. The iperf3 rows measured different endpoints (NYC against Amsterdam) and are not comparable at all. ### Historical results — May 2026 | Metric | Raff | Hetzner CPX | Result in that test | |---|---:|---:|---| | Geekbench 6 single-core | **2,266** | 1,847 | Raff higher | | Geekbench 6 multi-core | **4,057** | 2,321 | Raff higher | | fio 4K random-read IOPS | **97,468** | 80,153 | Raff higher | | fio 64K mixed aggregate | 2,927 MB/s | **3,249 MB/s** | Hetzner higher | | fio 1M sequential aggregate | 3,606 MB/s | **4,013 MB/s** | Hetzner higher | ### What the results tell us In that window Raff led CPU by roughly 1.23x single-core and 1.75x multi-core, and 4K random read by 1.22x. **Hetzner led both sequential disk measurements**, by 11% at 64K and 11% at 1M. Two reasons to treat this as context rather than a claim: the data is past the 90-day freshness window, and Hetzner has since revised its plan lineup, so the tested configuration may no longer exist under the same name. If performance is your deciding factor, benchmark the specific CPX\*2 plan you are considering against the matching Raff plan. ## Hetzner vs Raff: features and reliability ### Compute Hetzner Regular Performance runs from 1 to 16 shared vCPU and 2 to 32 GB on AMD, with the dedicated General Purpose line above it. Raff covers the same shared range and stops at 16 vCPU and 32 GB, with CPU-Optimized alongside. Raff resizes on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint for CPU, RAM and disk. ### Networking Raff includes a 3 Gbps port with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. Hetzner includes private networks, stateful firewalls at no extra cost, load balancers and a generous traffic allowance per server, with charges beyond it — confirm the current allowance and overage rate for your region, as these have changed alongside the plan revision. ### Storage Hetzner attaches local NVMe to the host and sells Volumes separately. Raff separates storage into VM disk, block volumes at $0.08/GiB-month that resize independently, and S3-compatible object storage at $7/month for 100 GB with 1 TB of egress. On the matched shapes above, Raff includes the same disk as Hetzner at every tier except the entry plan, where it includes more. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines. Hetzner's support runs on tickets and is well regarded for competence rather than speed. ### Platform Hetzner sells infrastructure: servers, storage boxes, load balancers, networks, and dedicated hardware — with a strong reputation for reliability and an active community. It does not sell managed databases, serverless functions or a PaaS layer. Raff adds those on the same account: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month, Functions with a free tier of 100,000 GB-seconds and 10,000 vCPU-seconds and runs up to 24 hours, Raff Apps from $3/month, and managed Kubernetes with a free control plane — connected over private networking, on one API and one bill. The honest counter-argument is that a 32 GB Hetzner box will run Postgres, Redis and your application together perfectly well. It will. What you are then operating is backups, restore testing, failover, point-in-time recovery and version upgrades — and Hetzner's backup add-on costs 20% of the server price on top. ## When you should choose Hetzner over Raff - **Users in Europe or Asia** — Falkenstein, Nuremberg, Helsinki and Singapore against Raff's single us-east region - **Sequential-disk-heavy workloads** — Hetzner measured 11% higher on both 64K mixed and 1M sequential aggregate in May 2026 testing - **Dedicated hardware and storage boxes** — Hetzner's dedicated server range and Storage Box products have no Raff equivalent - **Established community and tooling** — a large, active user base with extensive third-party guides and automation recipes - **Hourly billing with a monthly cap** — pay only for hours used if a server is deleted mid-month ## When you should choose Raff over Hetzner - **Lower cost on identical hardware** — 14% to 40% cheaper at five shapes with identical cores, memory and disk ([VPS for application hosting](/learn/guides/vps-for-application-hosting)) - **Backups without a 20% surcharge** — Daily and Weekly schedules on a free storage pool against 20% of the server's monthly price - **Users in North America** — us-east against a European-first footprint, with unmetered transfer on a 3 Gbps port - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, which Hetzner does not offer ([VPS for databases](/learn/guides/vps-for-databases)) - **Long-running serverless jobs** — Raff Functions run up to 24 hours; Hetzner has no serverless product - **24/7 human support** — live chat to the same engineers at any account size, first response typically under 10 minutes ## Migrating from Hetzner to Raff 1. **Check which CPX generation you are on first** — if you are on CPX21, CPX31, CPX41 or CPX51, moving to the current CPX\*2 line may save more than switching providers. Do that comparison before this one. 2. **Match the tier, not the name** — Hetzner "General Purpose" is dedicated vCPU and maps to Raff CPU-Optimized. Hetzner "Regular Performance" is shared and maps to Raff General Purpose. 3. **Check your region requirement** — Raff serves us-east only. If your users are in Europe, this migration adds latency that the price saving will not offset. 4. **Account for the backup line** — Hetzner backups cost 20% of the server price; on Raff that line goes away, which widens the real saving beyond the plan-price difference. 5. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then assets to object storage. Keep the Hetzner server running throughout. 6. **Cut over and delete, don't power off** — lower DNS TTL beforehand, switch, then delete the server. Hetzner bills until a server is deleted, not until it is stopped. ## About Hetzner Hetzner Online GmbH is a German hosting provider founded in 1997 and headquartered in Gunzenhausen, offering cloud servers, dedicated servers, storage boxes, load balancers and colocation from data centers in Germany, Finland, the United States and Singapore. It is known for low prices and a strong engineering reputation in the European developer community. See [Hetzner Cloud](https://www.hetzner.com/cloud/) for current plans and terms. ## Conclusion: Hetzner or Raff? The comparison resolves across four axes: - **Price** — Raff wins, 14% to 40% cheaper at five shapes with identical cores, memory and disk, plus no 20% backup surcharge - **Reach** — Hetzner wins, with European and Asian regions against Raff's single us-east - **Sequential disk** — Hetzner led by about 11% in May 2026 testing, though that data is now stale - **Managed services** — Raff wins, with managed databases, Functions and Kubernetes that Hetzner does not sell If your users are in Europe, you want dedicated hardware or storage boxes, or your workload is dominated by large sequential disk operations, choose Hetzner. If your users are in North America and you want the same hardware for less with managed databases beside it, choose Raff. And if you are on an older CPX plan, check the current line first — that saving is available without moving anywhere. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.90% monthly uptime SLA in writing. --- ### OVHcloud Alternative 2026: Pricing, Performance & Features URL: https://rafftechnologies.com/learn/compare/raff-vs-ovhcloud Description: Considering OVHcloud? Raff is $13.99/mo for 2 vCPU and 4 GB against d2-4 at $18.69, with a 3 Gbps port on every plan. OVHcloud is Europe's largest cloud provider, with its own data centers, its own network, and a VPS line priced lower than almost anything comparable. Raff Technologies is a US cloud provider selling VMs, managed databases, object storage, Functions and Apps on one account. On price this is not a close comparison: OVHcloud VPS-1 gives 2 vCores, 4 GB and 40 GB NVMe for $4.54/month, where the nearest Raff plan is $13.99. What differs is disk, port speed, how long a backup is kept, and what runs beside the server. ## OVHcloud VPS and Raff at a glance OVHcloud is Europe's largest cloud provider, running its own data centers and network since 1999. Raff Technologies is a US cloud provider selling VMs, managed databases, object storage, Functions and Apps from a single us-east region. One thing has to be settled before any price is compared: **OVHcloud sells two different compute products.** | | What it is | Starts at | |---|---|---| | **VPS 2027** | Budget self-managed servers. Monthly billing, four fixed sizes, one rolling 24-hour backup. | **$4.54/mo** | | **Public Cloud** | The cloud platform. Hourly billing, API and CLI, private networking, snapshots, managed databases and Kubernetes alongside. | **$9.41/mo** | **A Raff VM is the second kind of product.** It bills hourly, exposes an API and CLI, resizes on demand, sits on private networking, and has managed databases on the same account. So this page compares **Raff against Public Cloud**, and shows the VPS line separately — because it is genuinely cheaper, and some readers should buy it. **Raff Technologies** runs 15,000+ VMs for 3,000+ customers from us-east, with a 99.90% monthly uptime SLA backed by service credits, rated 4.5/5 on Trustpilot and 4.6/5 on G2. VMs run AMD EPYC with DDR5 ECC memory and NVMe storage, in two lines: General Purpose with shared vCPU from $4.99/month, and CPU-Optimized with dedicated vCPU from $9.99/month. Every plan includes a **3 Gbps port** with unmetered transfer regardless of size, Daily or Weekly backup schedules, uncapped snapshots, firewall controls, private networking and full root access. Beyond the VM, Raff sells managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month, object storage at $7/month for 100 GB, managed Kubernetes with a free control plane, Functions that run up to 24 hours, IAM, and Raff Apps from $3/month. ## OVHcloud VPS pricing vs Raff pricing Both providers sell shared and dedicated vCPU, so there are two comparisons. OVHcloud's shared range is **D2 Discovery**; its dedicated ranges are **B3**, **C3** and **R3**. ### Shared vCPU | Shape | Raff General Purpose | OVHcloud D2 | |---|---|---| | 1 vCPU / 2 GB | **$6.99** — 50 GB | d2-2 — $9.41, 25 GB | | 2 vCPU / 4 GB | **$13.99** — 80 GB | d2-4 — $18.69, 50 GB | | 4 vCPU / 8 GB | **$30.99** — 160 GB | d2-8 — $33.65, 50 GB | Raff is **8% to 26% cheaper**, with more disk on every row. ### Dedicated vCPU | Shape | Raff CPU-Optimized | OVHcloud C3 | |---|---|---| | 2 vCPU / 4 GB | **$27.99** — 80 GB | c3-4 — $39.42, 50 GB | | 4 vCPU / 8 GB | **$49.99** — 120 GB | c3-8 — $78.69, 100 GB | | 8 vCPU / 16 GB | **$89.99** — 180 GB | c3-16 — $157.22, 200 GB | Raff is **29% to 43% cheaper**. *OVHcloud Public Cloud US prices read from us.ovhcloud.com on 2026-08-20. Monthly figures are the published hourly rate at 730 hours.* ### Port speed Raff runs a **3 Gbps port on every plan**, including the $4.99 entry. OVHcloud scales bandwidth with instance size: | OVHcloud instance | Its port | Raff advantage | |---|---|---| | d2-2 | 100 Mbps | **30x** | | d2-4, c3-4 | 250 Mbps | **12x** | | d2-8, c3-8 | 500 Mbps | **6x** | | c3-16 | 1 Gbps | **3x** | On the small instances most projects start with, that is a thirty-fold difference in ceiling. ### If you only care about price, buy the VPS **OVHcloud VPS-1 is $4.54/month** — cheaper than any Raff plan, and cheaper than OVHcloud's own Public Cloud. If the monthly figure decides your purchase, buy it. This page will not argue otherwise. **Why is it so much cheaper than the same company's Public Cloud?** Not because the hardware is worse — OVHcloud does not say what the hardware is. It is cheaper because it is a smaller product: - **No hourly billing.** Monthly commitment only, where Public Cloud and Raff bill by the hour. - **One rolling 24-hour backup**, not a retention window. - **It sits outside the platform.** Managed databases, object storage and Kubernetes are Public Cloud products. A VPS does not get them beside it on the same private network. - **No published CPU specification.** OVHcloud states the vCore count but not the processor, the generation, or whether cores are shared or dedicated. Every other provider in this comparison publishes at least the CPU family. That last one is worth pausing on. It is not evidence of bad hardware — it is an absence of evidence, and you can verify the absence yourself on their pricing page. If knowing what you are running on matters, that is a reason to check before buying rather than a reason not to buy. At $4.54 the VPS is a fair trade for a small self-managed server. It is simply not the same purchase as a cloud instance. ### Backups OVHcloud VPS includes a **daily backup of the previous 24 hours** — one day of history. A problem introduced on Monday and found on Wednesday is already past it. Premium backup starts at $1.40/month. Raff includes a free backup and snapshot pool — 50 GB per account plus 10–15% of each VM's disk — with Daily and Weekly schedules, **1 to 365 day retention**, and uncapped snapshots. Above the pool it is $0.06/GB-month. ## OVHcloud VPS performance vs Raff **Raff has no current, matched benchmark against the VPS 2027 range, and this page will not estimate one.** The available data is from May 2026 and compared a Raff 2 vCPU / 4 GB instance against an OVHcloud `b3-16` Public Cloud instance with 4 vCores and 16 GB — a different product line, a different shape, and a single pass. That is not a basis for a claim about VPS 2027. What can be said from published specifications: **Bandwidth ceiling is the measurable difference.** Raff publishes 3 Gbps on every plan; OVHcloud publishes 100 Mbps to 4 Gbps depending on instance size, and only its largest instances exceed Raff's port. On the shapes most projects actually buy, the gap runs from 3x to 30x, and it does not depend on a benchmark to verify. **Storage architecture.** OVHcloud attaches NVMe to the host. Raff runs distributed block storage across an NVMe cluster, so a write crosses the network and is replicated before it is acknowledged — slower for small synchronous writes, and the reason data is replicated rather than pinned to one machine, snapshots are taken at the storage layer, and a VM can change plan without being rebuilt. **Reliability commitment.** Raff commits to 99.90% monthly uptime with service credits, documented in the service level agreement, running 15,000+ VMs from us-east. If performance is your deciding factor, run your workload on both. OVHcloud bills monthly with no term, so the test is inexpensive. ## OVHcloud vs Raff: features and reliability ### Compute OVHcloud VPS spans 2 to 8 vCores and 4 to 24 GB. Raff spans 1 to 16 vCPU and 1 to 32 GB across two lines, with CPU-Optimized offering dedicated vCPU from $9.99/month — OVHcloud's VPS line has no dedicated-vCPU equivalent, though its Public Cloud does. Raff resizes on demand: stop the VM, switch plan, restart, with the difference settled to the account balance and a `resize` API endpoint. ### Networking Raff includes a 3 Gbps port at every tier with unmetered transfer, private networking, VPC, firewall controls and site-to-site VPN gateways. OVHcloud includes unlimited traffic with a tier-dependent ceiling, anti-DDoS protection on every plan, and a global network that is genuinely one of the company's strongest assets. ### Storage Raff includes about twice the disk at each matched tier, and separates storage into VM disk, block volumes at $0.08/GiB-month, and S3-compatible object storage at $7/month for 100 GB with 1 TB of egress. OVHcloud sells object storage and block storage through its Public Cloud rather than the VPS product. ### Support Raff provides 24/7 human support through live chat, with a first response typically under 10 minutes. No bots triaging you first, and no support tier to buy: a single $4.99 VM reaches the same engineers as a hundred production machines. OVHcloud's VPS support is documented as email-based assistance alongside a substantial guide library. For a self-managed VPS at $4.54/month that is a reasonable trade, and it is worth pricing the difference honestly rather than assuming one model suits everyone. ### Platform This is where the comparison turns, if it turns at all. Raff sells the layers around the VM on the same account: managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month reachable over private networking, S3-compatible object storage, Functions with a free tier that run **up to 24 hours**, managed Kubernetes with a free control plane, IAM with roles and audit logs, and Raff Apps from $3/month. Private traffic between them is unmetered and free. OVHcloud has equivalents — managed databases, object storage, managed Kubernetes — but they live in Public Cloud, a separate product with its own pricing model, rather than beside the VPS you just bought. Assembling a VPS plus Public Cloud services is a different exercise from adding a database to an existing account. The honest counter-argument remains strong here: a VPS-4 with 24 GB of RAM at $23.37 will run Postgres, Redis and your application together comfortably. It will. What you are then operating is backups with more than 24 hours of history, restore testing, failover and version upgrades — and at that price, many teams will decide that is a fair trade. ## When you should choose OVHcloud over Raff - **The VPS line on price above all else** — VPS-1 at $4.54/month undercuts every Raff plan and OVHcloud's own Public Cloud, if a simpler product suits you - **Users outside North America** — European and global regions plus Local Zones in more than 15 cities, against Raff's single us-east - **Memory-heavy single servers** — 24 GB at $23.37 has no Raff equivalent near that price - **Dedicated servers and bare metal** — a deep dedicated range that Raff does not offer at all - **Anti-DDoS at every tier** — included on all VPS plans as standard ## When you should choose Raff over OVHcloud - **Backups with real retention** — Daily and Weekly schedules with 1 to 365 day retention, against a single rolling 24-hour backup ([VPS backup strategy](/learn/guides/vps-backup-strategy)) - **Egress-heavy applications** — a 3 Gbps port on every plan against 100 Mbps on d2-2 and 250 Mbps on d2-4, a twelve to thirty-fold difference in ceiling - **More included disk** — roughly twice the storage at each matched tier - **Database-backed products** — managed PostgreSQL, MySQL, Valkey, ClickHouse and Kafka from $7.99/month on the same account over private networking ([VPS for databases](/learn/guides/vps-for-databases)) - **Long-running serverless jobs** — Raff Functions run up to 24 hours; nothing in the OVHcloud VPS product is equivalent - **24/7 live support** — chat to the same engineers at any account size, first response typically under 10 minutes, against email-based VPS support ## Migrating from OVHcloud to Raff 1. **Be clear which OVHcloud product you are on** — if you run a VPS 2027 plan, Raff costs more and this migration is about backup retention, port ceiling and managed services, not price. If you run Public Cloud instances, Raff is cheaper at every class. 2. **Check which VPS generation you are on** — OVHcloud notes that VPS 2027 configurations have shifted, so an older plan may not map to the model with the same name. 3. **Check your region requirement** — Raff serves us-east only. European or Asian users will see added latency. 4. **Right-size on utilisation** — OVHcloud ships more cores at the upper tiers; Raff ships more disk. Measure what the workload uses rather than matching specifications. 5. **Move data in order** — files with rsync or SCP, then database dumps into managed Postgres or MySQL, then assets to object storage. Keep the OVHcloud VPS running throughout. 6. **Cut over and cancel properly** — lower DNS TTL beforehand, switch, then cancel the VPS in the OVHcloud control panel rather than leaving it idle. ## About OVHcloud OVHcloud is a French cloud provider founded in 1999 and headquartered in Roubaix, operating its own data centers and network across Europe, North America and Asia-Pacific. It offers VPS, dedicated servers, Public Cloud instances, managed Kubernetes, object storage and Local Zones, and is one of the largest cloud providers in Europe. See [OVHcloud VPS](https://us.ovhcloud.com/vps/) for current plans and terms. ## Conclusion: OVHcloud or Raff? The honest split is not price against price — it is **what stage the workload is at.** **For a trial, a prototype, a staging box or a small static site, the OVHcloud VPS is enough.** $4.54/month, unlimited traffic, a daily backup, and a server that works. Nothing on this page beats that for something you are still deciding about, and you should not pay production prices for a machine you might delete next week. **For production, the deciding factors stop being the monthly figure.** They become: how far back your backups go, whether the port holds up when traffic arrives, whether you can attach a managed database without assembling a second product, and how fast someone answers at 3 AM. That is the comparison Raff is priced for: - **Price at production class** — against OVHcloud Public Cloud, the equivalent product, Raff is **8% to 26% cheaper on shared vCPU and 29% to 43% cheaper on dedicated**, with more disk on most rows - **Backup history** — 1 to 365 days of retention with Daily and Weekly schedules, against a single rolling 24-hour backup - **Port ceiling** — a 3 Gbps port on every Raff plan, against 100 Mbps to 1 Gbps on the Public Cloud instances most projects buy - **Room to grow** — managed databases from $7.99, object storage, Functions and Kubernetes on the same account and private network, rather than in a separate product OVHcloud keeps the advantages that come with its scale: regions across three continents, Local Zones in more than 15 cities, a deep dedicated server range, and the cheapest entry price here. ### The part that decides it: what happens when it works Start on the OVHcloud VPS if the project might not survive the month. At $4.54 it costs almost nothing to find out, and that is a genuinely good reason. But be clear what you are choosing, because **the VPS line does not grow into Public Cloud — it is a separate product.** When the project does work, and backups need to reach further back than yesterday, or traffic outgrows the port, or you need a managed database on a private network, you are not upgrading. You are migrating: a different product or a different provider, a data move, a DNS cutover, and a maintenance window you have to explain to someone. On Raff the same account runs from $4.99 to 16 vCPU and 32 GB, and the managed database, object storage, Functions and Kubernetes are already there on the same private network. Growing means selecting a larger plan and restarting, not planning a migration. So the question is not which server is cheaper this month. It is whether you want to spend a weekend migrating in six months — and if the answer is no, starting where you intend to end up is worth more than the difference between $4.54 and $13.99. Raff runs 15,000+ VMs for 3,000+ customers and is rated 4.5/5 on Trustpilot, with a 99.90% monthly uptime SLA in writing. --- ### Confluent Alternatives 2026: Managed Kafka Options for Small Teams URL: https://rafftechnologies.com/learn/compare/confluent-alternatives-managed-kafka Description: Compare Confluent alternatives including Raff Managed Kafka, Amazon MSK, Aiven and self-managed Kafka across pricing, operations, regions, migration, and production fit. Confluent is one of the most complete managed data-streaming platforms around Apache Kafka, but it is not the right operating model for every team. Some buyers need Confluent's connectors, governance, Flink, ksqlDB, Tableflow, Cluster Linking, and global cloud footprint. Others mainly need **reliable managed Apache Kafka without adopting a broader enterprise streaming platform or a highly granular consumption bill**. For small and mid-sized teams, the strongest Confluent alternatives fall into four different categories: **Raff Managed Kafka** for a simpler fixed-plan Apache Kafka service in `us-east`, **Amazon MSK** for AWS-native Kafka, **Aiven for Apache Kafka** for multi-cloud managed open-source infrastructure, and **self-managed Apache Kafka** when broker-level control is a hard requirement. The right alternative depends less on a generic feature count and more on five questions: **Do you need Confluent-specific services? Which cloud or region must the cluster run in? Do you want fixed or usage-based billing? Who should own broker operations? How difficult will migration be from the parts of Confluent you actually use?** ## Confluent alternatives at a glance | Option | Kafka model | Billing model | Best fit | Main trade-off | |---|---|---|---|---| | Confluent Cloud | Managed Kafka plus broader streaming platform | Consumption-based across capacity, ingress, egress, storage and optional services | Teams that want a broad enterprise streaming ecosystem | More platform surface and more billing dimensions than a Kafka-only service | | Raff Managed Kafka | Managed Apache Kafka 4.3 with KRaft | Fixed plan pricing from $15.99/month | Small and mid-sized teams that want straightforward managed Kafka in `us-east` | One public region and a much smaller streaming ecosystem than Confluent | | Amazon MSK | AWS-managed Apache Kafka | Provisioned or serverless usage-based pricing | Teams deeply standardized on AWS | AWS pricing and architecture can involve several usage dimensions | | Aiven for Apache Kafka | Managed Apache Kafka across multiple clouds | Free/Developer entry tiers plus production plans with plan- and usage-dependent pricing | Teams wanting multi-cloud Kafka and a broad managed open-source data platform | Production pricing and service choices are broader than a simple fixed Kafka plan | | Self-managed Kafka | Apache Kafka operated by your team | Infrastructure + engineering + operations | Teams with hard broker-level requirements and mature Kafka operations | Your team owns upgrades, balancing, monitoring, incidents and recovery | **Short answer:** choose Confluent when its broader streaming platform is part of the requirement. Choose Raff when Kafka itself is the requirement and `us-east`, a smaller operating surface, and flat entry pricing fit. Choose Amazon MSK when AWS integration is more important than provider independence. Choose Aiven when multi-cloud placement and a larger open-source service catalog matter. Self-host only when the additional control has a documented reason. For the operating-model decision before vendor selection, read [Managed Kafka vs Self-Hosted Kafka](/learn/guides/managed-kafka-vs-self-hosted-kafka). ## Why teams look for Confluent alternatives Confluent's breadth is a strength, not a flaw. The reason to evaluate alternatives is that not every Kafka workload needs that breadth. Common switching or evaluation triggers include: - the application mainly needs Apache Kafka brokers rather than a complete streaming-data platform; - the team wants a simpler monthly cost model; - an AWS-native architecture makes Amazon MSK operationally easier; - a multi-cloud requirement favors a provider such as Aiven; - a small team wants fewer platform-specific services to learn and operate; - procurement wants a lower-cost entry point for an early production workload; - a workload needs broker-level control that a managed service does not expose; - the team wants to reduce dependence on Confluent-specific services before future migration becomes harder. A lower entry price is not enough reason to migrate. If your application relies heavily on Confluent connectors, Stream Governance, Flink SQL, ksqlDB, Tableflow, Cluster Linking, or other platform-specific workflows, replacing the Kafka cluster can be the easy part while replacing the surrounding platform becomes the real project. That distinction matters because **Kafka protocol portability and platform portability are not the same thing**. ## Confluent Cloud is strongest when Kafka is only one part of the streaming platform Confluent Cloud goes far beyond managed brokers. Its current cloud platform combines Kafka with managed streaming and data-integration capabilities such as connectors, governance, stream processing, cross-cluster tooling, and analytical/table integrations. Its billing model reflects that broader platform. Confluent documentation currently lists billable dimensions including: - Kafka cluster capacity through eCKUs or CKUs depending on cluster type; - data ingress; - data egress; - storage; - Cluster Linking; - connectors; - ksqlDB; - Flink SQL; - Tableflow; - audit logs; - support. For Basic, Standard, Enterprise, and Freight clusters, current Confluent documentation uses elastic capacity units, or **eCKUs**. Dedicated clusters use **CKUs**. Storage and transfer are separate billing dimensions. That model is useful when a company wants elastic capacity and many managed streaming services in one platform. It can be less attractive when a small team wants to answer a simpler question: “What will one Kafka environment cost us each month?” Choose Confluent when several of these are true: - your team actively uses or expects to use its broader streaming ecosystem; - global cloud placement is required; - enterprise governance and integration workflows are important; - usage-based elastic capacity fits your financial model; - migrating away from Confluent-specific services would create more work than the platform cost justifies. The goal of an alternatives page should not be to make Confluent look oversized for everyone. For many data-platform teams, that breadth is exactly why they buy it. ## Raff Managed Kafka: best when you want a smaller managed Kafka surface [Raff Managed Kafka](/products/managed-databases/kafka) is the most direct alternative in this list for a team that wants managed **Apache Kafka itself** without building an enterprise-wide streaming platform around the purchase. As of August 24, 2026, Raff's managed Kafka path uses **Apache Kafka 4.3 with KRaft** and supports a progression from a single-broker development deployment to a three-broker high-availability configuration. The published entry plan starts at **$15.99/month for 1 vCPU, 1 GB RAM, and 25 GB storage**. Raff uses fixed plan pricing rather than metering Kafka capacity, ingress, egress, and storage as separate Confluent-style billing dimensions. That makes it easier for a small team to establish a monthly baseline before traffic grows. Raff is a stronger fit when: - Kafka 4.3/KRaft meets the application requirement; - one public `us-east` region fits the workload; - the team wants broker operations managed without adopting a much larger streaming platform; - a fixed plan price is easier to budget than several usage dimensions; - direct support and migration assistance are useful to a smaller engineering team; - Kafka supports the product but is not itself the product team's core specialty. Raff is **not** the right substitute when the requirement is effectively “give us Confluent's entire platform at a lower price.” Raff does not match Confluent's global footprint or the breadth of its streaming ecosystem. A useful Raff decision rule is: **if your application needs Kafka semantics but your team does not gain product value from operating or extending a large Kafka platform, keep the service boundary small.** For topic, partition, consumer and retention decisions that remain your responsibility on any provider, use [Kafka Architecture for Small Teams](/learn/guides/kafka-architecture-small-teams). ## Amazon MSK: best when Kafka already belongs inside AWS Amazon Managed Streaming for Apache Kafka, or Amazon MSK, is the natural Confluent alternative for teams whose infrastructure, networking, security, observability, and procurement are already centered on AWS. AWS currently offers both **MSK Provisioned** and **MSK Serverless**. The serverless model charges across several usage dimensions, including: - cluster-hours; - partition-hours; - data written by producers; - data read by consumers; - storage; - additional standard AWS transfer charges in some network paths. AWS's own current pricing example for an MSK Serverless cluster in US East (Ohio) uses five topics with 20 partitions each, 100 GB/day written, 200 GB/day read, and 100 GB average storage. AWS calculates that specific 31-day example at **$1,299.60**. That is a workload example, **not a starting price**, but it illustrates why MSK buyers should model partitions, throughput and data movement before assuming the final bill from the word “serverless.” Amazon MSK is strongest when: - VPC, IAM, CloudWatch and other AWS integrations are already part of the architecture; - the team wants Apache Kafka without leaving AWS operational boundaries; - AWS regions satisfy placement and compliance requirements; - infrastructure teams already understand AWS billing and networking; - procurement prefers consolidating cloud spend into AWS. It is less compelling when the main goal is escaping hyperscaler complexity or when the team wants a small fixed monthly Kafka plan. ## Aiven for Apache Kafka: best for multi-cloud and managed open-source breadth Aiven is another strong managed Apache Kafka alternative, especially for teams that want to keep a broader set of open-source data services under one managed provider while retaining cloud and region choice. Aiven's current public Kafka pricing includes: - **Free: $0/month**, with limited throughput, topics and retention; - **Developer: starting at $35/month** for the current entry configuration; - production-oriented Professional options whose exact cost depends on plan, cloud, region, capacity and the current service model. The current Developer tier is designed for development, testing, and smaller workloads. Aiven documentation lists **1 MB/s ingress, 2 MB/s egress, up to 20 topics**, configurable one-to-three-day retention, and KRaft for that tier. Aiven also offers broader production capabilities and deployment across major cloud providers. Aiven is especially attractive when: - the team wants Kafka plus managed PostgreSQL, MySQL, Valkey, OpenSearch, ClickHouse or other open-source data services; - AWS, Azure or Google Cloud placement flexibility matters; - the organization wants a managed open-source platform rather than one cloud vendor's native stack; - region selection is more important than minimizing the provider surface; - the team's Kafka needs are likely to outgrow a small single-region service. Compared with Raff, Aiven offers much broader geographic and platform choice. Raff offers a smaller `us-east` footprint and simpler fixed entry plan. Those are different product strategies rather than a universal winner and loser. ## Self-managed Kafka: best only when control is the requirement Running Apache Kafka yourself remains a valid Confluent alternative when managed-service constraints block a real requirement. Self-management can make sense when you need: - exact broker configuration; - custom networking or security architecture; - precise upgrade timing; - host-level debugging or observability; - unusual storage or topology design; - Kubernetes-native operation through tooling such as an operator; - direct control over the full Kafka lifecycle; - an existing platform team that already operates Kafka reliably. The cost model is broader than VM price: ```text broker compute + storage + network + monitoring + spare capacity + replication overhead + upgrades + engineering time + on-call coverage + incident response + recovery testing ``` If no named team owns those responsibilities, self-hosting has not eliminated the managed-service cost; it has moved the cost into engineering and operational risk. This is exactly the boundary covered in [Managed Kafka vs Self-Hosted Kafka](/learn/guides/managed-kafka-vs-self-hosted-kafka). ## Confluent pricing vs alternatives: compare billing models, not one headline number There is no responsible one-line statement that “Provider X is Y% cheaper than Confluent” for every Kafka workload. The services bill different things and include different platform capabilities. | Provider | Public pricing model | Useful entry/reference point | Cost variables to model | |---|---|---|---| | Confluent Cloud | Consumption-based | No single fixed comparable monthly cluster price | eCKU/CKU capacity, ingress, egress, storage, connectors and other platform services | | Raff Managed Kafka | Fixed plans | From $15.99/month for 1 vCPU / 1 GB / 25 GB | selected plan, storage/capacity growth, HA configuration | | Amazon MSK | Provisioned or serverless usage pricing | AWS publishes workload examples rather than one universal starting total | brokers or cluster-hours, partitions, data in/out, storage, network transfer | | Aiven for Kafka | Tier/plan dependent | Free $0; Developer from $35/month | tier, retention, cloud/region, capacity, network and production configuration | | Self-managed Kafka | Infrastructure + labor | No managed-service fee | brokers, disks, traffic, monitoring, replicas, labor, on-call and recovery | A useful cost exercise is to define the same workload first: ```text average and peak ingress + average and peak egress + partition count + retention + stored data + replication / HA requirement + region + connectors / schema / stream processing needs + support requirement ``` Then price each provider against that workload. A small cluster with modest traffic may strongly favor one pricing model. A high-throughput platform using managed connectors, governance and stream processing can favor another because buying those capabilities separately creates its own cost. **Price equivalent outcomes, not just Kafka brokers.** ## Migration from Confluent depends on how much Confluent-specific surface you use For an application using standard Kafka producers and consumers, the Kafka broker layer is often the most portable part of the architecture. Client configuration, authentication, networking, topics, offsets, retention, and data movement still need a migration plan, but the application protocol is based on Kafka. Migration becomes more involved when the application also depends on Confluent-specific or Confluent-managed services. Inventory these before choosing an alternative: - Schema Registry and schema compatibility workflows; - managed connectors; - ksqlDB; - Flink SQL; - Tableflow; - Cluster Linking; - governance and audit workflows; - cloud-specific private networking; - identity and access configuration; - metrics and alerting integrations. A practical migration sequence is: 1. **Inventory Kafka and platform dependencies.** Record topics, partitions, retention, ACLs, schemas, connectors, consumer groups, throughput and Confluent-specific services. 2. **Create the target Kafka environment.** Match Kafka/client compatibility, networking, authentication, capacity, retention and HA requirements. 3. **Test client compatibility.** Point non-production producers and consumers at the target and validate serialization, authentication, throughput and failure behavior. 4. **Plan data movement.** Select a supported replication, mirroring, export/import or dual-run method appropriate to the source and target. 5. **Rebuild non-Kafka dependencies.** Replace or migrate schema, connector, processing and governance features that do not move with broker data. 6. **Cut over consumers and producers deliberately.** Define authoritative clusters, offset handling, rollback and the point where new writes stop on the source. 7. **Validate business outcomes.** Confirm event freshness, consumer lag, downstream state and critical workflows before retiring Confluent resources. Do not assume that “Kafka-compatible” means every surrounding feature migrates automatically. For consumer recovery planning during a move, use [Kafka Consumer Groups: Lag, Rebalances & Recovery Planning](/learn/guides/kafka-consumer-groups-lag-rebalances). ## Which Confluent alternative should you choose? ### Choose Confluent Cloud when - you need a broad enterprise data-streaming platform rather than only Kafka; - managed connectors, governance, Flink/ksqlDB, Tableflow or cross-cluster tooling reduce engineering work; - global cloud and region choice is important; - usage-based elastic billing fits the organization's cost model; - replacing Confluent-specific services would create unnecessary migration risk. ### Choose Raff Managed Kafka when - Apache Kafka 4.3/KRaft fits the workload; - `us-east` satisfies placement needs; - a published fixed entry plan from $15.99/month is easier to forecast; - the team primarily needs brokers, monitoring and managed operations rather than a broad streaming suite; - direct support and a smaller platform surface are preferable for a small engineering team. ### Choose Amazon MSK when - the organization is already deeply AWS-native; - VPC/IAM/CloudWatch and AWS procurement integration reduce operational work; - AWS region breadth matters; - the team is comfortable modeling serverless or provisioned AWS costs. ### Choose Aiven when - multi-cloud or broad region placement is a priority; - Kafka is part of a larger managed open-source data stack; - Aiven's free/developer path is useful for evaluation; - the team wants a provider-independent open-source platform with broader geographic coverage than Raff. ### Choose self-managed Kafka when - a documented broker-level requirement blocks managed services; - the team already has Kafka automation, monitoring and on-call maturity; - the operational control is worth the lifecycle burden. ## Confluent alternative evaluation checklist Before switching providers, confirm: - [ ] Required Kafka version and client compatibility are supported. - [ ] Required region and network architecture are available. - [ ] Peak ingress and egress fit the target service. - [ ] Partition count and connection requirements fit service limits. - [ ] Retention and storage growth are modeled. - [ ] HA and failure behavior are understood. - [ ] Schema Registry requirements are mapped. - [ ] Every connector is mapped to a target equivalent or replacement. - [ ] ksqlDB/Flink/Tableflow dependencies are identified. - [ ] Consumer groups and offsets have a migration plan. - [ ] Authentication and ACLs can be recreated. - [ ] Monitoring and alert ownership are defined. - [ ] Full monthly production cost is modeled from the same workload. - [ ] Rollback remains possible through the cutover window. ## Conclusion The best Confluent alternative depends on what you are actually replacing. If Confluent is your enterprise streaming platform, its broad ecosystem can justify both the platform surface and its consumption model. If Confluent is mainly acting as a managed Kafka cluster for a smaller product team, a narrower service may be easier to operate and budget. Raff is the strongest fit in this comparison for teams that want **Apache Kafka 4.3 with KRaft, fixed plan pricing from $15.99/month, managed broker operations, and a focused `us-east` deployment model**. Amazon MSK is stronger for AWS-native architecture. Aiven is stronger for multi-cloud and managed open-source breadth. Self-managed Kafka is strongest only when direct operational control is itself a requirement. Choose based on the platform capabilities you use today and the responsibilities you want to own tomorrow—not simply the lowest number on a pricing page. :::cta Explore Managed Kafka Compare Raff Managed Kafka when you need Apache Kafka without the operational surface of a larger enterprise streaming platform. ::: ## Sources - [Confluent Cloud Pricing](https://www.confluent.io/pricing/) - [Confluent Cloud Billing Dimensions](https://docs.confluent.io/cloud/current/billing/billing-dimensions.html) - [Confluent Cloud Cluster Types](https://docs.confluent.io/cloud/current/clusters/cluster-types.html) - [Amazon MSK Pricing](https://aws.amazon.com/msk/pricing/) - [Aiven for Apache Kafka Pricing](https://aiven.io/pricing/kafka) - [Aiven Kafka Developer Tier](https://aiven.io/docs/products/kafka/dev-tier/kafka-dev-tier) - [Raff Managed Kafka](/products/managed-databases/kafka) - [Apache Kafka Documentation](https://kafka.apache.org/documentation/) - Pricing and product details reviewed: 2026-08-24 --- ### PlanetScale Alternatives 2026: MySQL & Postgres Options URL: https://rafftechnologies.com/learn/compare/planetscale-alternatives-mysql-postgres Description: Compare PlanetScale alternatives for MySQL and Postgres including Raff, Neon and Supabase across pricing, database engines, branching, scaling, migration and production fit. PlanetScale has changed substantially from the product many developers still remember. In 2026 it is no longer just a serverless MySQL platform: PlanetScale now offers both **Vitess for MySQL-compatible workloads** and **PlanetScale Postgres**, with high-availability and high-performance deployment options, database branching, deploy workflows, and production query tooling. That makes “PlanetScale alternative” a broader decision than it was a few years ago. Some teams want to keep **MySQL compatibility**. Others are comfortable moving to **Postgres**. Some are primarily searching for a cheaper database. Others actually need PlanetScale's branching, non-blocking schema changes, or Vitess-style horizontal scaling. For small and mid-sized teams, the most useful alternatives break into four models: **Raff Managed MySQL/PostgreSQL** for straightforward managed databases with fixed plan pricing, **Neon** for serverless Postgres with scale-to-zero and database branching, **Supabase** for Postgres bundled into a broader backend platform, and staying with **PlanetScale** when Vitess, its schema workflow, or its high-scale architecture is the requirement. ## PlanetScale alternatives at a glance | Option | Database model | Pricing model | Strongest fit | Main trade-off | |---|---|---|---|---| | PlanetScale | Postgres + Vitess/MySQL-compatible | Resource-based / pay-as-you-go | Teams that value Vitess scale, database branching and PlanetScale's schema workflow | More specialized platform than a conventional managed MySQL/Postgres service | | Raff | Managed MySQL 8 + PostgreSQL | Free tier + fixed monthly plans | Small teams wanting familiar engines, predictable plans and managed operations | Smaller regional footprint and fewer database-development workflow features than PlanetScale | | Neon | Serverless Postgres | Free tier + usage-based paid plans | Postgres teams that value scale-to-zero, branching and variable workloads | Postgres only; cost follows metered compute/storage usage | | Supabase | Managed Postgres + backend services | Free tier + subscription + usage | Teams wanting database, auth, storage, realtime and APIs together | Broader backend platform can be unnecessary when the requirement is only a database | **Short answer:** stay with PlanetScale when Vitess, high-scale sharding, its branch/deploy workflow, or PlanetScale-specific operational tooling is part of the requirement. Choose Raff when you mainly need a managed MySQL or PostgreSQL database with a familiar engine and a simpler fixed-plan bill. Choose Neon when serverless Postgres and scale-to-zero are the priority. Choose Supabase when the database is one component of a complete backend platform. ## Why teams look for PlanetScale alternatives The reasons have changed over time. Earlier PlanetScale-alternative searches were often driven by the removal of its old Hobby plan. In 2026 the product itself has expanded: PlanetScale now sells Postgres as well as Vitess, publishes resource-based pricing, and continues to invest in database branches, safe migrations, schema recommendations, CLI tooling, and production insights. Today, teams usually evaluate alternatives for one of six reasons: - they want a **free database tier** for a small project or staging environment; - they want conventional MySQL/Postgres without the additional Vitess layer; - they prefer a fixed monthly plan instead of resource-based billing; - they need a broader backend platform such as auth, object storage, realtime, and APIs; - they want serverless Postgres that scales compute down when idle; - they no longer need PlanetScale-specific branching, schema-deployment, or horizontal-sharding capabilities. The correct alternative depends on which of those problems you are actually solving. ## PlanetScale in 2026: Postgres and Vitess, not just “serverless MySQL” PlanetScale's current public pricing surface supports two database engines: - **PlanetScale Postgres**; - **Vitess**, built around MySQL compatibility and horizontal scaling. PlanetScale currently lists Postgres single-node deployments starting at **$5/month**, high-performance Metal deployments starting at **$50/month**, and high-availability configurations with a primary plus two replicas across three availability zones. Vitess pricing is based on cluster size, VTGate configuration, storage, and the selected infrastructure profile. The current pricing page also includes **100 GB of egress bandwidth**, with additional egress listed at **$0.06/GB**. PlanetScale's strongest differentiator is not simply “we host a database.” Its Vitess product continues to combine vanilla MySQL with routing, control-plane components, and horizontal-sharding architecture. PlanetScale also continues to invest heavily in schema workflow: branches, deploy requests, safe migrations, non-blocking schema changes, query insights, and automation through its CLI/API/Terraform tooling. Choose PlanetScale when several of these are true: - horizontal MySQL scaling through Vitess is part of the architecture; - database branching is integrated into the development workflow; - non-blocking production schema changes are a recurring requirement; - the team values PlanetScale's deploy-request and schema-analysis workflow; - PlanetScale's performance-oriented infrastructure profiles fit the workload; - the organization is comfortable with resource-based pricing. If those are not requirements, a simpler managed database may be easier to operate and budget. ## Raff: best when you want familiar MySQL or Postgres with a smaller operational surface [Raff Managed Databases](/products/managed-databases) is the most direct alternative in this comparison for a team that mainly wants the database engine itself managed. Raff currently offers managed PostgreSQL and MySQL alongside Valkey, Kafka, ClickHouse and MongoDB. PostgreSQL, MySQL and Valkey also have a **free tier**: one free database per account, no fixed trial expiry, with inactive free databases pausing after seven days without a connection while retaining their data. Paid MySQL and PostgreSQL plans currently start at **$7.99/month**. The entry MySQL plan includes **1 vCPU, 1 GB RAM and 25 GB NVMe storage**, with daily backups included. Raff's MySQL service runs MySQL 8 with InnoDB; high-availability MySQL plans use a three-node Galera design behind HAProxy. Raff is a stronger fit when: - standard MySQL 8 or PostgreSQL compatibility is preferable to a specialized distributed database layer; - the team wants a clear fixed monthly plan; - backups, monitoring, private networking and migration support should be part of the managed service boundary; - a free database is useful for development or a small workload; - the application already runs on a conventional ORM or framework and should not need a database-architecture rewrite; - direct migration assistance matters more than sophisticated database branching. Raff is **not** a drop-in replacement for every PlanetScale architecture. A workload that depends on Vitess horizontal sharding, PlanetScale-specific branching, or deploy-request workflows should treat those as migration requirements, not optional features. For the broader operating-model decision, read [MySQL Hosting: Managed vs Self-Hosted for Production Apps](/learn/guides/mysql-hosting-managed-vs-self-hosted). ## Neon: best when the real requirement is serverless Postgres Neon is a better PlanetScale alternative when the application can use Postgres and the priority is serverless behavior rather than MySQL compatibility. Neon's current platform uses a usage-based pricing model and can scale idle compute to zero. Its Free plan remains available, while paid Launch and Scale plans meter compute usage rather than requiring a fixed monthly minimum. Neon also puts database branching at the center of its developer workflow. Current Neon pricing guidance lists: - a Free plan with multiple projects and per-project compute allowances; - Launch compute currently priced at **$0.106 per CU-hour**; - Scale compute currently priced at **$0.222 per CU-hour**; - **500 GB of public data transfer included each month on paid plans** as of June 2026. Neon is strongest when: - Postgres is acceptable or already used; - workloads are bursty or spend long periods idle; - scale-to-zero can materially reduce compute consumption; - branch-per-preview or branch-per-development workflows are important; - the team prefers metered serverless economics over fixed capacity plans. Neon is not the right direct substitute when retaining MySQL compatibility is mandatory. Moving from PlanetScale Vitess/MySQL to Neon is a **database-engine migration**, not just a provider migration. Raff already has a dedicated [Neon Alternative 2026 comparison](/learn/comparisons/neon-alternative) for that narrower provider decision. ## Supabase: best when PlanetScale is only one part of the backend you need Supabase is not primarily a PlanetScale-style database platform. It is a broader backend platform built around Postgres. Its value becomes clear when the application needs several services together: - managed Postgres; - authentication; - object/file storage; - realtime updates; - generated APIs; - edge functions; - backend administration tooling. Supabase currently offers a **Free plan at $0/month** and a **Pro plan from $25/month**. The current Free plan includes a 500 MB database per project. Pro includes an 8 GB disk allocation per project before additional storage charges and includes daily backups with seven-day retention. Choose Supabase when: - the app needs a backend platform rather than only a database; - Postgres is already the preferred engine; - built-in auth, storage, realtime and APIs reduce application engineering; - the team's architecture benefits from consolidating those backend services. Choose another option when the application only needs MySQL/Postgres and the broader platform would add concepts, billing dimensions or migration dependencies that the team does not need. Raff already publishes a dedicated [Supabase Alternative 2026 comparison](/learn/comparisons/supabase-alternative) for teams evaluating that specific switch. ## PlanetScale vs Raff: the most direct small-team decision For a small team that is not choosing a full backend platform, the most relevant comparison is often PlanetScale vs Raff. | Decision | PlanetScale | Raff | |---|---|---| | Engines | Postgres + Vitess/MySQL-compatible | PostgreSQL + MySQL 8 plus other managed data engines | | MySQL architecture | Vitess-based distributed platform | Conventional managed MySQL 8 / InnoDB | | Postgres available | Yes | Yes | | Free database tier | No general free tier shown on current PlanetScale pricing page | Yes for PostgreSQL/MySQL/Valkey, one per account | | Paid entry reference | Postgres single node from $5/month | Managed MySQL/Postgres paid plans from $7.99/month | | Database branching | Core PlanetScale workflow | Not the primary workflow | | Safe/non-blocking schema tooling | Strong PlanetScale feature | Standard database/application migration workflow | | Horizontal Vitess sharding | Core strength | No equivalent Vitess layer | | Pricing style | Resource-based / pay as you go | Fixed plan baseline | | Migration assistance | Provider tooling/support dependent on case | Raff advertises free migration assistance | | Best fit | Teams needing PlanetScale's scale and schema-development model | Teams wanting straightforward managed database operations | The question is therefore not simply “which starts cheaper?” PlanetScale's Postgres entry price can be lower than Raff's paid entry plan, while Raff also has a free database tier. Those numbers describe different capacity models and platform behavior. Choose from architecture first, then compare equivalent production configurations. ## What about TiDB, Railway and other PlanetScale alternatives? Several other products can make sense depending on the workload. ### TiDB TiDB is worth evaluating when retaining MySQL-style application compatibility and distributed horizontal scaling are more important than using conventional MySQL. It competes more directly with the distributed-database problem PlanetScale Vitess solves than Postgres-first alternatives do. ### Railway Railway is useful when the database should live beside application deployments in a developer platform. It can be convenient for small teams that value one deployment workflow for apps and databases, but the purchasing decision is closer to choosing an application platform than choosing a specialized DBaaS. ### Self-managed MySQL or Postgres Self-hosting can reduce provider abstraction and increase control, but it also moves backups, upgrades, monitoring, failover, security, disk growth and incidents back to your team. For small teams, compare that operating cost against the managed option rather than comparing only VM price. Use [VPS for Databases: What Small Teams Should Know](/learn/guides/vps-for-databases) when self-hosting is a serious candidate. ## Pricing comparison: use the same workload The providers in this comparison do not bill the same thing, so headline starting prices should not be treated as equivalent production costs. | Provider | Public pricing approach | Entry/reference point | Important variables | |---|---|---|---| | PlanetScale | Resource-based pay as you go | Postgres single node from $5/month; Metal from $50/month | engine, cluster size, replicas, storage, VTGate, egress | | Raff | Free tier + fixed plans | Free tier; paid MySQL/Postgres from $7.99/month | selected plan, storage growth, HA configuration | | Neon | Free + metered serverless usage | Free; Launch compute $0.106/CU-hour | active compute time, storage, transfer, branch usage | | Supabase | Subscription + compute/usage | Free; Pro from $25/month | compute, database storage, egress, auth/storage/realtime usage, add-ons | Before comparing cost, define: ```text engine + required memory / CPU + average and peak load + database size + monthly growth + read/write pattern + HA requirement + backup / PITR requirement + public egress + region + development branches + extra backend services ``` Then price each provider against the same workload. A free tier can be ideal for development but irrelevant to a production HA cluster. A $5 single-node plan is not equivalent to a three-node HA cluster. A usage-based database can be extremely inexpensive when idle and more expensive when continuously active. **Compare equivalent outcomes, not marketing entry prices.** ## Migration from PlanetScale: identify whether you are moving providers or database engines The first migration question is whether the target uses the same database family. ### PlanetScale Vitess to Raff Managed MySQL This keeps the application in the MySQL ecosystem, but it is still not a simple server copy. Vitess adds its own topology, routing and operational behavior. Validate: - SQL and feature compatibility used by the application; - schema and index definitions; - foreign key behavior used by the current PlanetScale configuration; - connection limits and pooling; - transaction patterns; - table size and growth; - data export/replication method; - cutover and rollback approach. ### PlanetScale Postgres to Raff or Neon Postgres This is a same-engine provider migration, which generally reduces application rewrite risk, but you still need to validate: - extensions; - roles and privileges; - connection strings and TLS; - logical replication or migration tooling; - sequence and identity state; - backups and PITR expectations; - connection pooling; - cutover lag and rollback. ### PlanetScale MySQL/Vitess to Neon or Supabase This is a MySQL-to-Postgres migration. Treat it as an application and schema migration, not merely infrastructure replacement. Data types, indexes, SQL behavior, extensions, migrations and ORM behavior all need validation. ## PlanetScale alternative migration checklist - [ ] Confirm whether the source is PlanetScale Vitess or PlanetScale Postgres. - [ ] Decide whether the target keeps the same database engine. - [ ] Inventory schema, indexes, extensions and database-specific features. - [ ] Measure production database size and write rate. - [ ] Document connection and transaction patterns. - [ ] Define HA and recovery requirements on the target. - [ ] Map backups and PITR expectations. - [ ] Identify PlanetScale branch/deploy workflows that must be replaced. - [ ] Test application queries against the target before moving production data. - [ ] Choose replication, logical migration or export/import based on the engine pair. - [ ] Define a cutover window and rollback condition. - [ ] Verify consumer/background jobs do not continue writing to the old database after cutover. - [ ] Validate application behavior and business data before deleting the source. ## Which PlanetScale alternative should you choose? ### Stay with PlanetScale when - Vitess horizontal scaling is a real requirement; - PlanetScale's branching and deploy-request workflow saves your team meaningful engineering time; - non-blocking schema changes are part of frequent production releases; - the current resource-based pricing matches workload economics; - moving away would require rebuilding database workflows that are already working well. ### Choose Raff when - standard managed MySQL 8 or PostgreSQL fits the application; - predictable fixed monthly plans matter; - the team wants a free development/small-workload database option; - conventional ORM and framework compatibility is more important than Vitess-specific scale; - migration assistance and direct human support are valuable; - the team wants multiple managed data engines under one provider. ### Choose Neon when - Postgres is the target engine; - scale-to-zero is valuable; - database branching is central to development and preview workflows; - usage-based serverless pricing fits an intermittent workload. ### Choose Supabase when - the application needs Postgres plus auth, storage, realtime and APIs; - consolidating backend services is more important than buying a database independently. ## Conclusion PlanetScale is no longer a product that can be summarized as “serverless MySQL.” In 2026 it is a broader cloud database platform spanning PlanetScale Postgres and Vitess, with sophisticated branching, schema-deployment and performance workflows. That means the best alternative depends on what part of PlanetScale you actually value. Choose **Raff** when the goal is a familiar managed MySQL or Postgres database with a free tier, fixed paid plans from $7.99/month, backups and managed operations without adopting a specialized distributed-database workflow. Choose **Neon** when serverless Postgres and scale-to-zero are central. Choose **Supabase** when the database should arrive with a full backend platform. Stay with **PlanetScale** when Vitess, database branching, safe migrations, or its high-scale workflow materially reduce engineering work. The right migration is the one that removes complexity your team does not need without throwing away capabilities it actually depends on. :::cta Explore Managed Databases Compare Raff Managed MySQL and PostgreSQL when you want a conventional managed database with a predictable plan and migration support. ::: ## Sources - [PlanetScale Pricing](https://planetscale.com/pricing) - [PlanetScale Features](https://planetscale.com/features) - [PlanetScale Vitess](https://planetscale.com/vitess) - [PlanetScale Changelog](https://planetscale.com/changelog) - [Neon Usage-Based Pricing](https://neon.com/blog/new-usage-based-pricing) - [Neon Compute Price Update](https://neon.com/blog/major-compute-price-reduction-on-neon) - [Neon Data Transfer Update](https://neon.com/blog/more-data-transfer-on-paid-plans) - [Supabase Pricing](https://supabase.com/pricing) - [Raff Managed Databases](/products/managed-databases) - [Raff Managed MySQL](/products/managed-databases/mysql) - Product and pricing details reviewed: 2026-08-24 --- ### Cloudflare R2 Pricing 2026: Free Tier, Costs & Raff Comparison URL: https://rafftechnologies.com/learn/compare/raff-object-storage-vs-cloudflare-r2 Description: Cloudflare R2 pricing explained for 2026: Standard and Infrequent Access rates, 10 GB free tier, request costs, free egress, calculator examples, and Raff comparison. Cloudflare R2 pricing in 2026 is built around four meters: stored data, Class A operations, Class B operations, and—only for Infrequent Access—data retrieval. **Standard storage costs $0.015/GB-month, Infrequent Access costs $0.01/GB-month, and direct internet egress from R2 is free.** The Standard free tier includes 10 GB-month of storage, 1 million Class A operations, and 10 million Class B operations every month. For most buyers, the important detail is that R2 is not simply “$0.015 per GB.” Request volume can become the larger part of the bill. Raff Object Storage uses a different model: **$7/month includes 100 GB storage, 1 TB egress, and no separate API request charges.** Raff is materially more expensive for storage-heavy, low-request workloads, while it can be cheaper for request-heavy workloads. ## Cloudflare R2 pricing at a glance | R2 meter | Standard | Infrequent Access | |---|---:|---:| | Storage | $0.015/GB-month | $0.01/GB-month | | Class A operations | $4.50/million | $9.00/million | | Class B operations | $0.36/million | $0.90/million | | Retrieval processing | None | $0.01/GB | | Internet egress | Free | Free | | Minimum storage duration | None | 30 days | | Free tier | Yes | No | Cloudflare's free tier applies only to **Standard storage**. It does not apply to Infrequent Access. Cloudflare also rounds each billable meter up to the next billing unit. For example, 1.1 GB-month is billed as 2 GB-months, and 1,000,001 operations are billed as 2 million operations. That rounding matters most for small workloads close to a billing boundary. ## Cloudflare R2 free tier in 2026 The current R2 Standard free tier includes, every month: - **10 GB-month of Standard storage** - **1 million Class A operations** - **10 million Class B operations** - **Free direct internet egress** The free tier resets monthly and applies only to Standard storage. Infrequent Access does not receive the 10 GB storage allowance or the operation allowances. This makes R2 attractive for small sites, prototypes, static assets, and applications whose reads stay below the included Class B allowance. The common mistake is assuming that “free egress” means serving any amount of traffic is completely free. R2 itself does not charge egress bandwidth, but reads still count as Class B operations. Other Cloudflare products connected to R2 can also have their own pricing. ## How much does Cloudflare R2 cost? For Standard storage, a useful simplified formula is: ```text Monthly R2 cost = billable storage + billable Class A operations + billable Class B operations ``` Where, after the Standard free tier: ```text Storage: $0.015 per GB-month Class A: $4.50 per million operations Class B: $0.36 per million operations Egress: $0 ``` Cloudflare rounds usage up to the next billing unit, so use the official R2 calculator for exact production estimates. ### 100 GB stored with light request volume If you store 100 GB for the month in Standard storage and stay inside the free operation allowances: ```text 100 GB - 10 GB free = 90 GB billable 90 × $0.015 = $1.35/month ``` **Estimated R2 cost: $1.35/month.** Raff Object Storage is **$7/month** for the same 100 GB capacity, but that $7 also includes 1 TB egress and no separate request meter. For a storage-led workload with light requests, R2 wins clearly on price. ### 1,000 GB stored with light request volume For 1,000 GB of R2 Standard storage: ```text 1,000 GB - 10 GB free = 990 GB billable 990 × $0.015 = $14.85/month ``` **Estimated R2 cost: $14.85/month.** Raff would cost **$70/month** for 1,000 GB of storage before any egress overage. Again, R2 is much cheaper when stored capacity is the main cost driver. ### 100 GB with 300 million reads per month This is where the model changes. At 100 GB, storage is still about $1.35. If the bucket receives 300 million Class B reads: ```text 300M reads - 10M free = 290M billable reads 290 × $0.36 = $104.40 Storage = $1.35 Total ≈ $105.75/month ``` Raff remains **$7/month** at 100 GB because API requests are not metered separately. This is the key crossover: **R2 is cheaper for storage-heavy workloads; Raff can be cheaper for request-heavy workloads.** ### 100 GB with 50 million Class A operations Class A operations are much more expensive than Class B operations. ```text 50M Class A - 1M free = 49M billable 49 × $4.50 = $220.50 Storage = $1.35 Total ≈ $221.85/month ``` Raff remains $7 at 100 GB because there is no separate Class A/Class B billing model. Applications that frequently list objects, write many small files, perform multipart workflows, or generate large volumes of metadata operations should model these request costs before choosing a provider. ## Cloudflare R2 pricing calculator: what to include When estimating R2, use more than stored GB. A useful calculator input set is: 1. average GB-month stored; 2. Standard vs Infrequent Access storage; 3. monthly Class A operations; 4. monthly Class B operations; 5. GB retrieved from Infrequent Access; 6. whether objects may be deleted before the 30-day IA minimum; 7. costs from any other Cloudflare service connected to the bucket. Cloudflare provides an official R2 pricing calculator. It is particularly useful because R2 rounds billable usage to whole units and because operation count can dominate low-storage workloads. For application planning, also separate **object count** from **stored capacity**. One 100 GB file and one million 100 KB objects can have similar storage footprints but very different request patterns. ## Cloudflare R2 vs Raff Object Storage: quick cost comparison | Scenario | Raff Object Storage | Cloudflare R2 Standard | Better fit | |---|---:|---:|---| | 100 GB, light operations | $7.00/mo | About $1.35/mo | R2 | | 500 GB, light operations | $35.00/mo | About $7.35/mo | R2 | | 1,000 GB, light operations | $70.00/mo | About $14.85/mo | R2 | | 100 GB, 300M Class B reads | $7.00/mo | About $105.75/mo | Raff | | 100 GB, 50M Class A operations | $7.00/mo | About $221.85/mo | Raff | These examples use R2 Standard, apply the monthly Standard free tier, and assume no other billable operation classes unless shown. The table is not meant to claim that Raff is cheaper overall. It shows that the two products optimize for different billing patterns. ## Raff Object Storage pricing Raff Object Storage uses a simpler bundle: - **$7/month base price** - **100 GB storage included** - **1 TB egress included each month** - **API requests are not separately metered** - **$0.07/GB-month for storage above 100 GB** - **$0.01/GB for egress above 1 TB** - **Free inbound traffic** There are no Class A or Class B request meters. That makes Raff easier to forecast for backup tooling, application uploads, object browsers, sync jobs, or workloads that generate many small API calls. The trade-off is important: Raff's raw per-GB storage price is higher than R2. If your workload is mostly stored capacity with modest request volume or very high public egress, R2 is usually the cheaper choice. :::cta Create a Bucket Now Create S3-compatible storage with 100 GB and 1 TB egress included for $7/month. ::: ## Is Cloudflare R2 egress really free? For R2 itself, direct egress to the internet is free for both Standard and Infrequent Access storage. Cloudflare specifically documents free R2 egress through the Workers API, S3 API, and `r2.dev` domains. The important caveat is that **other metered Cloudflare services connected to R2 can still generate their own charges**. R2 therefore has a major advantage for: - public asset delivery; - software downloads; - media files; - large datasets downloaded frequently; - migration architectures where outbound bandwidth would otherwise dominate the bill. Raff includes 1 TB egress in the $7 bundle and then charges $0.01/GB. | Monthly internet egress | Raff incremental egress charge | R2 egress charge | |---:|---:|---:| | 1 TB | $0 | $0 | | 5 TB | $40.96 | $0 | | 10 TB | $92.16 | $0 | | 50 TB | $501.76 | $0 | For bandwidth-heavy public delivery, R2 is the stronger economic choice. ## Standard vs Infrequent Access pricing R2 Infrequent Access lowers the storage rate from $0.015 to $0.01 per GB-month, but it is not simply a cheaper version of Standard. Infrequent Access adds: - Class A operations at $9.00/million; - Class B operations at $0.90/million; - $0.01/GB retrieval processing; - a 30-day minimum storage duration; - no Standard free-tier allowances. Use Infrequent Access for objects that are genuinely cold and remain stored long enough for the lower capacity price to offset retrieval and request costs. Do not use it simply because $0.01/GB looks lower on the pricing table. ## What are Class A and Class B operations? Cloudflare groups R2 requests into operation classes. **Class A operations** generally mutate state or perform management work. Examples include `PutObject`, `ListObjects`, multipart upload operations, copies, and lifecycle configuration changes. **Class B operations** generally read existing data or metadata. Examples include `GetObject`, `HeadObject`, and several bucket metadata reads. Deletes and some abort operations are free. For asset-heavy sites, Class B reads are usually the meter to watch. For upload-heavy systems, backup tools, data ingest, or object-management workflows, Class A volume can become significant. ## Feature comparison: Cloudflare R2 vs Raff Pricing is only part of the decision. | Feature | Raff Object Storage | Cloudflare R2 | |---|---|---| | S3-compatible API | Yes | Yes | | Standard storage class | Yes | Yes | | Infrequent Access class | No | Yes | | Direct internet egress | 1 TB included, then $0.01/GB | Free | | Request charges | None | Class A / Class B after free tier | | Free storage tier | No separate free tier | 10 GB-month Standard | | Lifecycle rules | Not currently exposed | Yes | | Bucket locks | Not currently exposed | Yes, Cloudflare bucket locks | | Native S3 bucket versioning | No | Not implemented in the R2 S3 compatibility matrix | | Presigned URLs | Yes | Yes | | Multipart uploads | Yes | Yes | | Workers integration | Separate Raff compute products | Native R2 Workers binding | | Public placement options | `us-east` | Automatic placement, location hints, jurisdiction controls | R2 also publishes an eleven-nines annual durability design target and documents redundancy across multiple storage facilities within a geographic region. Raff publishes a 99.9% platform SLA but does not publish an equivalent object-durability target. If a procurement or recovery policy requires a published durability target, R2 has the stronger documented position. ## Is R2 really S3-compatible? R2 implements a broad S3-compatible API and works with many AWS S3 SDKs and tools by changing the endpoint and credentials. It is not full Amazon S3 parity. Cloudflare publishes a compatibility matrix showing implemented and unsupported operations. For example, native S3 bucket versioning operations such as `PutBucketVersioning` remain unsupported, and S3 Object Lock APIs are not equivalent to Cloudflare's separate Bucket Locks feature. Raff is also S3-compatible for common object-storage workflows, including AWS CLI, SDKs, rclone, s3cmd, multipart uploads, and presigned URLs. Before migrating stateful storage, test the exact API operations your application depends on rather than treating “S3-compatible” as “identical to S3.” ## When Cloudflare R2 is the better choice Choose R2 when: - raw storage price is the primary cost driver; - public internet egress is high; - you need a free tier for a small workload; - you use Cloudflare Workers or Cloudflare-native delivery; - lifecycle rules or Cloudflare Bucket Locks matter; - you need broader placement and jurisdiction controls; - you want a published eleven-nines durability design target. For large, low-request buckets, R2's pricing advantage is substantial. ## When Raff is the better choice Choose Raff when: - request volume is high or difficult to predict; - you want one fixed base bundle instead of separate operation classes; - 100 GB storage and 1 TB egress fit the workload; - your application infrastructure is already on Raff; - you want storage, compute, networking, databases, and support under one account; - you do not need R2-specific lifecycle, placement, or Cloudflare Workers integrations. The strongest Raff case is not “cheaper storage.” It is **simpler request economics and fewer billing dimensions**. ## Migrating between R2 and Raff Both products use S3-compatible workflows, so the data path is familiar, but feature parity still needs review. A safe migration plan is: 1. inventory buckets, object counts, total bytes, storage classes, lifecycle rules, bucket locks, CORS, access keys, and application dependencies; 2. create the target bucket and credentials; 3. verify required S3 operations on the target provider; 4. copy objects with rclone, an S3 SDK, or another S3-compatible migration tool; 5. preserve content types, cache headers, object keys, and metadata; 6. validate object counts and checksums; 7. test presigned URLs, uploads, downloads, CORS, and permissions; 8. cut over the application endpoint with a rollback window; 9. remove the old bucket only after new writes and reads are verified. If the application continues writing during migration, plan a final synchronization or controlled write freeze before cutover. R2 Infrequent Access objects can also incur retrieval and minimum-duration charges during migration, so include those costs in the plan. ## Frequently asked questions ### How much is Cloudflare R2? R2 Standard storage is $0.015/GB-month after the 10 GB Standard free tier. Standard Class A operations are $4.50/million after 1 million free monthly operations, and Class B operations are $0.36/million after 10 million free monthly operations. Direct R2 internet egress is free. ### Is Cloudflare R2 free? R2 has a monthly Standard free tier, not an unlimited free plan. It includes 10 GB-month storage, 1 million Class A operations, 10 million Class B operations, and free direct egress. The free tier does not apply to Infrequent Access storage. ### Why is Cloudflare R2 so cheap? R2 prices storage aggressively and does not charge direct internet egress. It still charges for Class A and Class B operations, so request-heavy workloads can cost much more than the storage price alone suggests. ### Is R2 egress really free? Direct egress from R2 is free. Cloudflare notes that other metered services connected to R2 may still have their own charges. ### What is the Cloudflare R2 free storage limit? The Standard free tier includes 10 GB-month of storage per month. Usage above that is billed at $0.015/GB-month. Infrequent Access does not receive the free storage allowance. ### Is R2 cheaper than Raff Object Storage? For storage-heavy, low-request workloads, usually yes. At 100 GB with light operations, R2 is about $1.35/month versus Raff at $7. For request-heavy workloads, Raff can be cheaper because it does not charge per API request. ### Does Cloudflare R2 charge for reads? Yes, after the free allowance. Standard Class B operations, which include common reads such as `GetObject`, cost $0.36 per million requests after 10 million free operations each month. ### Does Cloudflare R2 have a pricing calculator? Yes. Cloudflare provides an official R2 pricing calculator. Use it for exact estimates because storage, requests, storage class, retrieval, and billable-unit rounding all affect the total. ## Sources - [Cloudflare R2 pricing](https://developers.cloudflare.com/r2/pricing/) - [Cloudflare R2 S3 API compatibility](https://developers.cloudflare.com/r2/api/s3/api/) - [Cloudflare R2 durability](https://developers.cloudflare.com/r2/reference/durability/) - [Raff Object Storage](/products/object-storage) - Date verified: 2026-08-28 ## Conclusion: Cloudflare R2 pricing vs Raff Cloudflare R2 is one of the lowest-cost mainstream S3-compatible options when stored capacity and public egress dominate the workload. Standard storage is $0.015/GB-month, direct egress is free, and the monthly free tier covers 10 GB-month plus substantial request allowances. The trade-off is request-based billing. Class A and Class B operations can become the largest part of the bill for asset-heavy, backup, synchronization, or metadata-intensive workloads. Raff takes the opposite approach: $7/month includes 100 GB storage, 1 TB egress, and no separate API request charges. Choose **Cloudflare R2** when low per-GB storage cost, free egress, Cloudflare integrations, or lifecycle controls matter most. Choose **Raff** when request volume is hard to forecast and a simpler bundled bill is more valuable than the lowest raw storage price. --- ### AWS Lightsail Pricing 2026: Plans, Costs & Raff Comparison URL: https://rafftechnologies.com/learn/compare/raff-vs-aws-lightsail Description: AWS Lightsail pricing in 2026: Linux plans from $3.50 IPv6-only or $5 with public IPv4, transfer allowances, overage costs, add-ons, and Raff comparison. AWS Lightsail pricing in 2026 starts at **$3.50/month for an IPv6-only Linux/Unix virtual server** or **$5/month for a Linux/Unix bundle with a public IPv4 address**. The popular public-IPv4 General Purpose tier with **2 vCPU, 4 GB RAM, 80 GB SSD, and 4 TB transfer is $24/month**. Lightsail bundles compute, SSD storage, and a transfer allowance into one monthly cap, but snapshots, block storage, load balancers, databases, object storage, and transfer overages are separate charges. Raff uses a different VM pricing model. Its current General Purpose **2 vCPU / 4 GB / 80 GB NVMe** plan is **$13.99/month with unmetered VM bandwidth**. At the four Lightsail General Purpose shapes that match Raff on vCPU, RAM, and disk capacity, Raff is about **29% to 42% lower on monthly VM price** before any Lightsail transfer overage. This page focuses on the actual cost question: what Amazon Lightsail costs, what the monthly bundle includes, where extra charges appear, and when the simpler Raff price model can be cheaper. ## AWS Lightsail pricing in 2026 Amazon Lightsail offers General Purpose, Memory Optimized, and Compute Optimized virtual-server bundles. It also prices Linux/Unix and Windows separately and offers a lower-priced IPv6-only option for virtual servers that do not need a public IPv4 address. The current **Linux/Unix General Purpose bundles with public IPv4** include: | Monthly price | Memory | vCPU | SSD disk | Transfer allowance | |---:|---:|---:|---:|---:| | $5 | 0.5 GB | 2 vCPU | 20 GB | 1 TB | | $7 | 1 GB | 2 vCPU | 40 GB | 2 TB | | $12 | 2 GB | 2 vCPU | 60 GB | 3 TB | | $24 | 4 GB | 2 vCPU | 80 GB | 4 TB | | $44 | 8 GB | 2 vCPU | 160 GB | 5 TB | | $84 | 16 GB | 4 vCPU | 320 GB | 6 TB | | $164 | 32 GB | 8 vCPU | 640 GB | 7 TB | | $384 | 64 GB | 16 vCPU | 1,280 GB | 8 TB | Lightsail also scales much higher than Raff, including larger General Purpose, Memory Optimized, and Compute Optimized bundles. That matters when a workload needs more than Raff's current 16 vCPU / 32 GB ceiling. ### AWS Lightsail IPv6-only pricing Lightsail discounts virtual servers that use only IPv6. Current Linux/Unix General Purpose examples are: | Monthly price | Memory | vCPU | SSD disk | Transfer allowance | |---:|---:|---:|---:|---:| | $3.50 | 512 MB | 2 vCPU | 20 GB | 1 TB | | $5 | 1 GB | 2 vCPU | 40 GB | 2 TB | | $10 | 2 GB | 2 vCPU | 60 GB | 3 TB | | $20 | 4 GB | 2 vCPU | 80 GB | 4 TB | | $40 | 8 GB | 2 vCPU | 160 GB | 5 TB | | $80 | 16 GB | 4 vCPU | 320 GB | 6 TB | | $160 | 32 GB | 8 vCPU | 640 GB | 7 TB | If the application can operate without public IPv4, the IPv6-only bundle is the correct Lightsail price to compare. If you need a public IPv4 address, use the public-IPv4 table instead of quoting the $3.50 entry price. ## What is included in AWS Lightsail pricing? Lightsail's core appeal is that a virtual-server plan bundles several resources under one monthly price. AWS currently lists a static IP address, management console, DNS management, one-click SSH or RDP access, API access, SSD storage, and server monitoring among the capabilities included with Lightsail plans. The VM price also includes a transfer allowance. For the public-IPv4 General Purpose Linux bundles above, that allowance ranges from 1 TB on the smallest plan to 10 TB on the largest tiers. However, the VM bundle is not the entire Lightsail bill. Common separate charges include: | Lightsail add-on | Current pricing signal | |---|---:| | Manual or automatic snapshots | $0.05/GB-month | | Block storage | $0.10/GB-month | | Load balancer | $18/month | | Object storage | $1/mo for 5 GB, $3/mo for 100 GB, $5/mo for 250 GB | | Managed database | Starts at $15/mo Standard or $30/mo HA | | CDN distribution | Starts at $2.50/month | The practical lesson is that **Lightsail virtual-server pricing is predictable at the bundle level, but the full application price can grow as you add storage, backups, databases, load balancing, CDN, and transfer overages.** ## AWS Lightsail vs Raff pricing Raff's current General Purpose VM lineup is designed around several CPU-to-memory ratios rather than one fixed ladder. Four Lightsail General Purpose shapes currently match a Raff plan exactly on **vCPU, RAM, and disk capacity**: | Shape | Raff General Purpose | AWS Lightsail public IPv4 | Raff price difference | |---|---:|---:|---:| | 2 vCPU / 4 GB / 80 GB | **$13.99/mo** | $24/mo | about 42% lower | | 2 vCPU / 8 GB / 160 GB | **$27.99/mo** | $44/mo | about 36% lower | | 4 vCPU / 16 GB / 320 GB | **$52.99/mo** | $84/mo | about 37% lower | | 8 vCPU / 32 GB / 640 GB | **$115.99/mo** | $164/mo | about 29% lower | The comparison above is deliberately narrow. It compares monthly VM price at matching resource shapes. It does **not** imply identical CPU behavior, storage architecture, region coverage, ecosystem depth, or service feature parity. Raff also offers smaller and alternative ratios, including 2 vCPU / 2 GB at $8.49, 4 vCPU / 4 GB at $16.99, and 4 vCPU / 8 GB at $30.99. All current Raff General Purpose VM plans include unmetered bandwidth on a 3 Gbps public port. For current Raff sizes, see [Raff cloud pricing](/pricing) and [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained). ## AWS Lightsail bandwidth pricing and transfer overages The transfer allowance is the most important variable after VM size. AWS states that **both inbound and outbound transfer count toward the Lightsail allowance**, but only **outbound transfer above the allowance** is billed as overage. Transfer allowances are also smaller in several Asia-Pacific and South America regions than the headline bundle values. Overage pricing varies by AWS Region. In **US East**, Lightsail transfer overage is currently **$0.09/GB**. For the $24 public-IPv4 General Purpose plan with a 4 TB transfer allowance, a simple all-outbound example looks like this: | Monthly outbound transfer | Raff 2 vCPU / 4 GB | Lightsail 2 vCPU / 4 GB | |---:|---:|---:| | 2 TB | $13.99 | $24 | | 4 TB | $13.99 | $24 | | 6 TB | $13.99 | about $204 | | 8 TB | $13.99 | about $384 | | 20 TB | $13.99 | about $1,464 | The Lightsail examples use $0.09/GB and 1 TB = 1,000 GB for the overage calculation. Real bills depend on region, ingress/outbound mix, pooled allowances, and other Lightsail resources. For low-traffic applications, the included allowance may be plenty and no overage appears. For public downloads, media delivery, large restores, software distribution, or unexpectedly viral traffic, the transfer line can become the dominant cost. Raff VM bandwidth is currently unmetered, so those examples remain at the VM's monthly price rather than adding a GB-based transfer charge. ## Is AWS Lightsail free? AWS currently includes Lightsail in the AWS Free Tier and advertises free-start offers for selected Lightsail bundles. The exact eligible plans and duration can depend on the current AWS Free Tier offer and account eligibility, so treat the free tier as an onboarding offer rather than the long-term production price. For production planning, use the normal bundle prices above and verify any free-tier credit separately on AWS before deployment. ## AWS Lightsail snapshot and backup costs Lightsail prices **manual and automatic instance/disk snapshots at $0.05/GB-month**. That means backup cost scales with snapshot storage rather than being permanently included in the VM bundle. Raff uses a different backup model. Current Raff VM accounts receive a backup and snapshot storage pool, with additional storage priced separately. The important architecture point is that neither provider's backup cost should be inferred from the VM headline price alone: check retention, snapshot growth, and restore requirements. For recovery planning, see [VPS backup strategy](/learn/guides/vps-backup-strategy) and [Raff Data Protection](/products/data-protection). ## Lightsail block storage, load balancer, database, and object-storage pricing A multi-service Lightsail architecture can add several fixed or usage-based components: - **Block storage:** $0.10 per allocated GB-month, starting at 8 GB. - **Load balancer:** $18/month. - **Object storage:** bundles currently start at $1/month for 5 GB and 25 GB transfer; the 100 GB bundle is $3/month with 250 GB transfer. - **Managed databases:** Standard plans start at $15/month; HA starts at $30/month. - **CDN distributions:** start at $2.50/month. This is why a fair Lightsail cost calculation should model the application architecture, not only the VM. A WordPress site using a VM, CDN distribution, and object storage has a different monthly bill from a single Lightsail instance. A SaaS application using a VM, managed database, snapshots, and load balancer has a different cost again. ## AWS Lightsail pricing calculator: what to include Before comparing Lightsail with another VPS or cloud provider, estimate at least these variables: 1. Linux/Unix or Windows; 2. public IPv4 or IPv6-only; 3. General Purpose, Memory Optimized, or Compute Optimized; 4. required vCPU, RAM, and SSD capacity; 5. monthly inbound and outbound transfer; 6. transfer-overage region; 7. snapshot storage and retention; 8. attached block storage; 9. load balancers; 10. managed databases; 11. object storage and CDN usage; 12. whether the workload will stay inside Lightsail or expand into the wider AWS catalog. That final point matters. Lightsail can be economical as a simple VPS, but an application that gradually adds RDS, S3, CloudFront, Lambda, Route 53, or other AWS services is no longer a Lightsail-only pricing problem. ## AWS Lightsail vs Raff: features and operating model ### Compute Lightsail offers a much wider upper range than Raff and now exposes General Purpose, Memory Optimized, and Compute Optimized bundles. The smallest Lightsail plans are attractive for tiny workloads, especially when IPv6-only is acceptable. Raff General Purpose starts at 2 vCPU / 2 GB / 40 GB NVMe for $8.49/month and offers multiple CPU-to-memory ratios through 16 vCPU / 32 GB. Raff also has a separate CPU-Optimized line for workloads that need a different compute model. ### Networking Raff current VM plans include a 3 Gbps public port and unmetered bandwidth, plus private networking, VPC, firewall controls, and IPv4 with optional IPv6. Lightsail bundles a transfer allowance with each virtual server. Only outbound transfer above the allowance is billed, and regional overage prices apply. Lightsail also includes DNS tooling and supports load balancers and CDN distributions as separate products. ### Storage Both platforms separate VM disk from other storage products. Raff offers NVMe-backed VM disk, block volumes, and S3-compatible Object Storage. Lightsail offers SSD bundle storage, block storage, snapshots, and Lightsail Object Storage, with Amazon S3 available elsewhere in the AWS account. ### Managed databases and application services Lightsail offers managed databases and a container service, while the wider AWS account provides products such as RDS, Lambda, EKS, S3, CloudFront, and many more. Raff provides managed databases, Kubernetes, Apps, Functions, object storage, VPC, and data protection under the same platform. AWS wins on catalog breadth; Raff focuses on a smaller infrastructure surface with simpler pricing. ## What about AWS Lightsail performance? There is **no current controlled Raff-vs-Lightsail benchmark with the same VM shape, region, image, test window, and methodology** that is strong enough to support a responsible performance winner. The earlier comparison used third-party Lightsail data and Raff internal data from different regions and different memory sizes. Those results are not suitable for a direct speed claim, so this update does not present them as a benchmark. If performance is the deciding factor, test the exact Lightsail and Raff shapes you would buy using the same OS image, CPU workload, disk test, network path, and sustained-load duration. Pricing can be compared from published rate cards; performance needs matched measurement. ## When AWS Lightsail is the better choice Choose Lightsail when: - you want a very small VM starting below Raff's entry price; - an IPv6-only server fits the workload and you want the lowest Lightsail bundle price; - your application already lives inside an AWS account; - you expect to use RDS, S3, CloudFront, Lambda, Route 53, or other AWS services; - you need a much larger VM than Raff's current maximum; - you need broader AWS region coverage; - AWS-specific contracts, compliance controls, IAM practices, or operational tooling are already part of the organization. Lightsail's strongest advantage is the path into the broader AWS ecosystem, not merely the VPS bundle price. ## When Raff is the better choice Choose Raff when: - a current Raff shape matches the workload and you want a lower monthly VM price; - bandwidth usage is high or difficult to predict; - you want unmetered VM transfer rather than a transfer allowance and regional overage model; - the application needs the common infrastructure layers rather than the full AWS service catalog; - you want VM, database, storage, networking, Kubernetes, Apps, Functions, and support under a smaller platform surface; - predictable monthly infrastructure cost matters more than access to hundreds of AWS services. At the exact 2 vCPU / 4 GB / 80 GB match, Raff is currently $13.99/month versus Lightsail public-IPv4 General Purpose at $24/month. :::cta Deploy a Cloud Server Deploy a Raff VM with unmetered bandwidth and current General Purpose plans from $8.49/month. ::: ## Migrating from AWS Lightsail to Raff 1. **Export the real monthly cost first.** Review the last several Lightsail bills for VM bundles, transfer overage, snapshots, block storage, databases, CDN, and load balancers. 2. **Inventory AWS dependencies.** Identify S3, RDS, CloudFront, Route 53, IAM, Lambda, or other services that will stay in AWS if only the VM moves. 3. **Choose the Raff shape from measured usage.** Match CPU, RAM, and storage based on actual workload metrics instead of copying the Lightsail bundle blindly. 4. **Provision networking and security.** Recreate firewall rules, private networking, credentials, and monitoring before moving production traffic. 5. **Move state deliberately.** Copy files, database data, and application assets using a tested migration plan. Keep the source available until checks pass. 6. **Lower DNS TTL and cut over.** Switch traffic only after application, database, storage, and backup verification. 7. **Delete unneeded AWS resources after rollback.** Removing the instance alone may not remove snapshots, disks, databases, static IPs, load balancers, or other billable resources. If the application depends heavily on AWS-native services, moving only the VM can increase cross-cloud complexity. In that case, the lower VM price may not justify the architectural split. ## Frequently asked questions ### How much does AWS Lightsail cost? Linux/Unix General Purpose virtual servers currently start at $3.50/month for IPv6-only or $5/month with a public IPv4 address. Larger public-IPv4 bundles include $24/month for 2 vCPU / 4 GB / 80 GB with 4 TB transfer and $44/month for 2 vCPU / 8 GB / 160 GB with 5 TB transfer. ### Is AWS Lightsail cheaper than EC2? There is no universal answer. Lightsail bundles compute, SSD storage, and transfer into a fixed monthly plan, while EC2 exposes more instance families and pricing dimensions. Lightsail is usually easier to estimate for a simple VPS; EC2 is more flexible for broader AWS architectures. ### Is AWS Lightsail free? AWS includes Lightsail in its Free Tier offers for eligible accounts and selected plans. Treat the free offer as temporary onboarding and use normal bundle pricing for long-term production budgeting. ### Does AWS Lightsail charge for bandwidth? Each Lightsail VM includes a transfer allowance. Both inbound and outbound traffic count toward that allowance, but only outbound transfer above the allowance is charged. Regional overage pricing applies; US East is currently $0.09/GB. ### How much do Lightsail snapshots cost? Manual and automatic instance/disk snapshots are currently $0.05/GB-month. ### What is the cheapest AWS Lightsail plan? The cheapest current Linux/Unix General Purpose virtual-server bundle is $3.50/month with IPv6 only. The cheapest bundle with a public IPv4 address is $5/month. ### Is Raff cheaper than AWS Lightsail? At four matching public-IPv4 General Purpose shapes, Raff is currently about 29% to 42% lower on the monthly VM price. The exact 2 vCPU / 4 GB / 80 GB comparison is $13.99/month on Raff versus $24/month on Lightsail. Lightsail can still be the better choice when AWS ecosystem access, global regions, or larger instances matter more than VM price. ### Does Lightsail have a pricing calculator? AWS provides pricing pages and the broader AWS Pricing Calculator. For Lightsail, estimate the VM bundle plus transfer overage, snapshots, block storage, load balancers, databases, object storage, CDN, and any wider AWS services the application uses. ## Sources - [Amazon Lightsail pricing](https://aws.amazon.com/lightsail/pricing/) - [AWS Free Tier for Lightsail](https://aws.amazon.com/free/compute/lightsail/) - [Raff pricing](/pricing) - [Raff General Purpose VM Plans](/learn/guides/raff-general-purpose-vm-plans-explained) - Pricing verified: 2026-08-28 ## Conclusion: AWS Lightsail pricing vs Raff AWS Lightsail remains one of AWS's simplest compute products because the VM price bundles memory, vCPU, SSD storage, and a transfer allowance. Linux plans start at $3.50/month for IPv6-only and $5/month with public IPv4, while larger General Purpose bundles scale far beyond Raff's current maximum. For directly matched public-IPv4 VM shapes, Raff is currently about 29% to 42% lower on monthly VM price and includes unmetered VM bandwidth. Lightsail's trade-off is access to a larger AWS operating model: broader regions, much larger servers, and a path into hundreds of AWS services. Choose **AWS Lightsail** when AWS integration, region choice, very small entry plans, or large instance sizes matter most. Choose **Raff** when the workload fits Raff's current VM range and predictable pricing with unmetered VM bandwidth is the stronger requirement. --- ### AWS S3 Pricing 2026: Storage, Egress & Raff Comparison URL: https://rafftechnologies.com/learn/compare/raff-object-storage-vs-aws-s3 Description: AWS S3 pricing in 2026: storage cost per GB, request fees, egress pricing, storage classes, and Raff Object Storage comparison. AWS S3 pricing in 2026 is built from several separate cost components: **storage, API requests, data retrieval, and data transfer**. For S3 Standard in US East, storage starts at **$0.023 per GB-month for the first 50 TB**. PUT, COPY, POST, and LIST requests are billed separately, GET requests are billed separately, and public internet egress is charged after AWS's shared monthly free-transfer allowance. Raff Object Storage uses a simpler model: **$7/month for the first 100 GB**, **1 TB of egress included**, **$0 API request fees**, $0.07/GB-month above the first 100 GB, and $0.01/GB for egress above the included 1 TB. That means AWS S3 can be cheaper for low-egress storage-only workloads, while Raff can be materially cheaper once public transfer and request volume become important. For example, 100 GB stored with no internet egress is about **$2.30/month on S3 Standard before requests** versus **$7 on Raff**. At 100 GB stored and 1 TB of internet egress, the same AWS example is about **$85.46/month before requests**, while Raff remains $7. This guide explains the actual AWS S3 cost model, storage-class pricing, request charges, egress, and how those costs compare with Raff Object Storage. ## AWS S3 pricing in 2026 Amazon S3 does not have one fixed monthly plan. Your bill depends on what storage class you use, how much data you store, how many requests your applications make, whether data is retrieved from colder classes, and where the data is transferred. For a typical S3 Standard workload, the most important pricing components are: 1. storage per GB-month; 2. PUT, COPY, POST, and LIST requests; 3. GET and other read requests; 4. data transfer out to the internet; 5. cross-region or special transfer paths; 6. optional features and management services; 7. retrieval charges for colder storage classes. That is why an S3 pricing estimate should model workload behavior rather than only multiply storage by a per-GB number. ## AWS S3 Standard storage pricing per GB For **S3 Standard in US East**, current storage pricing starts at: | Monthly S3 Standard storage | Price per GB-month | |---:|---:| | First 50 TB | $0.023 | | Next 450 TB | $0.022 | | Over 500 TB | $0.021 | At the first-tier rate: | Stored data | Approx. S3 Standard storage cost | |---:|---:| | 100 GB | $2.30/month | | 500 GB | $11.50/month | | 1 TB | about $23.55/month | | 10 TB | about $235.52/month | These figures are **storage only**. They do not include requests, public internet transfer, retrieval, replication, or other AWS services. This distinction matters because `AWS S3 pricing per GB` often sounds like one number, but storage cost is only one part of the bill. ## AWS S3 request pricing S3 Standard also meters API requests. In US East, current Standard request pricing includes approximately: | Request type | Price | |---|---:| | PUT, COPY, POST, LIST | $0.005 per 1,000 requests | | GET and other read requests | $0.0004 per 1,000 requests | Examples: | Monthly request volume | Approx. request cost | |---:|---:| | 1 million PUT-class requests | $5 | | 1 million GET requests | $0.40 | | 10 million GET requests | $4 | | 100 million GET requests | $40 | For many small workloads, request charges are modest. For workloads with millions or billions of object operations, request pricing becomes another cost dimension to forecast. Raff currently charges **$0 for object API requests**, so request volume does not add a separate billing line there. ## AWS S3 data transfer pricing Public internet transfer is where S3 costs can change quickly. AWS currently provides a shared **100 GB/month free data-transfer allowance** across eligible AWS services and Regions. After that, standard internet-transfer pricing applies. A typical U.S. schedule starts at: | Monthly public internet egress | Standard AWS transfer rate | |---:|---:| | First 10 TB after free allowance | $0.09/GB | | Next 40 TB | $0.085/GB | | Next 100 TB | $0.07/GB | | Above 150 TB | $0.05/GB | Actual transfer charges can differ when traffic uses CloudFront, same-region AWS paths, private endpoints, cross-region architectures, accelerated transfer, negotiated enterprise pricing, or other AWS services. For a simplified S3 Standard example using 1 TB = 1,024 GB and assuming the full 100 GB free-transfer allowance is available: | Internet egress | Approx. AWS transfer cost before storage/requests | |---:|---:| | 1 TB | about $83.16 | | 5 TB | about $451.80 | | 10 TB | about $912.60 | | 50 TB | about $4,394.70 | Raff includes **1 TB of egress** in its $7 base Object Storage plan and charges **$0.01/GB above 1 TB**. ## AWS S3 storage-class pricing One of AWS S3's biggest advantages is its range of storage classes. Teams can trade access frequency, retrieval behavior, minimum storage duration, resilience model, and price against one another. Common classes include: - S3 Standard; - S3 Intelligent-Tiering; - S3 Standard-Infrequent Access; - S3 One Zone-Infrequent Access; - S3 Express One Zone; - S3 Glacier Instant Retrieval; - S3 Glacier Flexible Retrieval; - S3 Glacier Deep Archive. Cold and archive classes can have much lower storage prices than S3 Standard, but may introduce retrieval charges, minimum storage durations, delayed access, or different availability characteristics. That flexibility is a real AWS advantage. If the workload has predictable hot, warm, and archival tiers, S3 can optimize them independently. Raff intentionally uses a simpler general-purpose object-storage model rather than reproducing AWS's full storage-class matrix. ## AWS S3 pricing calculator: what to include A realistic AWS S3 cost estimate should include more than stored GB. Before comparing providers, model: 1. average stored GB or TB; 2. chosen S3 storage class; 3. monthly PUT/LIST request volume; 4. monthly GET request volume; 5. retrieval volume from colder storage classes; 6. public internet egress; 7. cross-region transfer; 8. replication; 9. lifecycle transitions; 10. versioning growth; 11. Object Lock retention; 12. CloudFront or other delivery architecture; 13. data-processing or analytics services that read from S3. This is also why two companies storing the same 1 TB of data can receive very different S3 bills. ## AWS S3 vs Raff pricing Raff Object Storage uses a base bundle plus simple overages. AWS S3 uses component pricing. The table below uses **S3 Standard in US East**, the shared 100 GB monthly internet-transfer allowance, and the standard public-transfer schedule. AWS request charges are excluded from scenario totals and shown separately above. | Workload | Raff Object Storage | AWS S3 Standard | What it means | |---|---:|---:|---| | 100 GB stored, 0 GB internet egress | $7.00/month | about $2.30/month before requests | AWS is cheaper for storage-only use | | 100 GB stored, 1 TB internet egress | $7.00/month | about $85.46/month before requests | Raff's included egress changes the economics | | 500 GB stored, 1 TB internet egress | $35.00/month | about $94.66/month before requests | Raff remains lower in this transfer-heavy example | | 1 TB stored, 1 TB internet egress | about $71.68/month | about $106.71/month before requests | Both storage and transfer matter | | 1 TB stored, 5 TB internet egress | about $112.64/month | about $475.35/month before requests | Public transfer dominates the AWS example | These examples do not imply identical durability architecture, region coverage, storage classes, governance features, or service parity. They compare cost for general-purpose object storage workloads. ## When AWS S3 is cheaper AWS S3 is often cheaper when: - the workload stores data but sends little of it to the public internet; - S3 Standard's $0.023/GB-month storage rate is the main cost driver; - colder data can move into IA or Glacier classes; - data stays inside AWS and avoids standard public egress; - the application already depends heavily on AWS services; - storage-class optimization is more important than billing simplicity. At 100 GB stored with no public egress, S3 Standard costs about $2.30/month before requests, which is below Raff's $7 base plan. ## When Raff Object Storage is cheaper Raff becomes more attractive when: - public internet egress is high or unpredictable; - the workload regularly downloads backups, exports, media, or static assets; - API request volume is large enough to create another AWS cost line; - the team values one simple storage model over multiple classes and retrieval rules; - the application already runs on Raff infrastructure. Raff's current Object Storage plan includes **100 GB of storage, 1 TB egress, and API requests for $7/month**. Storage above 100 GB is $0.07/GB-month and egress above 1 TB is $0.01/GB. :::cta Create a Bucket Now Create S3-compatible object storage with 100 GB and 1 TB egress included. ::: ## AWS S3 vs Raff feature comparison Pricing is only one side of the decision. AWS S3 has a much deeper feature and governance surface. | Feature | AWS S3 | Raff Object Storage | |---|---|---| | API | Native Amazon S3 API | S3-compatible | | S3 Standard storage | $0.023/GB-month first 50 TB in US East | $7 first 100 GB; $0.07/GB-month above | | Included internet egress | 100 GB shared AWS allowance | 1 TB included | | Request fees | Metered by request type | $0 | | Storage classes | Many | One general-purpose model | | Bucket versioning | Yes | Not currently native | | Lifecycle rules | Yes | Not currently native | | Object Lock | Yes | Not currently native | | Same-region replication | Yes | No equivalent native feature | | Cross-region replication | Yes | No equivalent native feature | | Presigned URLs | Yes | Yes | | Multipart uploads | Yes | Yes | | Global regions | Broad AWS global footprint | Current public region: us-east | AWS S3 clearly wins when versioning, lifecycle automation, immutable retention, cross-region replication, archive classes, or deep AWS integration are requirements. Raff wins when the workload primarily needs standard S3-compatible object operations with a smaller, easier-to-predict billing surface. ## S3 compatibility and migration Raff Object Storage supports common S3-compatible workflows through `s3.raffusercloud.com`. Common tools include: - AWS CLI; - Boto3 and other AWS SDKs; - rclone; - s3cmd; - Cyberduck; - multipart uploads; - presigned URLs; - bucket policies; - ACLs. S3 compatibility does **not** mean full AWS feature parity. Applications that rely on IAM role assumptions, S3 event notifications, lifecycle transitions, Object Lock, access points, cross-region replication, Storage Lens, or AWS-specific analytics integrations need additional migration work. ## AWS S3 durability and availability AWS S3 publishes unusually specific durability targets. S3 Standard is designed for **99.999999999% durability** and **99.99% availability**, with redundant storage across at least three Availability Zones. Raff publishes a **99.9% platform SLA** but does not publish an equivalent eleven-nines Object Storage durability target. If procurement requires a documented object-durability design, AWS has the stronger published position. That difference should be treated as a real architecture consideration rather than hidden behind price comparison. ## AWS S3 regions and replication AWS S3 is available across AWS's global region footprint and supports same-region and cross-region replication. Raff currently exposes Object Storage from `us-east`. That can fit workloads whose users, recovery design, and data-placement requirements are compatible with that geography, but AWS is the stronger choice when multi-region object placement or specific data residency is required. ## When you should choose AWS S3 over Raff Choose AWS S3 when: - you need versioning, lifecycle policies, Object Lock, replication, or advanced storage classes; - you need global region choice or multi-region data placement; - your application already depends on IAM, Lambda, CloudFront, Athena, Glue, EventBridge, or other AWS-native services; - archive economics matter more than a simple single storage class; - procurement requires AWS's published durability model; - most traffic stays inside AWS and public egress is low. AWS S3's main advantage is not the headline storage rate alone. It is the combination of global architecture, data-governance controls, storage classes, and ecosystem depth. ## When you should choose Raff over AWS S3 Choose Raff when: - your workload needs straightforward S3-compatible buckets; - public egress is meaningful or unpredictable; - you want 1 TB egress bundled into the base plan; - you want $0 API request fees; - the application already runs on Raff compute; - you prefer a smaller billing surface over AWS's storage-class and request matrix. For uploads, media, exports, backups, static assets, build artifacts, and ordinary application-object storage, the simpler pricing model can be easier to forecast. ## Migrating from AWS S3 to Raff 1. **Inventory the S3 estate.** Record bucket names, regions, object counts, sizes, storage classes, versioning, lifecycle policies, Object Lock, replication, encryption, bucket policies, IAM dependencies, and event integrations. 2. **Check feature dependencies.** Identify AWS-specific features that do not map directly to Raff. 3. **Provision Raff Object Storage.** Create the target bucket and credentials and confirm `us-east` satisfies the workload. 4. **Transfer objects.** Use rclone, AWS CLI with the Raff endpoint, an SDK migration, or another verified copy process. 5. **Verify object integrity.** Compare object counts and checksums and test uploads, downloads, multipart operations, presigned URLs, policies, and application reads/writes. 6. **Cut over application endpoints.** Change the S3 endpoint only after validation. 7. **Keep AWS available through a rollback window.** Remove old buckets, replication rules, IAM policies, and other AWS resources only after production verification. Version history, lifecycle rules, Glacier classes, Object Lock, replication, and AWS event integrations do not move as ordinary object data. They must be redesigned or replaced deliberately. ## Frequently asked questions ### How much does AWS S3 cost per GB? S3 Standard in US East currently starts at $0.023 per GB-month for the first 50 TB. That is storage-only pricing; API requests, retrieval, and internet transfer can add separate charges. ### How much does 1 TB of AWS S3 cost per month? At the first-tier S3 Standard storage rate, 1 TB is roughly $23.55/month using 1 TB = 1,024 GB. Public egress, API requests, and other services can increase the total. ### Is AWS S3 expensive? It depends on workload behavior. S3 Standard storage itself can be inexpensive, but public egress, request volume, retrieval, replication, and other services can materially increase the monthly bill. ### Does AWS S3 charge for requests? Yes. S3 Standard meters request types separately. PUT, COPY, POST, and LIST operations are currently about $0.005 per 1,000 requests, while GET-class requests are about $0.0004 per 1,000 in US East. ### Does AWS S3 charge for bandwidth? Yes. AWS provides a shared monthly free-transfer allowance, then charges public internet egress using tiered rates. The first standard U.S. tier is currently $0.09/GB after the allowance. ### Is Raff cheaper than AWS S3? It depends on the workload. At 100 GB stored with no internet egress, S3 Standard is about $2.30/month before requests versus Raff at $7. At 100 GB stored and 1 TB of public egress, Raff remains $7 while the AWS example is about $85.46 before requests. ### What is the cheapest S3 storage class? AWS offers multiple lower-cost archive and infrequent-access classes, including Glacier options. The cheapest class depends on access frequency, retrieval needs, minimum storage duration, and recovery-time requirements. ### Does Raff support the S3 API? Raff provides S3-compatible Object Storage and works with common S3 tooling such as AWS CLI, SDKs, rclone, s3cmd, multipart upload, and presigned URLs. It does not reproduce every AWS S3 feature. ## Sources - [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/) - [Amazon S3 product overview](https://aws.amazon.com/s3/) - [Raff Object Storage](/products/object-storage) - [S3-Compatible Object Storage: Use Cases for Developers](/learn/guides/s3-compatible-object-storage-use-cases-for-developers) - Pricing verified: 2026-08-28 ## Conclusion: AWS S3 pricing vs Raff AWS S3 pricing starts with inexpensive per-GB storage, but the complete bill depends on storage class, API requests, retrieval, and transfer. S3 Standard in US East begins at $0.023/GB-month and gives teams access to AWS's deep storage-class, replication, lifecycle, Object Lock, region, and ecosystem capabilities. Raff Object Storage takes the opposite approach: $7/month includes 100 GB, 1 TB egress, and API requests, with simple storage and transfer overages. Choose **AWS S3** when global architecture, advanced governance, archive classes, replication, or AWS-native integrations matter most. Choose **Raff** when standard S3-compatible workflows and predictable transfer/request economics are the stronger priority. --- ## Windows Server articles ### Windows Server 2016 End of Life: Dates, Costs, and Options URL: https://rafftechnologies.com/windows-server/windows-server-2016-end-of-life Description: Windows Server 2016 support ends January 12, 2027. What the deadline means in practice, what Extended Security Updates really cost, and your three exit options. ## In short Windows Server 2016 reaches end of life on **January 12, 2027**, when Microsoft stops shipping free security updates and technical support. Mainstream support already ended back in January 2022. You have three realistic options: pay for Extended Security Updates (roughly $5,614 per server over three years), upgrade the OS in place, or migrate the workload to Windows Server 2025. At Raff we recommend planning the move now: a typical small-business migration takes 2 to 6 weeks end to end, and every EOL wave produces a Q4 rush that makes the last months harder than they need to be. ## Windows Server 2016 lifecycle: The exact dates Windows Server 2016 follows Microsoft's Fixed Lifecycle Policy: five years of mainstream support, five years of extended support, then a paid Extended Security Updates (ESU) window for customers who cannot move in time. | Milestone | Date | What stops | |---|---|---| | Release | October 15, 2016 | | | Mainstream support ended | January 11, 2022 | New features, design changes, non-security fixes | | **Extended support ends (end of life)** | **January 12, 2027** | Free security updates, technical support | | Extended Security Updates end | January 12, 2030 | The paid safety net; after this, nothing | Both support dates come from the [Microsoft Lifecycle page for Windows Server 2016](https://learn.microsoft.com/en-us/lifecycle/products/windows-server-2016). Microsoft confirmed the ESU program for Server 2016 in a [February 25, 2026 announcement](https://www.microsoft.com/en-us/windows-server/blog/2026/02/25/planning-ahead-for-windows-server-2016-end-of-support/), giving stragglers a paid bridge of up to three years. Put plainly: Windows Server 2016 leaves extended support on January 12, 2027, and even the paid ESU program runs out on January 12, 2030. ## What actually happens after January 12, 2027 Your servers keep booting. Nothing turns off. The risk builds quietly instead: - **Every new vulnerability becomes permanent.** Windows Server CVEs keep being discovered after a version leaves support; without patches, each one is an open door that never closes. Attackers specifically scan for end-of-life systems because the exploit list only grows. - **Compliance frameworks stop cooperating.** PCI DSS, HIPAA, SOC 2, and ISO 27001 audits all expect production systems on a vendor-supported OS. An unsupported domain controller or file server is a finding, not a footnote. - **Cyber insurance gets harder.** Renewal questionnaires increasingly ask for OS lifecycle status. Running an unsupported server can raise premiums or void claims after an incident. - **Software support erodes.** Backup agents, EDR tools, and line-of-business vendors certify against supported platforms. Expect "upgrade your OS first" answers to support tickets. One more deadline that surprises people: **SQL Server 2016 already left extended support on July 14, 2026** ([Microsoft Lifecycle](https://learn.microsoft.com/en-us/lifecycle/products/sql-server-2016)). A 2016-era box running SQL Server 2016 is unsupported at the database layer today, before the OS deadline even lands. ## Your three options compared | Option | 3-year cost per server | Downtime | Makes sense when | |---|---|---|---| | Extended Security Updates | ~$5,614 (Standard) plus existing hardware costs | None | A hard blocker (legacy app) prevents any move | | In-place upgrade | Licence cost, plus upgrade risk | Hours, with a risky rollback | Hardware is healthy and roles are simple | | Migrate to Server 2025 on a VM | From ~$1,965 all-in (4 vCPU / 8 GB, licence included) | A planned cutover window | Aging hardware, most small-business setups | ### Option 1: Pay for Extended Security Updates ESU delivers security patches only: no bug fixes, no feature updates, no technical support. Microsoft prices ESU as a percentage of the licence cost that roughly doubles each year. For Windows Server 2016 Standard (about $1,069 list), that works out to roughly $802 in year one, $1,604 in year two, and $3,208 in year three: about **$5,614 per server** across the full window, on top of the hardware you already run. Two purchasing details catch teams off guard. First, ESU is not automatic: you buy it through Microsoft's volume licensing channels or a Cloud Solution Provider, per server, per year. Second, in the previous ESU programs for Server 2008 and 2012 the coverage was cumulative, meaning a team that joined in year two also paid for the year they skipped. Budget for Server 2016 as if the same rule applies. ESU buys time, not a future. It is the right call only when a critical dependency genuinely cannot move yet, and even then the money usually funds the migration you were postponing. ### Option 2: Upgrade in place Microsoft documents supported in-place upgrade paths from Server 2016 to newer versions in its [Windows Server upgrade overview](https://learn.microsoft.com/en-us/windows-server/get-started/upgrade-overview). An in-place upgrade keeps your hardware and installed roles, which is also its weakness: the 9-year-old disks, the accumulated configuration drift, and the applications nobody dares touch all come along for the ride. Rollback means restoring from backup. If the hardware is due for replacement anyway, upgrading in place solves the software deadline while keeping the hardware risk. ### Option 3: Migrate to Windows Server 2025 (what we recommend) A clean Windows Server 2025 build on current hardware sidesteps both problems: the OS is supported until November 2034, and the underlying compute is no longer your capital expense. On Raff, Windows Server 2025 VMs run on dedicated vCPU with NVMe storage: | Plan | Compute | With Standard licence ($15/mo SPLA) | |---|---|---| | 2 vCPU / 4 GB / 80 GB NVMe | $21.99/mo | $36.99/mo | | 4 vCPU / 8 GB / 120 GB NVMe | $39.59/mo | $54.59/mo | | 8 vCPU / 16 GB / 180 GB NVMe | $70.49/mo | $85.49/mo | Every Windows VM includes a 6-month Windows Server evaluation licence at no extra cost, so you can build and test the destination server before paying for a licence at all. After that it is $15.00/month per instance through Raff's SPLA program, or bring your own licence. Current prices are always on the [Windows VM page](/products/windows-vm). The full technical walkthrough (AD DS promotion, FSMO transfer, Storage Migration Service, SQL Server move, cutover and rollback) is in our [Windows Server 2016 to 2025 migration guide](/windows-server/migrate-windows-server-2016-to-2025). For a lighter planning pass, start with the [small-business migration checklist](/windows-server/windows-server-migration-checklist-small-business). ## The cost math: ESU vs migrating Three years of Server 2016 ESU costs about $5,614 per server; three years of a Raff 4 vCPU / 8 GB Windows Server 2025 VM costs about $1,965, licence included. The ESU path also leaves you exactly where you started, but three years closer to the 2030 hard stop and still on the same hardware. The migration path ends with a current OS, supported until 2034, on infrastructure that someone else patches, powers, and replaces. | | ESU route (3 years) | Raff migration route (3 years) | |---|---|---| | Software cost | ~$5,614 ESU | ~$1,965 total (36 x $54.59, compute + licence) | | Hardware cost | Your existing server, power, and replacement risk | Included | | End state in 2030 | Unsupported OS, no more ESU available | Windows Server 2025, supported until Nov 2034 | :::cta deploy Deploy your Server 2025 destination from $10.99/month plus the $15 Windows licence. ::: ## Which path fits your setup - **A 5 to 50 person office running a 2016 file server, QuickBooks, or Sage:** Migrate. These workloads move cleanly to a 2 vCPU / 4 GB or 4 vCPU / 8 GB Windows VM, and the office stops depending on one aging box in a closet. Start with the [migration checklist](/windows-server/windows-server-migration-checklist-small-business). - **A DBA with SQL Server 2016 on the same host:** Move the database first; it is already out of support. The [SQL Server migration guide](/windows-server/sql-server-migration-to-windows-vps) compares the methods, then the OS move follows. - **An MSP managing client fleets:** Triage by exposure. Internet-facing and compliance-scoped 2016 servers migrate first; isolated single-role boxes can ride ESU year one while the queue clears. The per-server ESU math above makes the client conversation straightforward. - **A workload already virtualized on Hyper-V or VMware:** The move is an export, convert, and import rather than a rebuild, which shortens the cutover window considerably. The same January 2027 date applies either way. - **A legacy application certified only for Server 2016:** ESU, isolation, and a dated exit plan. Press the vendor for a supported-platform roadmap; three years passes faster than a rewrite. ## What to migrate first: Roles in priority order When one 2016 box carries several roles, move them in this order: 1. **File shares first.** Lowest risk, easiest rollback, and Storage Migration Service preserves paths and permissions. A failed test costs nothing; the old shares stay live until cutover. 2. **Application servers second.** QuickBooks, Sage, ERP, and line-of-business apps should be reinstalled clean on the new server rather than copied, so nine years of DLL drift stays behind. 3. **SQL Server third.** Backup and restore onto a current SQL Server version on the new machine, verify the application against it, then repoint connection strings at cutover. 4. **Domain controllers last.** Never upgrade the only DC. Promote a new Server 2025 DC alongside the old one, let replication settle, transfer the FSMO roles, and only then demote the 2016 controller. Each step is expanded with the exact commands in the [migration guide](/windows-server/migrate-windows-server-2016-to-2025). ## When to start: Working back from January 2027 Counting back from the deadline, a realistic small-business timeline looks like this: 1. **Now until September 2026: inventory.** List every 2016 instance, what runs on it (AD, file shares, SQL Server, line-of-business apps), and who owns each dependency. 2. **October to November 2026: build and test.** Deploy the Windows Server 2025 destination, move a copy of the data, and test the applications against it. The 6-month evaluation licence covers this entire phase. 3. **December 2026: cutover.** Migrate roles and data with a rollback plan, then run both systems in parallel briefly. 4. **Buffer before January 12, 2027.** Leave at least a month of slack. Every EOL cycle ends with a December rush of migrations that could have happened in October. ## What we recommend at Raff Windows Server 2025 is the default image for new Windows VMs on Raff, with 2022 and 2019 available for compatibility cases. We tested the full 2016-to-2025 path (AD DS install, role promotion, FSMO transfer, Storage Migration Service, SQL Server move) end to end on a Raff Windows Server 2025 VM in our us-east region, and that test is the basis of the migration guide linked throughout this article. Our standing advice for 2016 holdouts is simple: use the free 6-month evaluation licence to build the destination now, prove the applications on it, and let the January deadline pass as a non-event. ## Common mistakes - **Waiting for the next hardware refresh.** The refresh budget lands in 2028, the OS deadline lands in January 2027. Decouple them: the OS problem is solvable this quarter without touching capital budgets. - **Migrating the OS and forgetting the database.** SQL Server 2016 has its own, earlier deadline (July 14, 2026). Teams that only track the Windows date ship a supported OS running an unsupported database. - **Buying ESU for the whole fleet.** ESU makes sense for the two servers with hard blockers, not for the eight that could migrate this quarter. Triage before you purchase; the per-server price doubles yearly. - **Skipping the parallel-run window.** Cutting over without running old and new side by side turns every missed dependency into an outage. The 6-month evaluation licence exists precisely so the parallel phase costs nothing extra. - **Forgetting access licensing on the destination.** If users connect over RDP beyond two admin sessions, the new server needs RDS licensing just like the old one did. Plan RDS User SALs ($8.00/month per user on Raff) into the budget, not as a surprise after cutover. ## What's next - [How to migrate Windows Server 2016 to 2025](/windows-server/migrate-windows-server-2016-to-2025): the tested step-by-step path - [Windows Server end of life dates for every version](/windows-server/windows-server-end-of-life-dates): where 2019, 2022, and 2025 stand - [Windows Server version comparison](/windows-server/windows-server-version-comparison): choosing the destination version ## Sources - Microsoft Lifecycle: [Windows Server 2016](https://learn.microsoft.com/en-us/lifecycle/products/windows-server-2016) - Microsoft: [Planning ahead for Windows Server 2016 end of support](https://www.microsoft.com/en-us/windows-server/blog/2026/02/25/planning-ahead-for-windows-server-2016-end-of-support/) (February 25, 2026) - Microsoft Learn: [Windows Server upgrade overview](https://learn.microsoft.com/en-us/windows-server/get-started/upgrade-overview) - Microsoft Lifecycle: [SQL Server 2016](https://learn.microsoft.com/en-us/lifecycle/products/sql-server-2016) - Date last verified: 2026-08-05 --- ### Remote Desktop Server on a Windows VPS: Setup, Security, and Costs URL: https://rafftechnologies.com/windows-server/remote-desktop-server-for-business Description: What a remote desktop server is, how to set one up on a Windows VPS, the access models to choose from, and what hosted remote desktop really costs. A remote desktop server helps businesses give employees access to a shared Windows environment, Windows applications, files, and internal tools from different locations. A Windows VPS can work as the cloud-hosted Windows Server foundation for this model, but user count, Remote Desktop Services licensing, RD Gateway, security, backups, application support, and sizing should be planned before production. Raff Technologies provides Windows VMs for teams that need Remote Desktop access, business app hosting, and cloud Windows Server infrastructure. Remote Desktop is not only a convenience feature. For many small businesses, it becomes the way employees reach accounting software, tax tools, ERP systems, inventory apps, Microsoft Access databases, shared folders, reports, and legacy Windows applications. That is why a business remote desktop server should not be planned like a quick admin login. It should be planned like a production work environment: who connects, what they run, how they authenticate, how data is backed up, how sessions perform, and what happens if the server goes down. ## Quick verdict: When a remote desktop server fits a business Use this table before choosing a remote desktop server. | Business situation | Remote desktop server fit | Why | |---|---|---| | Employees need access to Windows apps from outside the office | Strong fit | Users can connect to one hosted Windows environment. | | Multiple users need the same business app | Strong fit after app support check | The app can run centrally where supported. | | Business is replacing an office server | Strong fit | Remote access can be built into the new cloud model. | | Team has branch offices or remote employees | Strong fit | Users can connect from different locations. | | Users need shared files inside the Windows environment | Good fit | Files can stay close to apps inside the server. | | Business only needs simple document sharing | Depends | SaaS file collaboration may be simpler. | | Users run heavy graphics or media workloads | Depends | Test performance before production. | | App vendor does not support RDS or multi-user use | Risky | Vendor support and licensing must be checked. | | High availability is mandatory | Not a single-server decision | Design redundancy, failover, and recovery architecture. | The best fit is a business that needs centralized Windows access for people, apps, files, and workflows. ## What a remote desktop server is A remote desktop server is a Windows Server environment that users connect to from another device. Instead of running everything on their local laptop or office PC, the user works inside a hosted Windows session. In business terms, this can support: | Use case | Example | |---|---| | Remote employee access | Staff connect from home or branch offices | | Business app hosting | Accounting, tax, ERP, inventory, Access, legacy apps | | Shared Windows workspace | Users work in the same controlled Windows environment | | Admin access | IT or MSP connects to manage the server | | Office server replacement | Old server moves into a cloud-hosted Windows environment | | Multi-location access | Different offices use the same apps and data | | File access | Shared folders are accessed inside the remote session | | SQL-backed apps | App and database tools run in one controlled environment | The goal is not just “open RDP.” The goal is to give users a reliable way to work with the Windows tools the business depends on. ## RDP, RDS, RD Gateway, and Windows VPS are different Many buyers use “RDP server” to mean everything. That can create confusion. | Term | What it means | Business relevance | |---|---|---| | RDP | Remote Desktop Protocol, the connection protocol | Used to connect to Windows remotely | | Admin RDP | Limited administrator access to manage the server | Good for 1-2 admins | | RDS Session Host | Windows Server role for multiple user sessions | Relevant for staff desktop/app sessions | | RD Gateway | Secure gateway for RDS access over HTTPS | Useful for controlled remote access | | Windows VPS | Cloud-hosted Windows Server VM | Infrastructure foundation | | RemoteApp | Published app instead of full desktop | Useful when users only need specific apps | | VPN/private access | Private network access before connecting | Useful for controlled internal access | Microsoft describes Remote Desktop Services as a Windows Server platform for securely delivering virtualized applications, remote desktop access, and simplified remote access administration. That is the broader business model, not just one RDP connection. ## Remote desktop server vs regular Windows VPS A Windows VPS gives you the server. A remote desktop server is what you build and operate on top of it. | Area | Windows VPS | Business remote desktop server | |---|---|---| | Infrastructure | Cloud Windows Server VM | The foundation | | User model | Admin access by default | Staff sessions need planning | | Licensing | Windows Server environment | RDS CALs may apply | | Security | Firewall and access controls needed | Users, policies, gateway, monitoring | | Workload | General Windows server | Desktop/app sessions for people | | Backups | VM/data protection needed | User data and app data need recovery | | Support | Server-level support | User workflow and app support also matter | This is why the cheapest Windows VPS plan is not always the right remote desktop server plan. A business desktop workload needs enough CPU, RAM, storage, and access planning. ## Common business use cases ### Remote employees Remote employees may need access to a stable Windows environment even when they use different laptops or locations. Remote desktop can help when: | Need | Why it helps | |---|---| | Same Windows tools for every user | Users connect to one environment | | Company apps stay off personal devices | Data stays inside the remote session | | Branch and home users need access | Access path can be standardized | | Support team needs consistency | Easier to troubleshoot one hosted setup | The remote desktop server should still have clear policies for user accounts, passwords, file access, printer use, and offboarding. ### Accounting, tax, ERP, and inventory software Many business apps are Windows-based or expect a Windows Server environment. Remote desktop fits when: | Workload | Planning focus | |---|---| | Accounting software | Data files, printers, user access, backups | | Tax software | Seasonal users, client files, vendor support | | ERP/inventory | Database, reports, branch users, devices | | Microsoft Access | Split database, file paths, app/data proximity | | Legacy apps | Runtimes, dependencies, vendor support | | SQL-backed tools | SQL logins, jobs, connection strings, backups | Before production, confirm that the app vendor supports the deployment model. Some apps work well in RDS. Others have licensing or support limitations. ### Multi-location businesses A remote desktop server can simplify access for businesses with multiple offices. Instead of each location keeping its own server or app install, users connect to one Windows environment. This can reduce: | Problem | How central access helps | |---|---| | Different app versions | One managed app environment | | File duplication | Shared folders in one place | | VPN complexity | Controlled remote access model | | Support inconsistency | One server to document and manage | | Branch hardware dependency | Less reliance on one office server | Multi-location success still depends on internet quality, user count, app behavior, and backups. ### MSP-managed client environments MSPs can use remote desktop servers to standardize client access and support. Good MSP patterns include: | MSP need | Why remote desktop server helps | |---|---| | Repeatable client environments | Easier to document and support | | Client app hosting | Business apps run centrally | | Remote support | Admin access is controlled | | User onboarding/offboarding | Accounts and groups can be standardized | | Client separation | Each client can have its own environment | | Migration projects | Test, cutover, and rollback can be planned | Each client environment should have its own access model, backup plan, support owner, and documentation. ## Direct RDP vs RDS Session Host vs RD Gateway The right access model depends on who connects and why. | Model | Best fit | Watch out for | |---|---|---| | Direct admin RDP | One or two admins | Do not broadly expose to the internet | | RDS Session Host | Staff desktop/app sessions | RDS CALs, profiles, performance, app support | | RD Gateway | Controlled remote access | Requires configuration and certificate planning | | VPN + RDP/RDS | Private access first | VPN management and user support | | RemoteApp | Users need only specific apps | App compatibility and user experience | Microsoft’s RD Gateway documentation describes RD Gateway as enabling secure, encrypted connections to RDS resources over the internet without requiring VPN access. For businesses with remote users, that can be a cleaner access layer than broad direct RDP exposure. ## How to set up a remote desktop server The build order matters less than doing every step before real users depend on the server: 1. **Deploy the Windows Server VM.** Pick the size from the sizing table below; see [connecting via RDP](/windows-server/connect-to-windows-vps-via-rdp) for the first login. 2. **Restrict RDP immediately.** Limit source IPs in [Windows Firewall](/windows-server/configure-windows-firewall) before anything else. 3. **Create named user accounts.** Separate admin accounts from daily users; no shared logins. 4. **Choose the access model.** Admin-only RDP, [RDS Session Host](/windows-server/multi-user-rdp-vs-rds) for staff sessions, or [RD Gateway](/windows-server/remote-desktop-gateway-vs-direct-rdp) as the controlled entry point. 5. **Install the business applications** and confirm vendor support for server or multi-session use. 6. **Configure [backups](/windows-server/windows-vps-backup-strategy-small-business), run one restore test, then connect real users** from their real locations. A remote desktop server is production infrastructure from day one; the checklist at the end of this article covers the full pre-launch review. ## RDS licensing: What businesses should know Remote Desktop licensing is one of the most important planning areas. Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs a Remote Desktop Services Client Access License. Microsoft also supports per-user and per-device RDS CAL models. | Scenario | Licensing implication | |---|---| | One or two admins connect for server management | Different from staff desktop usage | | Employees use Windows desktop sessions daily | RDS CAL planning is usually required | | Shared office devices connect to RDS | Per-device licensing may be considered | | Named employees connect from multiple devices | Per-user licensing may be considered | | MSP manages client users | Track users/devices per client environment | Do not confuse full administrator RDP access with a licensed multi-user business desktop environment. ## Sizing a remote desktop server Remote desktop server sizing depends on concurrent users and workload type, not just total employee count. Use this starting point: | Workload | Starting size | When to move up | |---|---:|---| | 1-2 admin users | 2 vCPU / 4 GB RAM | If apps or reports run on the server | | 3 light RDP users | 4 vCPU / 8 GB RAM | If users browse, open PDFs, or use Office apps | | 3 business app users | 4 vCPU / 16 GB RAM | If accounting, tax, Access, or legacy apps run daily | | 5 active users | 4 vCPU / 16 GB RAM | If users stay logged in for long sessions | | 10 active users | 8 vCPU / 32 GB RAM | If the server is a shared workplace | | RDS plus SQL/ERP workload | 8-16 vCPU / 32-64 GB RAM | Consider splitting app/database roles | Plan storage for user profiles, app data, downloads, shared folders, database files, reports, exports, logs, and backups. :::cta View Pricing Compare Raff Windows VM plans and monthly costs for Remote Desktop users. ::: ## Performance planning for Remote Desktop users Remote Desktop performance depends on the whole path, not only the server. Check: | Area | Why it matters | |---|---| | CPU | App launch, reports, browser activity | | RAM | User sessions, app memory, profiles | | Disk | Logins, file access, app data, databases | | Network latency | Mouse/keyboard responsiveness | | Packet loss | Freezes and disconnects | | Client device | Display settings, local resources | | Printers | Redirection and driver behavior | | App behavior | Some apps are not RDS-friendly | | User habits | Many tabs, PDFs, spreadsheets, idle sessions | If one branch reports slowness and others do not, the issue may be local internet, Wi-Fi, firewall, DNS, or endpoint configuration. ## Security planning before users connect A business remote desktop server can hold sensitive files, financial data, client records, application access, and user sessions. Security should be designed before production. Minimum planning: | Security area | Recommendation | |---|---| | User accounts | Named users, not shared logins | | Admin access | Separate admin accounts from daily users | | RDP exposure | Avoid broad direct RDP exposure | | RD Gateway/VPN | Use controlled access where appropriate | | Firewall | Restrict allowed sources and ports | | Passwords | Strong credentials and offboarding process | | Patching | Schedule Windows and app updates | | Backups | Protect against mistakes and ransomware | | Logs | Review failed logins and access events | | Permissions | Use groups and least privilege | Microsoft provides Windows Server security baseline guidance and Security Compliance Toolkit resources for recommended security configuration baselines. Small businesses can use those as a starting point, but real security also depends on operations and user discipline. ## Backups for remote desktop servers A remote desktop server often contains app data, user profiles, files, reports, and configuration. Backups should be in place before production users connect. Plan: | Backup layer | Purpose | |---|---| | VM backup | Recover the whole Windows server | | Snapshot before changes | Roll back before updates or migrations | | User profile backup | Recover user settings and workspace data | | File-level backup | Restore shared folders and documents | | App/database backup | Protect SQL Server, ERP, accounting, or Access data | | Off-server copy | Reduce account, ransomware, and VM failure risk | | Restore test | Prove recovery works | Do not assume that cloud hosting replaces backups. A remote desktop server still needs a recovery plan. ## Pricing: What affects remote desktop server cost Remote desktop server cost depends on more than the VM plan. | Cost area | What affects it | |---|---| | CPU and RAM | Active users, apps, reports, browsers | | Storage | Profiles, files, databases, logs, growth | | Windows licensing | Provider model and Windows Server terms | | RDS CALs | Staff desktop sessions | | Backups | Size, frequency, retention | | Snapshots | Change protection and rollback needs | | SQL Server | Edition and licensing if used | | Migration | Apps, users, files, data, cutover | | Support | Windows, RDS, app, and user troubleshooting | | Security | Access controls, monitoring, hardening | A lower monthly server price may not be cheaper if users lose productivity because the environment is under-sized or poorly protected. ## When not to use a remote desktop server Remote Desktop is useful, but it is not always the right tool. Pause when: | Situation | Better next step | |---|---| | Users only need browser apps | Use the web app directly | | Collaboration is mainly documents | Consider SaaS collaboration tools | | App vendor does not support RDS | Ask vendor for supported hosting model | | Heavy graphics/media work is required | Test first or consider different architecture | | Internet is unreliable | Fix connectivity or design fallback | | High availability is required | Plan redundancy and failover | | Local hardware devices are critical | Test device workflow first | | Licensing is unclear | Resolve licensing before production | Do not use Remote Desktop to force a bad application architecture into production. ## Migration path: From office PC or server to remote desktop server Many remote desktop projects start with an old office PC or local server. A safe migration path: 1. Inventory apps, users, files, databases, and devices. 2. Confirm app vendor support for Windows Server/RDS use. 3. Choose the Windows VPS size. 4. Build and secure the server. 5. Configure RDP/RDS/RD Gateway/VPN access model. 6. Install apps and dependencies. 7. Copy non-production data first. 8. Test users from real locations. 9. Configure backups and run restore test. 10. Schedule cutover. 11. Move users. 12. Keep rollback ready. 13. Monitor performance and support tickets. The goal is not to connect users quickly. The goal is to make the remote desktop environment stable enough for daily work. ## How Raff fits remote desktop server hosting Raff fits businesses that need hosted remote desktop infrastructure: a cloud Windows VM for Remote Desktop users, Windows business apps, shared workloads, office server replacement, migration projects, multi-location access, MSP client environments, and backup-aware Windows infrastructure. Raff Windows VMs provide the infrastructure layer. The buyer or MSP still needs to plan RDS licensing, access model, user count, business app support, backups, security, monitoring, and documentation. Raff is not a replacement for application vendor support, RDS CAL planning, SQL Server licensing, or internal IT process ownership. The clean model is: use Raff for the Windows VM foundation, then design the Remote Desktop workload correctly. :::cta Deploy Windows Now Deploy a Raff Windows VM for your remote desktop workload: from $10.99/month plus the $15 Windows licence. ::: ## Final remote desktop server checklist Before production, confirm: | Check | Done | |---|---| | Number of active users estimated | ☐ | | User workflows documented | ☐ | | Business apps listed | ☐ | | App vendor support checked | ☐ | | RDS CAL requirements reviewed | ☐ | | Direct RDP/RDS/RD Gateway model chosen | ☐ | | CPU/RAM/storage sized | ☐ | | User profile plan defined | ☐ | | Firewall rules planned | ☐ | | Backups configured | ☐ | | Restore test completed | ☐ | | Security baseline reviewed | ☐ | | Printers and devices tested | ☐ | | Real users tested from real locations | ☐ | | Support owner assigned | ☐ | | Rollback plan documented | ☐ | If any line is unclear, pause before users depend on the server. ## What's next - Explore [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) when you are ready to compare Windows VM options. - Review [Raff pricing](https://rafftechnologies.com/pricing) before choosing CPU, RAM, storage, and monthly cost. - Read [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) for the broader SMB infrastructure guide. - Read [Windows VPS Pricing Explained](https://rafftechnologies.com/windows-server/windows-vps-pricing-explained) to understand cost drivers. - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing a plan. - Read [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) before choosing an access model. - Read [RDS CAL Licensing on Windows Server](https://rafftechnologies.com/windows-server/rds-cal-licensing-guide) before rolling out staff sessions. - Read [RDP Performance Tuning](https://rafftechnologies.com/windows-server/rdp-performance-tuning) if users report slowness. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before storing production data. ## Sources - Microsoft Learn — [Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [Deploy Remote Desktop Gateway role for Remote Desktop Services](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remote-desktop-gateway-role) - Microsoft Learn — [Remote Desktop clients feature comparison](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-client-feature-comparison) - Microsoft Learn — [Security baselines guide](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/windows-security-baselines) - Microsoft Learn — [Microsoft Security Compliance Toolkit](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) - Raff — [Windows Server Hub](https://rafftechnologies.com/windows-server) --- ### RDP VPS: Using a Windows VPS for Remote Desktop URL: https://rafftechnologies.com/windows-server/windows-vps-for-remote-desktop Description: What an RDP VPS is, when a Windows VPS with RDP fits a small team, and how to plan sizing, security, licensing, and performance before users connect. An RDP VPS, a Windows VPS accessed over Remote Desktop, can be a practical remote desktop server when a small team needs secure access to Windows software, files, admin tools, or business applications from anywhere. Use normal admin RDP for server administration only. Use Remote Desktop Services with proper RDS CAL licensing when multiple users need their own desktop sessions for daily work. ## TL;DR * Use a Windows VPS for Remote Desktop when your team needs a cloud-hosted Windows environment instead of an office PC or local server. * The default RDP access model is for administration, not full multi-user desktop hosting. * If several employees need to work inside the server at the same time, plan for Remote Desktop Services and RDS CALs. * Performance depends on user count, application load, CPU, RAM, storage, network quality, and display settings. * Security matters because RDP is a high-value access path. Plan firewall rules, strong credentials, updates, backups, and monitoring before production. ## What an RDP VPS is and how it works Remote Desktop on a Windows VPS means connecting to a cloud-hosted Windows Server through Remote Desktop Protocol, usually from a local Windows, macOS, Linux, iOS, or Android device. ![Remote Desktop session connected to a Raff Windows VPS showing a Windows Server desktop for small business remote access.](https://raff-images.s3.raffusercloud.com/windows_vps_remote_desktop_session_webp_b57b683f60.png) The Windows VPS runs the desktop environment and applications. The user’s local device becomes the screen, keyboard, mouse, and audio endpoint. A simple model looks like this: ```text User device ↓ Remote Desktop client ↓ Windows VPS public IP or secured access path ↓ Windows Server session ↓ Business software, files, browser, admin tools, or server roles ``` This model is useful when the work needs to happen inside a Windows Server environment. Examples include: * Remote access to business software * Accounting tools * ERP clients * Admin dashboards * Browser-based internal tools * SQL Server tools * IIS administration * PowerShell administration * MetaTrader or other Windows-only software * Shared operational desktops * Temporary contractor access * Small office server replacement The important distinction is that Remote Desktop can mean two different things: | Use case | What it means | | ---------------- | --------------------------------------------------------------------------- | | Admin RDP | One or two administrators connect to manage the server | | RDS Session Host | Multiple users connect to use desktops or apps as a normal work environment | A small team should decide which model it needs before choosing the Windows VPS size, licensing path, and security setup. ## A Windows VPS is useful when the desktop must stay online A Windows VPS makes sense when the Windows environment should stay online even when a user’s laptop, office PC, or local network is unavailable. That is the practical reason many small teams move Remote Desktop workloads to a cloud server. Instead of keeping a desktop tower in the office, the team runs the Windows environment on a VPS and connects to it remotely. Users can access the same server from home, office, travel, or another device. This is especially useful when the workload depends on: * Windows-only software * A shared company file * A database running near the application * A stable desktop session * Long-running automation * 24/7 availability * Centralized administration * One server environment instead of many local PCs For example, an accounting team may want QuickBooks or Sage available from multiple locations. A developer may want a Windows Server environment for IIS and SQL Server. A trading operator may want a Windows session that keeps software running overnight. A Windows VPS gives these workloads a central place to run. The trade-off is operational responsibility. A VPS still needs updates, security controls, backups, user management, and performance monitoring. ## Admin RDP and RDS Session Host solve different problems The biggest mistake in Remote Desktop planning is treating admin RDP and multi-user Remote Desktop as the same thing. They are not the same. ![Decision visual comparing admin RDP and RDS Session Host for server management, multi-user desktop access, licensing, session type, common applications, support model, and best-fit business use cases.](https://raff-images.s3.raffusercloud.com/admin_rdp_vs_rds_session_host_webp_363dbc0d13.png) Admin RDP is for managing the server. It is suitable for administrators who need to sign in, configure services, install updates, check logs, or troubleshoot. RDS Session Host is for user desktops or app sessions. It is suitable when multiple people need to use the Windows environment for daily work. | Requirement | Better fit | | ------------------------------------------------- | ---------------- | | One admin needs to configure the server | Admin RDP | | Two admins occasionally troubleshoot | Admin RDP | | Five employees need daily desktop sessions | RDS Session Host | | Accounting staff need to run QuickBooks remotely | RDS Session Host | | Contractors need separate user sessions | RDS Session Host | | A developer needs IIS and SQL Server admin access | Admin RDP | | A team needs hosted Windows apps | RDS Session Host | For a deeper licensing and access breakdown, read [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds). The simple rule: Use admin RDP to manage a server. Use Remote Desktop Services when users are working on the server. ## The decision framework for Remote Desktop on a Windows VPS Use this framework before turning a Windows VPS into a Remote Desktop environment. | Decision area | Admin RDP is usually enough when... | RDS Session Host is better when... | | ------------- | --------------------------------------- | ------------------------------------------------------- | | User count | One or two admins connect occasionally | Multiple employees need daily access | | Purpose | Server management | Desktop or application usage | | Session type | Occasional maintenance session | Separate user work sessions | | Licensing | Standard admin access is enough | RDS CAL planning is required | | Applications | Admin tools, PowerShell, IIS, SQL tools | Accounting, ERP, Office, browser apps, trading software | | Security | Small admin group | User access policy, MFA path, stronger auditing | | Performance | Light management workload | CPU/RAM sizing per user and application | | Support | IT/admin access only | End-user support and session management | | Best fit | Server administration | Remote work or hosted business software | This is the main decision. A Windows VPS can support both models, but the planning is different. Admin access is simple. Multi-user desktop hosting needs more thought around licensing, sizing, session limits, security, and support. :::cta deploy Deploy a Windows VM with full RDP access from $10.99/month plus the $15 Windows licence. ::: ## Remote Desktop workloads are not all the same Remote Desktop performance depends on what users do inside the session. A single admin opening Server Manager is light. Five users running accounting software during tax season is not the same workload. A trader running multiple charts and expert advisors has different pressure than a bookkeeper entering invoices. | Workload | Typical pressure points | | --------------------------- | -------------------------------------------- | | Basic administration | Low CPU/RAM, occasional login | | Office-style desktop work | RAM, session count, display responsiveness | | Accounting software | RAM, disk, file/database access, backups | | SQL Server administration | RAM, database load, storage performance | | IIS and .NET management | CPU, RAM, app pools, logs | | MetaTrader or trading tools | CPU, RAM, uptime, latency, session stability | | Browser-heavy work | RAM, CPU, profile data | | Multi-user RDS | RAM per user, CPU, licensing, session policy | The more users and applications you add, the less the server behaves like a simple remote admin box. That is when sizing, session management, and performance tuning become important. ## Sizing a Windows VPS for Remote Desktop A Windows VPS for Remote Desktop should be sized around people, applications, and session behavior. ![Task Manager Performance tab showing CPU, memory, disk, and network usage during a Remote Desktop session on a Windows VPS.](https://raff-images.s3.raffusercloud.com/windows_vps_rdp_task_manager_performance_webp_f58a6bac73.png) A small admin-only VPS can be modest. A multi-user RDS server needs more CPU and RAM because every active user session consumes resources. Use this as a planning model: | Scenario | Starting spec direction | Notes | | --------------------------------------- | --------------------------------- | ---------------------------------------------------- | | Admin-only RDP | 2 vCPU / 4 GB RAM | Good for light administration and setup work | | One user running light Windows apps | 2 vCPU / 4–8 GB RAM | Browser-heavy work may need more RAM | | 2–3 users with business software | 4 vCPU / 8 GB RAM | Watch RAM, disk, and app load | | 5–10 users with accounting or ERP tools | 4–8 vCPU / 16 GB RAM or more | Plan RDS, backups, antivirus exclusions, and support | | SQL Server plus RDP users | Larger VM or separated database | SQL Server and RDP sessions compete for RAM | | Trading platform 24/7 | Size by software count and charts | Stability and uptime matter more than minimal cost | Do not size only by login count. A user running one lightweight admin tool is different from a user running Outlook, browser tabs, accounting software, PDFs, Excel, and database-connected software in the same session. ![Visual guide showing Windows VPS sizing considerations for admin-only RDP, single-user Remote Desktop, small team business software, accounting or ERP tools, and SQL Server workloads.](https://raff-images.s3.raffusercloud.com/windows_vps_remote_desktop_sizing_guide_webp_703b0e6969.png) The useful sizing question is: ```text What will each user actually run inside the Remote Desktop session? ``` For performance tuning after launch, read [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning). ## Licensing is part of the Remote Desktop decision Remote Desktop licensing matters because admin access and user desktop access are different use cases. For basic server administration, normal Remote Desktop access is used by administrators to manage the server. For multi-user desktop or app access, plan Remote Desktop Services and RDS CALs. RDS CAL planning usually depends on: * Number of users or devices * Whether users share devices * Whether users connect from multiple devices * Whether the server is joined to Active Directory * Whether the environment needs per-user or per-device licensing * Whether licensing is BYOL or provider-managed * Whether Office or Microsoft 365 Apps are used in the session For example, a five-person accounting firm where each employee connects from their own laptop usually thinks differently from a shift-based office where many people share the same physical workstations. The safest approach is to decide licensing before inviting users onto the server. For the full licensing breakdown, read [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) and [Windows Server Licensing on Raff](/windows-server/windows-licensing). ## Security should be planned before users connect Remote Desktop is an access path into the server. Treat it as production infrastructure. ![Windows Defender Firewall inbound rules showing Remote Desktop access controls on a Windows VPS.](https://raff-images.s3.raffusercloud.com/windows_vps_rdp_firewall_rules_webp_bc6a5d3dbe.png) At minimum, a Windows VPS used for Remote Desktop should have: * Strong administrator password policy * Separate user accounts * Least-privilege access * Windows Firewall enabled * RDP access reviewed * Windows updates planned * Microsoft Defender enabled * Audit logging reviewed * Backups configured * Unused services removed * User access removed quickly when someone leaves For small teams, the most common security mistake is convenience. Everyone shares one login, RDP stays open broadly, passwords are reused, and no one reviews access after the first setup. That approach may work for a test server. It is not a good production pattern. For practical hardening steps, read [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) and [Configure Windows Firewall on a Windows VPS](/windows-server/configure-windows-firewall). ## Remote Desktop performance is a combined system RDP performance is not only about the VPS. It depends on four layers: | Layer | What affects the experience | | ---------------- | ------------------------------------------------------ | | Client device | Screen resolution, local RDP app, display settings | | Network path | Latency, packet loss, ISP route, blocked ports | | Windows VPS | CPU, RAM, disk, background processes | | Session workload | Apps, browser tabs, database tools, charts, user count | A slow session can come from any of these layers. If CPU and RAM are already high inside the VPS, changing display settings will not fix the root problem. If the server is calm but input feels delayed, the network path or client settings may be the issue. A good troubleshooting order is: 1. Check server CPU and RAM. 2. Check network path and RDP connectivity. 3. Review RDP client display settings. 4. Reduce unnecessary visual effects. 5. Tune session policies. 6. Resize the VPS if the workload has outgrown the plan. For the full walkthrough, use [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning). ## Windows VPS vs office PC for Remote Desktop Many small businesses start by exposing an office PC or local server for remote access. That can work temporarily, but it creates operational limits. | Area | Office PC or local server | Windows VPS | | ------------ | ------------------------------------ | ----------------------------------------- | | Availability | Depends on office power and internet | Runs in cloud infrastructure | | Access | Often tied to office network | Accessible from authorized remote clients | | Maintenance | Usually informal | Centralized server management | | Hardware | Local hardware failures matter | VM can be resized or replaced more easily | | Backups | Often inconsistent | Can be planned around server workload | | Security | Depends on local setup | Can be hardened as server infrastructure | | Scaling | Harder to add capacity | Resize or separate workloads when needed | An office server may be enough when everyone works in one location and downtime is low impact. A Windows VPS becomes more attractive when users are distributed, the office network is unreliable, the software needs to stay online, or the team wants one hosted Windows environment instead of a local machine under someone’s desk. ## Windows VPS vs cloud PC for Remote Desktop A cloud PC and a Windows VPS can both give users remote Windows access, but they are not the same decision. A cloud PC is usually a managed personal desktop. It is often best when each user needs their own individual desktop environment and the organization wants the provider to manage much of the desktop platform. A Windows VPS is usually better when the team needs a server-style Windows environment for shared software, admin tools, databases, IIS, accounting apps, or RDS Session Host planning. | Need | Better fit | | ------------------------------------- | ----------- | | Personal managed desktop per employee | Cloud PC | | Shared Windows Server environment | Windows VPS | | Business software on one server | Windows VPS | | Server administration | Windows VPS | | Minimal IT operations | Cloud PC | | Direct server control | Windows VPS | | RDS Session Host planning | Windows VPS | | Individual employee desktops | Cloud PC | The question is not which one is “better.” The question is whether the team needs personal desktops or a Windows Server environment. ## Raff Windows VPS context Raff Windows VPS fits the Remote Desktop use case when a small team needs a cloud-hosted Windows Server environment for admin work, business software, or RDS planning. Common Raff use cases include: * Remote Desktop access for admins * Hosted accounting software * QuickBooks or Sage environments * SQL Server administration * IIS and .NET application management * Internal tools * Trading platforms * Small business software * RDS Session Host planning * Office server replacement Raff Windows VPS gives teams a simple Windows Server path with cloud VM control, NVMe SSD storage, unmetered bandwidth, 3 Gbps port speed, one IPv4 address, optional IPv6 dual-stack support, and Windows Server version options. This is not the same as saying every Remote Desktop workload should run on one VPS. If a team needs many users, strict compliance, high availability, or managed desktop governance, the design should be reviewed more carefully. But for many small teams, a Windows VPS is a practical starting point because it keeps the Windows environment centralized, accessible, and easier to manage than scattered local machines. ## Common mistakes when using Windows VPS for Remote Desktop ### Treating admin RDP as multi-user desktop hosting Admin RDP is for server management. If multiple users need daily desktop sessions, plan Remote Desktop Services and RDS CALs instead of trying to stretch the admin model. ### Buying by CPU only Remote Desktop sessions are often RAM-sensitive. Browsers, accounting software, Office apps, ERP clients, and SQL tools can consume memory quickly. CPU matters, but RAM is often the first limit users feel. ### Ignoring software behavior Two applications with similar-looking interfaces can behave very differently. QuickBooks, Sage, SQL Server tools, browser apps, trading platforms, and IIS management all create different CPU, RAM, disk, and network pressure. ### Leaving RDP security too open Remote Desktop should not be treated like a casual login page. Review firewall rules, passwords, account access, audit logs, updates, and backups before the server becomes part of daily work. ### Forgetting disconnected sessions Disconnected sessions can keep applications open and continue consuming RAM. For RDS environments, session timeout and disconnected-session policies should be planned. ### Skipping backups A Remote Desktop server often becomes a place where users save files, app data, exports, reports, and configuration. If users depend on the server, backups should be planned before production use. ### Waiting too long to resize A server that worked for one admin may not work for five daily users. Monitor CPU, RAM, disk, and session experience after real usage begins. ## What Raff recommends Start by deciding whether the server is for administration or user work. For admin-only access, keep the setup simple: one or two administrators, strong credentials, firewall review, Windows updates, and basic monitoring. For daily user work, treat the Windows VPS as a Remote Desktop environment. Plan RDS licensing, user accounts, RAM per user, session policy, backups, security, and performance tuning before the team depends on it. For small business software, keep the application and data close together where possible. Do not make users open a database or company file across a slow VPN if the software expects local or LAN-like access. For Remote Desktop performance, check the server load before changing display settings. A slow desktop is often a sizing or workload issue, not only an RDP setting. ## What's next * [Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) — step-by-step connection instructions for Windows, macOS, Linux, iOS, and Android. * [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) — practical checks for slow Remote Desktop sessions. * [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) — decide when default RDP is enough and when RDS is required. * [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) — understand per-user and per-device licensing. * [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) — secure the Windows VPS before production use. ## Sources * [Microsoft Learn — Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) * [Microsoft Learn — Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) * [Microsoft Learn — License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) * [Microsoft Learn — License Remote Desktop session hosts](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-license-session-hosts) * [Raff — Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) * [Raff — Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) * [Raff — RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) * [Raff — RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) --- ### Windows VPS for Property Management Companies: Apps, Files, and Remote Access URL: https://rafftechnologies.com/windows-server/windows-vps-property-management-companies Description: Learn when a Windows VPS fits property management companies that need shared business applications, lease and owner records, maintenance workflows, accounting access, backups, and remote teams. A Windows VPS for property management companies can centralize supported Windows business applications, accounting tools, lease and owner records, maintenance documents, reports, shared folders, and remote user sessions in one cloud-hosted Windows Server environment. It is strongest for small and midsize property managers that still depend on Windows-based software, mapped drives, local databases, shared documents, or an aging office server. It is less useful when the company already runs entirely on vendor-hosted browser applications and cloud document platforms. Raff Technologies provides the Windows VM infrastructure. The property management company or its MSP remains responsible for application compatibility, software licensing, Remote Desktop Services licensing, user permissions, database administration, backups, security, migration, and recovery. This article is different from [Windows VPS for Real Estate Offices](https://rafftechnologies.com/windows-server/windows-vps-real-estate-offices). The real estate article focuses on brokerage and transaction workflows. This guide focuses on recurring property operations: leases, rent and owner reporting, maintenance coordination, vendor records, property-level permissions, and multi-location staff access. :::cta Explore Windows VM Centralize property apps, records, users, and reporting on Windows. ::: ## Quick verdict: when a Windows VPS fits property management Use this table before moving a property management workload to a Windows VPS. | Property management situation | Windows VPS fit | Why | |---|---|---| | The core application supports Windows Server or RDS | Strong fit after vendor confirmation | The app, database, reports, and users can share one hosted environment. | | Managers, accountants, and maintenance coordinators work remotely | Strong fit | Authorized users can reach the same Windows environment from different locations. | | Lease, owner, vendor, and property files are scattered | Strong fit | Shared folders and permissions can be centralized. | | An aging office server hosts property or accounting software | Strong fit after dependency review | The workload can move away from one physical machine. | | Several offices manage the same properties | Strong fit with connectivity planning | Teams can work from one controlled environment. | | The company uses desktop accounting alongside property software | Good fit | Accounting tools, reports, exports, and files can remain close together. | | Check printing, document scanning, or local printers are critical | Test before production | Driver, redirection, security, and workflow behavior vary. | | The main property platform is already vendor-hosted SaaS | Depends | A Windows VPS may only be useful for accounting, files, legacy tools, or integrations. | | The vendor prohibits hosted or multi-user deployment | Poor fit | Use a supported deployment model. | | The business needs application-level high availability | Not a single-VM decision | Design redundancy, database recovery, and failover separately. | The strongest candidate is a residential, commercial, or mixed-property management company that needs one controlled Windows environment for staff, business applications, records, reports, and backups. The goal is not to move every process into Remote Desktop. The goal is to centralize the Windows workloads that are currently difficult to secure, support, and recover. ## Why property management companies outgrow office-based systems Many property management companies begin with a practical setup: one office server, a shared drive, desktop accounting software, a property application, and several staff PCs. That model becomes harder to manage as the portfolio, team, and document volume grow. | Common problem | What it looks like in practice | How a Windows VPS can help | |---|---|---| | Property software is tied to one office | Remote staff depend on VPN workarounds or office PCs | A supported application can run in one cloud-hosted Windows environment. | | Files are organized differently by employee | Lease, inspection, owner, and vendor records are difficult to find | Shared folders and permissions can be standardized. | | Accounting and property data are separated | Staff export and email files between departments | Applications and approved shared folders can remain close together. | | The office server is aging | Hardware, power, storage, and warranty risks increase | The workload moves away from one physical server. | | Several branches maintain separate copies | Property records and reports become inconsistent | Users can work from one controlled environment. | | Former employees retain access or copies | Offboarding is incomplete | Named users and central permissions are easier to review. | | Backups are unclear | Nobody can prove that the application or database can be restored | Backup layers and restore tests can be documented. | | Growth requires another server purchase | More users, properties, reports, and documents increase load | A VM can be resized and storage can be expanded. | The business benefit is not simply replacing an office server with a cloud server. It is giving property managers, accounting staff, leasing teams, maintenance coordinators, and administrators one controlled place to reach the applications and records they use every day. ## Property management workloads that fit a Windows VPS ### Property management and accounting applications A Windows VPS can host property management or accounting software when the vendor supports the operating system, hosted deployment, database, and multi-user access model. Potential workloads include: - property and unit records; - tenant or resident records; - owner records; - lease administration; - charges and payment records; - accounts receivable and payable; - owner statements; - general ledger and financial reports; - security deposit records; - vendor records; - maintenance costs; - property budgets; - bank reconciliation tools; - year-end exports; - custom reports; - document generation. Do not assume that every desktop property application supports Windows Server or Remote Desktop Services. Confirm the exact version, database engine, licensing model, and support terms with the vendor before migration. When accounting is the primary workload, read [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms). ### Lease, owner, property, and vendor documents Property management companies generate a large volume of operational records. A Windows VPS can centralize: - leases and amendments; - owner agreements; - property and unit documents; - move-in and move-out records; - inspection reports; - maintenance photos and attachments; - vendor contracts; - invoices and purchase records; - insurance certificates; - notices and correspondence; - property reports; - owner statements; - bank and accounting exports; - archived tenant records; - templates and forms. Moving a disorganized file structure to the cloud does not fix it. Clean up duplicate folders, naming rules, property codes, access groups, retention requirements, and archive ownership before migration. Read [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) when shared files are the main problem. ### Maintenance and work-order administration A Windows VPS can support the administrative side of maintenance operations when the software is compatible. Potential uses include: - work-order entry; - assignment and scheduling; - vendor contact records; - estimate and invoice review; - property notes; - maintenance history; - recurring maintenance schedules; - purchase approvals; - inspection records; - photos and attachments; - cost reporting; - exported work lists. Mobile maintenance applications and vendor portals may remain separate SaaS systems. The Windows VPS can still host the back-office application, reporting tools, accounting integration, or shared records when the workflow supports it. ### Owner reporting and month-end work Month-end can create more server load than normal daily use. The environment may need to process: - owner statements; - property-level income statements; - rent-roll reports; - delinquency reports; - accounts payable batches; - bank reconciliation; - management fee calculations; - vendor payment reports; - general ledger exports; - PDF generation; - spreadsheet exports; - archived report packages. Size for reporting peaks, database activity, and PDF or spreadsheet generation, not only the number of people who can log in. ### Remote and multi-location staff Property management work is often distributed across a main office, leasing locations, property sites, home offices, and external accounting or IT support. A centralized Windows VPS can give authorized users access to the same: - supported property application; - accounting tools; - reports; - shared folders; - templates; - property records; - vendor documents; - maintenance records; - archived files; - administrative utilities. Use named accounts and role-based permissions. Property managers, accountants, leasing staff, maintenance coordinators, executives, and IT providers should not automatically receive the same desktop or folder access. Read [Windows VPS for Multi-Location Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-multi-location-business) for the broader branch-office model. ## A practical property management architecture A small or midsize property management company may use this pattern: ![Property managers, accounting staff, leasing teams, maintenance coordinators, and remote staff accessing applications, files, databases, permissions, and backups through a Windows VPS](https://raff-images.s3.raffusercloud.com/property_management_windows_vps_architecture_png_bb5e5d7b45.png) The cloud Windows environment becomes the shared business workspace. Browser-based services and local devices remain separate where that design is safer or better supported. A good architecture answers seven questions: 1. Which application is the source of truth for property and financial records? 2. Which users need a full desktop, a RemoteApp, or only shared files? 3. Which integrations require local software or a service account? 4. Which documents must remain close to the application? 5. Which printers, scanners, or check-printing devices are business-critical? 6. What happens when an office or property site loses internet access? 7. Who owns recovery when the application, database, integration, or server fails? ## Remote Desktop access should follow job roles Microsoft describes Remote Desktop Services as a Windows Server platform for delivering managed desktops and applications to users in offices, homes, branches, and partner locations. A property management company should design access around the actual job. | User role | Likely access need | |---|---| | Owner or executive | Portfolio reports, approvals, financial visibility, and dashboards | | Property manager | Property records, leases, work orders, vendor information, and reports | | Accounting team | Receivables, payables, bank reconciliation, owner statements, and exports | | Leasing staff | Unit records, applicant or tenant documents, templates, and approved reports | | Maintenance coordinator | Work orders, vendor records, schedules, costs, and attachments | | Administrative staff | Shared documents, forms, reports, and data entry | | External accountant | Restricted accounting access for an approved period | | MSP or IT provider | Administration, patching, monitoring, backups, and recovery | If employees use an RD Session Host for daily desktop or RemoteApp sessions, Microsoft requires an appropriate RDS Client Access License for each connecting user or device. Administrative sessions are not a substitute for a licensed multi-user environment. Use these related guides: - [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) - [Windows VPS for Remote Employees](https://rafftechnologies.com/windows-server/windows-vps-remote-employees) - [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) - [RDS CAL Licensing on Windows Server](https://rafftechnologies.com/windows-server/rds-cal-licensing-guide) :::cta Talk to Windows Engineer Plan users, applications, integrations, storage, backups, and migration first. ::: ## Printers, scanners, check printing, and integrations need testing A migration can be technically successful while daily office workflows still fail. Property management teams may depend on: - office printers; - PDF printers; - document scanners; - check printers; - MICR-capable printing workflows; - signature pads; - USB licensing devices; - local email clients; - browser extensions; - document-signing tools; - payment portals; - banking portals; - watched folders; - local export or import utilities; - spreadsheet templates; - service accounts and scheduled tasks. Remote Desktop can redirect some printers, drives, clipboard content, and other resources, but policy, client settings, drivers, application behavior, and the device communication method affect the result. Test the complete business process, not only whether Windows detects the device. | Dependency | Acceptance test | |---|---| | Office printer | Correct queue, paper size, duplex settings, speed, and user access | | PDF workflow | Correct file name, save location, permissions, and application attachment behavior | | Document scanner | TWAIN or WIA requirement, multi-page scans, resolution, naming, and upload path | | Check printing | Approved printer, paper, alignment, security controls, and accounting-software support | | Signature device | Vendor support, redirection method, and session behavior | | Payment or bank portal | Browser compatibility, authentication, export or upload workflow, and user role | | Email integration | Supported client, SMTP or API settings, attachment behavior, and service account | | Document signing | Browser or desktop requirement, file path, and final document storage | | Scheduled export | Service account, file path, schedule, error handling, and duplicate prevention | | Application integration | Supported API, ODBC, file transfer, service, or vendor-approved method | Do not weaken security controls only to make an old workflow function. When a local device or integration cannot be supported safely, keep that component local or replace the workflow. ## Application databases and integrations determine real performance The visible desktop application may not be the main resource consumer. Database queries, owner reports, payment imports, document generation, and month-end jobs can create more load than user sessions. Document: - database engine and version; - database size and monthly growth; - number of properties and units; - peak concurrent users; - reporting peaks; - payment and bank imports; - accounting exports; - scheduled jobs; - integrations and APIs; - ODBC connections; - service accounts; - file paths and mapped drives; - document-generation tools; - transaction-log growth; - database recovery model; - backup windows; - restore process. Keep the application and database close to each other. Avoid placing a file-based database across a wide-area network path. If the database becomes large or business-critical, consider separating Remote Desktop, application, and database roles. SQL Server backup and restore planning must match the database recovery model. A VM-level backup alone does not replace application-aware database protection. ## Size for concurrent users and peak reporting Do not size a property management Windows VPS by total employee count. Size it by concurrent sessions, application requirements, database activity, reports, integrations, and file growth. Use the following only as initial test ranges: | Workload | Initial test size | Increase resources when | |---|---:|---| | One administrator or reporting user | 2 vCPU / 4 GB RAM | The app, browser, PDF tools, and reports compete for memory | | 2-3 light office users | 4 vCPU / 8 GB RAM | Several sessions and documents stay open together | | 3-5 active business users | 4 vCPU / 16 GB RAM | Property app, accounting, database, and reports share one VM | | 6-10 active users | 8 vCPU / 32 GB RAM | The server becomes a daily shared workspace | | SQL-backed property or accounting platform | 8-16 vCPU / 32-64 GB RAM | Database working set, reports, imports, and integrations need more capacity | | Document-heavy portfolio | Size storage separately | Leases, inspections, invoices, photos, and reports grow quickly | | High-availability requirement | Multi-server assessment | One VM does not provide application-level failover | For a five-user office, 4 vCPU and 16 GB RAM can be a reasonable test starting point. It is not a performance guarantee. Raff's current sizing documentation recommends dedicated CPU plans for Windows responsiveness and lists 4 vCPU / 8 GB as the starting infrastructure plan for a light multi-user RDP terminal server. Property management workloads commonly need more memory once accounting tools, databases, browsers, PDFs, and reports run together. Measure during representative workflows: - user logon time; - application launch time; - property or tenant lookup time; - posting and save time; - owner statement generation; - rent-roll report duration; - bank or payment import duration; - PDF generation; - CPU peaks; - available memory; - disk latency; - database waits; - backup duration; - session disconnects; - storage growth. Read [Windows VPS Sizing for Remote Users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing a production plan. ## Plan storage around records, profiles, and growth Property management environments can grow faster than expected because application data and documents expand at different rates. Plan capacity for: - Windows and application installation; - property management database; - accounting database; - transaction logs; - lease and owner documents; - inspection files and photos; - vendor invoices and contracts; - maintenance attachments; - statements and reports; - scanned documents; - user profiles; - temporary PDF and export files; - integration logs; - backup staging; - migration copies; - 12 to 24 months of growth. Keep the operating system, database, documents, and backups logically separated where the application supports it. Raff Volumes can add block storage that outlives the VM, but volume layout and backup scope should be designed before moving production data. ## Security must protect property, financial, and personal records A property management Windows environment may contain personal contact information, lease records, owner records, financial data, bank exports, vendor information, maintenance records, credentials, and remote-access pathways. Minimum controls include: | Security area | Planning requirement | |---|---| | Identities | Named users, strong authentication, and prompt offboarding | | Administration | Separate privileged accounts from daily user accounts | | Remote access | Use controlled RDS, RD Gateway, VPN, or private-access design | | Firewall | Permit only required ports and sources | | Permissions | Limit access by role, property, department, or responsibility | | Shared folders | Use groups and least privilege instead of broad access | | Service accounts | Document purpose, ownership, permissions, and credential rotation | | Updates | Plan Windows, application, browser, and integration maintenance | | Logging | Review failed logons, account changes, and unusual access | | Backups | Protect backup deletion rights and recovery credentials | | Vendor access | Make access approved, time-bound, and monitored where possible | | Documentation | Record owners, dependencies, recovery order, and support contacts | Do not expose unrestricted RDP, SMB, or database ports directly to the public internet. Microsoft recommends blocking inbound SMB from the internet and using segmentation and controlled access for file-sharing traffic. Microsoft's Windows Server security baselines provide a standardized hardening starting point, but baseline changes can affect legacy applications and must be tested before production. This article is not legal, privacy, payment-security, housing, or compliance advice. Review applicable requirements with qualified advisers and the relevant software vendors. Read [Windows Server Hardening Checklist](https://rafftechnologies.com/windows-server/windows-server-hardening-checklist) before production rollout. ## Backups must protect the server, database, files, and recovery process A property management backup plan needs more than a copy of the Windows disk. Use layered protection: | Protection layer | Purpose | |---|---| | Application-aware database backup | Protect property, accounting, payment, and reporting data correctly | | File backup | Recover deleted or changed leases, reports, invoices, and records | | VM backup | Recover the broader Windows environment | | Snapshot before change | Create a short-term rollback point before updates or migration | | Off-server copy | Reduce risk from server, account, or ransomware incidents | | Retention policy | Preserve recovery points for the required business period | | Restore test | Prove that applications, data, permissions, and workflows are usable | | Recovery documentation | Preserve owners, credentials, sequence, dependencies, and contacts | A successful backup notification does not prove the operation can resume. Restore the database to a test environment. Open the property application. Confirm property, lease, owner, and accounting records. Generate an owner statement. Open shared documents. Validate permissions, integrations, scheduled jobs, and printing. Raff VMs support point-in-time snapshots and automated daily or weekly backup schedules with configurable retention. Application owners still need to define database protection, file-level recovery, off-server copies, and restore procedures. Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production records. :::cta Explore Data Protection Protect property applications, databases, documents, and recovery points. ::: ## Internet outages and business continuity need a fallback A cloud-hosted Windows environment depends on connectivity from the office or property site. Define what happens when users cannot reach the server. Possible fallback measures include: - a secondary office internet connection; - cellular failover; - locally available emergency contact information; - locally stored building and vendor emergency procedures; - approved manual maintenance intake; - a process for recording payments or documents for later entry; - offline copies of critical property instructions; - a reconciliation process after connectivity returns; - a defined point at which financial or data-entry work pauses. Do not assume mobile data is a recovery plan until it has been tested from the actual office. Signal strength, carrier congestion, VPN behavior, firewall rules, and data limits can change the result. The business should know whether a one-hour outage delays reporting, blocks leasing administration, stops payment posting, prevents maintenance coordination, or halts the whole office. That impact determines the connectivity and recovery design. ## Migration should start with discovery and one bounded workflow A property management migration is safer when the first phase has a clear scope. ### 1. Inventory the current environment Document: - applications and versions; - databases; - users and groups; - properties, units, and portfolio size; - file shares and permissions; - mapped drives; - printers and scanners; - check-printing workflow; - email and document-signing integrations; - payment and banking exports or imports; - scheduled tasks and services; - ODBC connections; - service accounts; - storage usage and growth; - backup jobs; - remote offices and home users; - recovery requirements; - vendor and MSP contacts. ### 2. Classify every dependency Mark each item as: - cloud candidate; - local office dependency; - browser-based external service; - integration between systems; - unsupported or unknown; - replacement candidate. Unknown dependencies should block production cutover until they are tested. ### 3. Confirm vendor and licensing support Ask the application vendor: - Is Windows Server supported? - Is virtual or hosted deployment supported? - Is Remote Desktop Services supported? - Which database edition and version are required? - Are multiple concurrent users supported? - Are printers, scanners, check printing, and PDF workflows supported remotely? - Does the product require a USB device, local service, or desktop Office installation? - Are payment, bank, email, and document-signing integrations supported? - Will the vendor support the application after migration? ### 4. Build a parallel test environment Create a test Windows VPS, install the software, restore a copy of the data, and create non-administrator accounts for representative roles. Test from the office, home, branch, and external accountant or MSP networks where applicable. ### 5. Validate complete workflows Test: - login and authentication; - application launch; - property and tenant lookup; - lease and document access; - charge or payment entry using test data; - owner statement generation; - rent-roll and financial reports; - invoice entry and approval; - work-order entry; - PDF generation; - printing and scanning; - check printing where applicable; - payment and bank imports or exports; - email and document-signing workflow; - file open and save; - scheduled jobs; - backup; - database restore; - loss of connectivity; - rollback. ### 6. Schedule a low-risk cutover Avoid month-end, owner reporting periods, major portfolio onboarding, rent-processing peaks, or other critical business windows. Run the final backup and data synchronization. Validate the destination. Release users in a controlled order. Keep the previous environment available until the business owner, application owner, accounting owner, and IT owner approve the new workflow. ### 7. Monitor the first operating cycle Track performance and support issues through a normal reporting, accounting, maintenance, and leasing cycle. Monitor: - CPU and memory; - disk capacity and latency; - database performance; - session disconnects; - application errors; - printing and scanning issues; - integration failures; - backup success; - restore readiness; - support tickets; - user feedback. Use the [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) and [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) before production cutover. ## When a Windows VPS is not the right fit A Windows VPS should not be forced into every property management workflow. | Situation | Better next step | |---|---| | The company already uses a complete vendor-hosted SaaS platform | Use the SaaS platform unless another Windows workload justifies a server | | The vendor prohibits Windows Server, cloud, or RDS deployment | Use the supported model or replace the application | | Critical workflow depends on unsupported local hardware | Keep the dependent component local or redesign the workflow | | Internet outages cannot interrupt office work | Preserve local capability or build tested connectivity redundancy | | Check printing cannot be secured or supported remotely | Keep the approved printing workflow local | | The database requires high availability | Design database redundancy and failover rather than relying on one VM | | Security ownership is undefined | Assign access, patching, backup, and incident owners first | | Restore testing cannot be completed | Keep the environment in test status | | Users only need browser applications and cloud documents | Avoid adding Windows infrastructure without a clear benefit | | No one owns application vendor support | Resolve support responsibility before migration | The right answer may be SaaS, Windows VPS, local server, or a hybrid design. Place each workload where it can be supported and recovered. ## How Raff supports property management workloads Raff fits property management companies that need a cloud-hosted Windows Server foundation for supported business applications, accounting, shared documents, remote users, multi-location access, and replacement of an aging office server. Raff Windows VMs provide selectable Windows Server templates, Administrator and RDP access, dedicated or shared CPU plan families, SSD storage, optional attached Volumes, snapshots, automated backups, security groups, VPC networking, performance metrics, VM resizing, and human support. The property management company or its MSP remains responsible for: - application compatibility; - vendor licensing; - RDS licensing; - user roles and offboarding; - database administration; - printer and scanner testing; - check-printing controls; - payment, bank, email, and signing integrations; - backup retention; - restore testing; - Windows and application updates; - security hardening; - migration and rollback; - business continuity; - legal and compliance decisions. Raff should be the infrastructure layer under a documented property management workflow, not a shortcut around vendor support, licensing, security, or recovery planning. ## Recommended path by property management situation | Situation | Recommended path | |---|---| | One office has an aging property-management server | Test the application, database, users, documents, backups, and restore on one Windows VPS | | Managers and accounting staff need remote access | Use a controlled RDS or remote-access design with named users and licensing | | Several offices manage the same portfolio | Centralize the supported application, then test every site's connectivity and workflow | | Shared property documents are the main problem | Use a structured file-server design with permissions and backup | | Accounting and property software run together | Size around month-end reporting, database memory, and exports | | Printers, scanners, and checks are critical | Test exact models, drivers, permissions, and user sessions before cutover | | The main property platform is SaaS | Use a Windows VPS only for workloads SaaS does not solve | | SQL Server drives performance | Size around database memory, reports, jobs, and recovery requirements | | High availability is mandatory | Evaluate a multi-server application and database architecture | ## Final property management Windows VPS checklist Before putting the environment into production, confirm: | Check | Done | |---|---| | Applications and versions inventoried | ☐ | | Vendor support for Windows Server confirmed | ☐ | | Hosted and RDS licensing reviewed | ☐ | | Active users and roles documented | ☐ | | Properties, units, and reporting peaks documented | ☐ | | Database requirements documented | ☐ | | Shared folders and permissions planned | ☐ | | Lease, owner, vendor, and maintenance records classified | ☐ | | Printers and PDF workflows tested | ☐ | | Scanners tested | ☐ | | Check-printing workflow reviewed | ☐ | | Payment, bank, email, and signing integrations tested | ☐ | | Service accounts and scheduled jobs documented | ☐ | | Network flows and firewall rules documented | ☐ | | Internet-outage fallback tested | ☐ | | CPU, RAM, and storage starting point selected | ☐ | | Storage growth estimated | ☐ | | Application-aware database backups configured | ☐ | | File-level and off-server recovery copies planned | ☐ | | File, database, and application restores tested | ☐ | | Migration window approved | ☐ | | Rollback path documented | ☐ | | System, accounting, security, and recovery owners named | ☐ | | Old environment retained until final approval | ☐ | An incomplete checklist means the system is still a test environment. ## What's next A Windows VPS for property management companies works best when the business centralizes supported Windows applications and records, tests local devices and integrations, and proves that backups can restore the complete workflow. Read [Windows VPS for Real Estate Offices](https://rafftechnologies.com/windows-server/windows-vps-real-estate-offices) for brokerage and transaction workflows. Review [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms) when accounting software is the main workload. Use [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) when shared property documents are the main problem. Explore [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) when the users, applications, database, devices, storage, backups, and migration path are documented well enough to build a test environment. :::cta Deploy Windows Now Build a test environment for your property management workload. ::: ## Sources - Microsoft Learn — [Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) - Microsoft Learn — [Install Remote Desktop Services client access licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-install-cals) - Microsoft Learn — [Printer redirection and drive redirection troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-server/printing/printer-hard-drive-not-redirect-to-remote-desktop-session) - Microsoft Learn — [Secure SMB Traffic in Windows Server](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-secure-traffic) - Microsoft Learn — [SMB security hardening](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-security-hardening) - Microsoft Learn — [Configure Security Baselines for Windows Server 2025](https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines) - Microsoft Learn — [Recovery models for SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/recovery-models-sql-server) - Microsoft Learn — [Full database backups for SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/full-database-backups-sql-server) - Raff Docs — [Virtual Machines](https://docs.rafftechnologies.com/products/build/virtual-machines) - Raff Docs — [Plans and sizing](https://docs.rafftechnologies.com/products/build/virtual-machines/concepts/plans-and-sizing) - Raff Docs — [Virtual Machine features and limits](https://docs.rafftechnologies.com/products/build/virtual-machines/details/features-and-limits) - Raff Docs — [Enable backups](https://docs.rafftechnologies.com/products/build/virtual-machines/quickstart-guides/enable-backups) - Raff — [Windows VPS for Real Estate Offices](https://rafftechnologies.com/windows-server/windows-vps-real-estate-offices) - Raff — [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms) - Raff — [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) - Raff — [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) --- ### Windows Server Initial Setup Checklist: First 30 Minutes After Deploying a VPS URL: https://rafftechnologies.com/windows-server/windows-server-initial-setup-checklist Description: Use this 30-minute Windows Server setup checklist after deploying a VPS to establish updates, administrator access, firewall and Defender checks, storage visibility, and a recovery point before installing workloads. ## In short The first 30 minutes after deploying a Windows Server VPS should establish a safe operating baseline before you install IIS, SQL Server, Remote Desktop Services, business software, or other workloads. Confirm the server identity and network state, choose a clear hostname and time zone, start Windows Update, create a named administrator, verify Windows Firewall and Microsoft Defender, check disk capacity, and create a recovery point. This Raff Technologies checklist is for the first administrative session after you have connected successfully; it does not replace full production hardening. If you have not connected yet, start with [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp). Return here after the first successful login. ## The 30-minute checklist | Time | Action | Expected result | |---|---|---| | 0–5 minutes | Record the server purpose, OS, hostname, IP configuration, and recovery path | You know exactly which VM you are changing | | 5–10 minutes | Choose the final hostname and confirm the time zone | Logs, certificates, scheduled tasks, and monitoring use the correct identity and time | | 10–18 minutes | Start Windows Update and plan one controlled restart | The server begins from a current patch level | | 18–23 minutes | Create and test a named administrator account | Daily administration does not depend on one shared built-in account | | 23–27 minutes | Verify Windows Firewall, RDP rules, and Microsoft Defender | Core host protections are active before the workload is exposed | | 27–30 minutes | Check disk capacity, create a recovery point, and save a baseline record | You have a rollback path and a known starting state | Windows Update can take longer than 30 minutes. The goal is to complete the first-pass decisions and start the update cycle, not to guarantee every cumulative update finishes within the time window. ## Before you change anything Open PowerShell as Administrator and capture the current server state: ```powershell Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsBuildNumber, OsArchitecture Get-NetIPConfiguration Get-TimeZone Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter, FileSystemLabel, SizeRemaining, Size ``` Record these items outside the VPS: - Raff VM name - public IP address - selected Windows Server version - administrator username - server owner - intended workload - expected users - recovery or password-reset path - whether a snapshot or backup already exists A short record prevents confusion later when several Windows VMs have similar names or roles. > **Do not change the Windows network adapter to a static address unless the hosting platform specifically requires it.** Cloud VPS images commonly receive network configuration through the provider environment. An incorrect guest-level IP, gateway, or DNS change can immediately break RDP access. ## Minutes 0–5: Confirm the server identity and purpose Before installing software, decide what this server is for. A server that will become a domain controller needs different planning from an IIS server, SQL Server VM, RDS Session Host, or single-user administrative VPS. Use a simple role statement: ```text Purpose: Internal accounting application Owner: Operations team Users: 5 Data: Application files and SQL database Access: RDP through approved admin addresses Recovery target: Same business day ``` Then verify the operating system: ```powershell Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsBuildNumber ``` Do not assume the deployed image matches the version requested. Confirm it before installing drivers, agents, or application dependencies. For new deployments, [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison) explains when compatibility may matter more than choosing the newest version. ## Minutes 5–10: Set a clear hostname and correct time zone A random generated hostname is difficult to recognize in logs, monitoring, certificates, backup consoles, and Active Directory. Choose a short name that describes the server role without embedding secrets or customer data. Examples: ```text APP01 WEB01 SQL01 RDS01 DC01 ``` Check the current name: ```powershell $env:COMPUTERNAME ``` Rename a new workgroup server before joining it to a domain: ```powershell Rename-Computer -NewName "APP01" ``` The new name becomes active after restart. If the server is already domain-joined, use the correct domain credentials and change process instead of treating it as a fresh standalone VM. Next, check the current time zone: ```powershell Get-TimeZone ``` List available Windows time-zone IDs when needed: ```powershell Get-TimeZone -ListAvailable | Select-Object Id, DisplayName ``` Set the intended zone by its Windows ID: ```powershell Set-TimeZone -Id "UTC" ``` Use the zone required by the workload and organization. UTC is often easier for infrastructure logs, while business applications may require the organization’s local time zone. Verify Windows Time status: ```powershell w32tm /query /status ``` Correct time matters for event logs, authentication, scheduled tasks, certificate validation, database jobs, and incident review. ## Minutes 10–18: Start Windows Update before installing workloads Patch the base operating system before adding production software. This reduces the chance that application troubleshooting becomes mixed with pending operating-system changes. On Windows Server with Desktop Experience: 1. Open **Settings**. 2. Select **Windows Update**. 3. Check for updates. 4. Install available cumulative and security updates. 5. Note whether a restart is required. On Server Core, run: ```powershell SConfig ``` SConfig supports common first-run tasks, including computer name, local administrators, update settings, Remote Desktop, networking, date and time, activation, and restart controls. Do not install every optional driver or preview update automatically. Prioritize normal security and cumulative updates, then review optional items against the workload. After the update cycle and controlled restart, verify recently installed updates: ```powershell Get-CimInstance Win32_QuickFixEngineering | Sort-Object InstalledOn -Descending | Select-Object -First 10 HotFixID, Description, InstalledOn ``` For an established production server, use a maintenance window and recovery point rather than patching without rollback planning. See [Windows Update Strategy on Production Servers](/windows-server/windows-update-strategy) for the ongoing process. ## Minutes 18–23: Create a named administrator account Do not let every administrative action depend on a shared built-in `Administrator` account. Create a named local administrator for the person or operational function responsible for the server. Run PowerShell as Administrator: ```powershell $Password = Read-Host "Enter a strong password for opsadmin" -AsSecureString New-LocalUser ` -Name "opsadmin" ` -Password $Password ` -FullName "Operations Administrator" ` -Description "Named administrator for server operations" Add-LocalGroupMember -Group "Administrators" -Member "opsadmin" ``` Verify the local Administrators group: ```powershell Get-LocalGroupMember -Group "Administrators" ``` Then test a new RDP session with the named account before changing the built-in Administrator account. Use these rules: - Create one named account per administrator where practical. - Store credentials in an approved password manager. - Do not send passwords through ordinary chat or email. - Keep the number of local administrators small. - Do not disable the only known working administrator account during the first session. - If the server will become a domain controller, complete local-account planning before promotion because domain controllers do not use local accounts in the same way as member servers. Full account lockout, auditing, LAPS, and least-privilege configuration belong in the production hardening phase, not a rushed first-login change set. ## Minutes 23–27: Verify the firewall and RDP rules Windows Firewall should remain enabled on all profiles. Check its state: ```powershell Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction ``` Review the Remote Desktop rule group: ```powershell Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Select-Object DisplayName, Enabled, Direction, Action, Profile | Format-Table -AutoSize ``` At this stage, verify rather than aggressively rewrite the rules. A remote firewall mistake can lock you out. Do not: - disable Windows Firewall to solve a connection problem - open SQL Server, SMB, WinRM, IIS, or custom application ports before the service needs them - expose TCP 445 or database ports broadly to the public internet - restrict RDP to an IP address until you have confirmed the correct source address and recovery path - change several RDP and firewall controls at the same time For the detailed workflow, use [Configure Windows Firewall on a Windows VPS](/windows-server/configure-windows-firewall). ## Verify Microsoft Defender status Check whether Microsoft Defender Antivirus and real-time protection are active: ```powershell Get-MpComputerStatus | Select-Object AntivirusEnabled, RealTimeProtectionEnabled, AntivirusSignatureLastUpdated ``` Update signatures: ```powershell Update-MpSignature ``` If `Get-MpComputerStatus` is unavailable, confirm whether another endpoint-protection product or server image configuration is responsible for antimalware protection. Do not install multiple real-time antivirus products without checking compatibility. This first-pass check does not replace security hardening. Windows Server 2025 supports role-aware Microsoft security baselines through OSConfig, but those settings can change authentication, RDP redirection, SMB, TLS, audit, and application behavior. OSConfig security baselines apply to Windows Server 2025; use a different supported baseline workflow for earlier releases. Test any baseline against the real workload before enforcing it. Use [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) before production. ## Minutes 27–30: Check storage and create a recovery point Review mounted volumes and free capacity: ```powershell Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter, FileSystemLabel, @{Name="FreeGB";Expression={[math]::Round($_.SizeRemaining / 1GB, 2)}}, @{Name="SizeGB";Expression={[math]::Round($_.Size / 1GB, 2)}} ``` Confirm that: - the system volume has enough free space for updates and temporary files - expected data volumes are present - application data will not be placed randomly across user profiles - future database, log, upload, and backup growth has been considered Before installing server roles or business applications, create a snapshot or backup through the available Raff protection workflow. A snapshot is useful for fast rollback before a major change, but it is not a complete long-term backup strategy or an application-aware database backup. Read [Windows VPS Backup Strategy for Small Businesses](/windows-server/windows-vps-backup-strategy-small-business) before the server stores production data. ## Save a baseline record Create a small administration folder and export the starting state: ```powershell $Path = "C:\Admin\Baseline" New-Item -ItemType Directory -Path $Path -Force | Out-Null Get-ComputerInfo | Out-File "$Path\computer-info.txt" Get-NetIPConfiguration | Format-List * | Out-File "$Path\network.txt" Get-NetFirewallProfile | Format-Table Name, Enabled, DefaultInboundAction, DefaultOutboundAction -AutoSize | Out-File "$Path\firewall-profiles.txt" Get-LocalGroupMember -Group "Administrators" | Out-File "$Path\administrators.txt" Get-Volume | Where-Object DriveLetter | Format-Table DriveLetter, FileSystemLabel, SizeRemaining, Size -AutoSize | Out-File "$Path\volumes.txt" ``` This is not a monitoring system. It is a simple before-state that helps with later troubleshooting and change review. Keep critical recovery documentation outside the VPS as well. ## Final verification after the restart Use this checklist after Windows Update or hostname changes restart the server: | Check | Verification | |---|---| | RDP access | Reconnect successfully with the named administrator | | Hostname | `$env:COMPUTERNAME` shows the intended name | | OS version | `Get-ComputerInfo` shows the expected Windows Server edition and build | | Time | `Get-TimeZone` and `w32tm /query /status` are correct | | Updates | No required cumulative update remains waiting without a plan | | Firewall | All intended profiles remain enabled | | Defender | Antivirus and real-time protection report the expected state | | Administrators | Only known accounts have local administrator rights | | Storage | Expected volumes are mounted with adequate free space | | Recovery | A snapshot or backup path exists before major workload changes | | Documentation | Purpose, owner, access method, and change date are recorded | Do not install the production workload until the server can restart and pass this basic verification. ## What not to do in the first 30 minutes Avoid these common first-login mistakes: ### Do not disable Windows Firewall Fix the exact rule or service instead. Disabling the entire firewall removes a core protection layer. ### Do not change the guest network configuration casually An incorrect static IP, gateway, or DNS setting can break remote access. Follow the provider’s networking model. ### Do not expose application ports before installation A port should have a documented service, source, protocol, owner, and reason before it is opened. ### Do not browse and download software as the shared Administrator account Use trusted vendor sources and move toward named administrative and standard-user accounts. ### Do not promote the server to a domain controller without DNS and recovery planning Active Directory changes identity, DNS, local account behavior, and recovery requirements. Treat it as a dedicated project. ### Do not apply a full security baseline blindly Security baselines are valuable, but they can alter application and RDP behavior. Snapshot, test, and apply the baseline for the correct server role. ### Do not treat a snapshot as the only backup Snapshots support rollback. Production recovery also needs retention, off-server copies, application-aware backups, and restore testing where appropriate. ## The first-day work after this checklist The first 30 minutes establish a known starting point. The rest of the first day should be based on the server’s role. | Server role | Next work | |---|---| | Administrative Windows VPS | Restrict RDP, configure logging, and complete hardening | | RDS Session Host | Plan RDS roles, licensing mode, CALs, user profiles, and app publishing | | IIS server | Install IIS, configure HTTPS, deploy the app, and open only TCP 80/443 as required | | SQL Server | Confirm edition and licensing, storage layout, service accounts, backups, and private connectivity | | Domain controller | Confirm domain design, DNS, time hierarchy, backups, and a second-domain-controller plan | | File server | Plan volumes, NTFS and share permissions, SMB exposure, quotas, and backup recovery | | Business application server | Verify vendor support, prerequisites, database requirements, printing, licensing, and restore steps | Complete the production hardening checklist before the server becomes an internet-facing or business-critical system. ## Verification scope This checklist was reviewed against current Microsoft Learn documentation on July 31, 2026. The commands use built-in Windows Server administration tools and are written for a fresh Windows Server 2025 VPS; Microsoft also documents SConfig for Windows Server 2022 and 2019. Provider-specific networking, recovery, and image defaults can vary, so confirm those settings in the Raff dashboard before changing guest networking or access controls. The checklist deliberately avoids workload-specific configuration until the server role is known. :::cta Deploy Windows Now Deploy a Windows VM, complete the first-run checklist, and build from a known baseline. ::: ## What's next - [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) — complete the first connection before this checklist - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) — prepare the server for production - [Configure Windows Firewall on a Windows VPS](/windows-server/configure-windows-firewall) — review and narrow inbound access safely - [Windows VPS Backup Strategy for Small Businesses](/windows-server/windows-vps-backup-strategy-small-business) — build a real recovery plan - [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison) — select the operating system for the workload - [Raff Windows Server Hub](/windows-server) — browse Windows Server deployment, licensing, security, and troubleshooting resources ## Sources - Microsoft Learn — [Configure Server Core with SConfig](https://learn.microsoft.com/en-us/windows-server/administration/server-core/server-core-sconfig) - Microsoft Learn — [Rename-Computer](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/rename-computer) - Microsoft Learn — [Set-TimeZone](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-timezone) - Microsoft Learn — [New-LocalUser](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/new-localuser) - Microsoft Learn — [Add-LocalGroupMember](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/add-localgroupmember) - Microsoft Learn — [Get-NetFirewallProfile](https://learn.microsoft.com/en-us/powershell/module/netsecurity/get-netfirewallprofile) - Microsoft Learn — [Get-MpComputerStatus](https://learn.microsoft.com/en-us/powershell/module/defender/get-mpcomputerstatus) - Microsoft Learn — [Windows Server 2025 security baselines with OSConfig](https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines) - Date last verified: 2026-07-31 --- ### Windows Server Core vs Desktop Experience: Which Should You Choose for a VPS? URL: https://rafftechnologies.com/windows-server/windows-server-core-vs-desktop-experience Description: Compare Windows Server Core and Desktop Experience for a VPS. Choose the right installation option based on workload compatibility, management skills, security, resources, and Remote Desktop requirements. ## In short Choose **Windows Server Core** for a VPS when the required server role and application support it, your team can manage Windows remotely or with PowerShell, and you want the smallest practical operating-system footprint. Choose **Server with Desktop Experience** when the workload requires a local graphical interface, Remote Desktop Session Host, GUI-dependent software, or an operational team that relies on desktop management tools. Microsoft recommends Server Core by default unless you have a specific need for the additional interface and graphical tools included with Desktop Experience. The decision must be made before deployment: Windows Server 2016, 2019, 2022, and 2025 do not support converting between Core and Desktop Experience after installation. Changing later requires a clean installation. For most Raff Technologies customers deploying Windows business software or using the VPS as an interactive Remote Desktop workspace, Desktop Experience is usually the safer choice. For dedicated infrastructure roles such as DNS, DHCP, Active Directory Domain Services, IIS, Hyper-V, or file services, Server Core is often the cleaner option after compatibility and management requirements are verified. ## Quick decision table | Requirement | Better choice | Why | |---|---|---| | Dedicated infrastructure role with remote management | Server Core | Smaller footprint and fewer unnecessary interface components | | RDS Session Host for employee desktop sessions | Desktop Experience | RD Session Host is not included in Server Core | | GUI-dependent accounting, ERP, tax, or legacy software | Desktop Experience | The application or vendor workflow may depend on the desktop shell | | IIS web server managed remotely | Server Core | IIS is supported and can be managed with PowerShell or remote tools | | Active Directory domain controller | Server Core | AD DS is supported and usually does not need a local desktop | | DNS or DHCP server | Server Core | Role-based infrastructure is a strong fit for remote administration | | One administrator learning Windows Server | Desktop Experience | Easier local navigation and troubleshooting | | Automated or standardized server fleet | Server Core | Better fit for repeatable PowerShell and remote-management workflows | | Vendor requires local MMC or GUI administration | Desktop Experience | Reduces compatibility and support risk | | You are unsure whether the software supports Core | Desktop Experience | Reinstalling later is more disruptive than choosing the GUI initially | The best choice is based on workload compatibility first, administrator experience second, and resource savings third. ## What Windows Server Core is Server Core is a minimal installation option for Windows Server Standard and Datacenter. It includes most common server capabilities but does not install the traditional Windows desktop shell. After signing in, you work primarily with: - PowerShell - Command Prompt - SConfig - Windows Admin Center - Remote Server Administration Tools - Server Manager from another Windows machine - remote MMC snap-ins where supported Server Core does not mean the server cannot be reached through Remote Desktop. You can connect over RDP, but the session does not provide the normal desktop, Start menu, or full graphical management environment. You typically see a command-line environment and use SConfig or PowerShell for local tasks. Microsoft describes Server Core as having a smaller disk footprint and a smaller attack surface because fewer components are installed. It still requires updates, firewall rules, secure accounts, backups, monitoring, and hardening. A reduced footprint is an advantage, not a complete security strategy. ## What Server with Desktop Experience is Server with Desktop Experience installs the standard graphical Windows Server interface and the complete local management environment. It includes: - the Windows desktop shell - Start menu and File Explorer - Server Manager - Microsoft Management Console - graphical role and feature tools - graphical Windows Update and Settings workflows - broader application compatibility - local GUI troubleshooting tools Desktop Experience is normally easier for administrators who manage one or a few Windows VPS instances directly through RDP. It is also the practical choice for software that expects an interactive desktop, graphical installers, tray applications, locally opened management consoles, or regular end-user sessions. The trade-off is a larger operating-system footprint and more installed components than Server Core. ## Core differences at a glance | Area | Server Core | Desktop Experience | |---|---|---| | Local interface | PowerShell, Command Prompt, SConfig | Full graphical desktop | | Server Manager locally | No | Yes | | Remote management | Yes | Yes | | Windows Admin Center | Supported | Supported | | RSAT and remote MMC | Supported for applicable tools | Supported | | Disk footprint | Smaller | Larger | | Installed components | Fewer | More | | Application compatibility | More limited | Broadest Windows Server compatibility | | Local troubleshooting | Command-line focused | GUI and command-line tools | | Attack surface | Reduced by smaller code base | Larger because more components are installed | | RDS Session Host | Not included | Supported | | Switching after installation | Clean reinstall required | Clean reinstall required | The resource difference is real, but it should not override application or role requirements. ## The most important rule: you cannot switch later Modern Windows Server versions do not support converting an existing installation from Server Core to Desktop Experience or from Desktop Experience to Server Core. This means the following is not a normal in-place change: ```text Server Core → Desktop Experience Desktop Experience → Server Core ``` To change the installation option, plan a replacement or clean installation: 1. Create a backup and document the current configuration. 2. Deploy a new VPS or reinstall the existing one. 3. Install the correct Windows Server option. 4. Recreate roles, applications, users, certificates, firewall rules, and scheduled tasks. 5. Restore or migrate data. 6. Test the workload. 7. Cut over and retain a rollback path. This is why uncertainty should be resolved before production. If a critical application has not been validated on Server Core, Desktop Experience is usually the lower-risk initial choice. ## Security and patching differences Server Core removes the desktop shell and other components that are not required for supported server roles. Fewer installed components generally mean fewer components to configure, service, and expose. Potential Server Core advantages include: - smaller operating-system footprint - fewer locally installed graphical components - reduced attack surface - fewer unnecessary services for role-based servers - cleaner standardization for automation However, Server Core is not automatically secure. It still needs: - current Windows updates - Microsoft Defender or another approved security product - Windows Firewall enabled - restricted administrator access - secure remote-management configuration - logging and monitoring - backups and restore testing - role-specific hardening Desktop Experience can also be secured effectively. Its larger component set means there is more software to maintain, but the correct security choice is the option your team can operate reliably without unsafe workarounds. A poorly managed Server Core VPS is not safer than a well-managed Desktop Experience VPS. ## Resource usage on a VPS Server Core uses less disk space because the desktop shell and several graphical components are not installed. It may also reduce background activity associated with those components. That does not mean every workload will run dramatically faster. Application CPU, memory, storage, database, antivirus, and user-session requirements usually matter more than the interface choice. Use the resource difference this way: | Situation | How much the smaller footprint matters | |---|---| | Small dedicated DNS, DHCP, or domain controller | Useful | | Large automated fleet | Useful at scale | | IIS server with no local GUI dependency | Useful | | SQL or application server dominated by workload demand | Secondary factor | | RDS server with many interactive users | Desktop Experience is required regardless | | Business software that needs a GUI | Compatibility matters more than savings | Do not choose Server Core merely to fit a production workload into an under-sized VPS. Size the VPS for the actual server role and application load. ## Management experience on Server Core Server Core is easiest when you manage the VPS remotely instead of treating RDP as the primary graphical management interface. Microsoft supports several management methods: ### SConfig Run: ```powershell SConfig ``` SConfig provides a menu for common setup tasks such as: - computer name - domain or workgroup membership - local administrators - Windows Update settings - Remote Desktop - network settings - date and time - activation - restart and shutdown ### PowerShell PowerShell is the main local and remote administration interface. Examples: ```powershell # Display operating-system information Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsBuildNumber # List installed roles and features Get-WindowsFeature | Where-Object InstallState -eq "Installed" # Check services Get-Service | Sort-Object Status, DisplayName # Review firewall profiles Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction ``` ### Windows Admin Center Windows Admin Center provides browser-based administration for Windows Server. It can manage Server Core without installing a traditional desktop on the target server. ### RSAT, Server Manager, and MMC A Windows client or another Windows Server with Desktop Experience can manage Server Core remotely using supported tools. This allows administrators to retain graphical management without installing the GUI on every server. Server Core is therefore not “PowerShell only,” but it assumes remote-management discipline. ## Application Compatibility Feature on Demand Windows Server 2019, 2022, and 2025 support the Server Core Application Compatibility Feature on Demand. This optional package adds a subset of binaries and tools from Desktop Experience to improve compatibility and troubleshooting on Server Core. Depending on the version and configuration, it can provide tools such as Microsoft Management Console components, File Explorer, Event Viewer, Disk Management, Device Manager, Performance Monitor, and other compatibility files. It does not convert Server Core into Desktop Experience. The complete Windows desktop shell is still not installed. Use the feature when: - an otherwise supported application needs specific compatibility components - a management tool requires MMC components - troubleshooting requires an additional local utility - the workload is still intended to operate as Server Core Do not use it as a workaround for an application that fundamentally requires the full desktop shell. Confirm vendor support before production. ## Workloads that fit Server Core well Server Core is usually a strong choice for dedicated, remotely managed infrastructure roles. ### Active Directory Domain Services A domain controller normally does not need users browsing locally or running desktop applications. AD DS can be managed through PowerShell, RSAT, Windows Admin Center, and remote tools. ### DNS and DHCP DNS and DHCP are role-based services with mature remote-management options. They are natural Server Core candidates when the administrator has a reliable management path. ### IIS web server IIS is available on Server Core. It can host supported web workloads and be managed through PowerShell, configuration files, deployment automation, or remote IIS tools. Confirm that the application does not require desktop-only components or an unsupported framework dependency. ### Hyper-V Hyper-V is a classic Server Core workload because the virtual machines can be managed remotely. The host itself does not need a local graphical desktop for normal operation. ### File and storage services A dedicated file server can run on Server Core when permissions, shares, storage, backups, and monitoring are managed through supported remote or command-line tools. ### Automated infrastructure Server Core fits environments where deployment, configuration, patching, and monitoring are standardized through scripts or configuration management. ## Workloads that usually need Desktop Experience Desktop Experience is the better choice when people or software need the local graphical environment. ### Remote Desktop Session Host Do not choose Server Core for an employee Remote Desktop desktop server. Microsoft does not include the RD Session Host role service in Server Core. If users need regular desktop or RemoteApp sessions, use Desktop Experience and plan RDS roles, licensing, profiles, security, and sizing. ### GUI-dependent business software Accounting, tax, ERP, inventory, legal, trading, and legacy applications may rely on: - graphical installers - desktop shell components - tray applications - local printers or redirected devices - interactive user sessions - GUI administration consoles - vendor support procedures based on the desktop Even when an application technically starts on Server Core, vendor support matters. Use Desktop Experience unless the vendor explicitly supports Server Core and the complete workflow has been tested. ### One-server environments managed mainly through RDP A small business or administrator managing one Windows VPS may gain more from a familiar graphical interface than from Server Core’s smaller footprint. ### Local troubleshooting requirements If support teams regularly use Event Viewer, Services, Device Manager, browser-based vendor portals, GUI database tools, or locally installed support utilities, Desktop Experience reduces operational friction. ## Workload compatibility matrix | Workload | Server Core | Desktop Experience | Recommendation | |---|---:|---:|---| | Active Directory Domain Services | Yes | Yes | Prefer Core when remote management is established | | DNS Server | Yes | Yes | Prefer Core for a dedicated role | | DHCP Server | Yes | Yes | Prefer Core for a dedicated role | | IIS web server | Yes | Yes | Core when application dependencies support it | | Hyper-V host | Yes | Yes | Core is often the better operational model | | File server | Yes | Yes | Core when no local GUI tools are required | | Windows Update Services | Yes | Yes | Core can fit with remote administration | | RDS Session Host | No | Yes | Use Desktop Experience | | Interactive employee desktop | No | Yes | Use Desktop Experience | | GUI-dependent third-party app | Depends | Yes | Prefer Desktop Experience unless vendor supports Core | | Legacy Windows application | High compatibility risk | Broadest compatibility | Prefer Desktop Experience | | Local desktop administration | Limited | Full | Use Desktop Experience | | Scripted server fleet | Strong fit | Possible | Prefer Core when roles support it | Always verify the exact role service, application version, installer, monitoring agent, backup agent, and security software before choosing Core. ## Server Core for IIS and web hosting Server Core can be a good IIS platform because the server can be managed remotely and the web workload does not normally need an interactive desktop. A good Core-based IIS deployment has: - a supported .NET and application stack - automated deployment - remote log access - remote IIS or PowerShell administration - external monitoring - documented certificate renewal - tested backup and rollback Desktop Experience is safer when the application uses: - a GUI-only installer - desktop automation - locally launched browser components - COM or shell dependencies that have not been validated - vendor support tools that require the desktop The question is not whether IIS itself works on Core. It does. The question is whether the entire application stack works and is supportable. ## Server Core for Active Directory A Server Core domain controller reduces unnecessary local components on an identity-critical server. This is valuable when administrators already use RSAT, PowerShell, and remote management. Choose Desktop Experience for a domain controller only when there is a clear operational requirement. Do not install unrelated business software or allow regular users to work interactively on a domain controller regardless of the installation option. Before deployment, confirm: - DNS design - time synchronization - backup and system-state recovery - a second-domain-controller plan - remote administration access - monitoring and event collection - recovery credentials The Core-versus-GUI decision does not replace proper Active Directory architecture. ## Server Core for small businesses Server Core is technically attractive, but the operational model must match the business. A small company should choose Core when: - an MSP or experienced administrator manages the server - the workload is a supported infrastructure role - PowerShell or remote management is already standard - the application vendor supports Core - monitoring and backups are remote and documented A small company should choose Desktop Experience when: - the owner or general IT administrator manages through RDP - the server hosts interactive business applications - users need desktop sessions - vendor support expects a GUI - troubleshooting skills are mainly graphical - there is no separate management workstation or gateway The best installation is the one that can be maintained safely during an incident. ## Decision framework for a VPS Answer these questions in order. ### 1. Does the required role exist on Server Core? Check Microsoft’s current Server Core role and feature list. Some roles are available while specific role services are not. If the role service is unavailable, choose Desktop Experience. ### 2. Does the application vendor support Server Core? Do not rely only on whether the installer launches. Verify the full production stack, including updates, backup agents, security tools, monitoring, printers, licensing services, and support procedures. If support is unclear, choose Desktop Experience or test on a disposable VM before committing. ### 3. Do users need an interactive desktop? If employees will work inside the server, use Desktop Experience and the correct RDS licensing model. If only administrators connect, Core may still be appropriate. ### 4. Can the team manage the server remotely? Core is a strong fit when Windows Admin Center, RSAT, PowerShell remoting, monitoring, and recovery access are already established. If the only management method is opening RDP and clicking through local tools, Desktop Experience is safer. ### 5. Can you recover without the local GUI? Document: - provider console and password recovery - network recovery path - backup restore steps - remote-management credentials - firewall rollback - application reinstall process Choose Core only when command-line and remote recovery are realistic for the team. ## Common mistakes ### Choosing Core only to save RAM The operating-system footprint is smaller, but application compatibility and operational readiness matter more. Do not use Core to compensate for an under-sized VPS. ### Assuming RDP provides a normal desktop on Core RDP access can be enabled, but the session remains a Server Core environment without the full Windows desktop shell. ### Assuming every Windows application works on Core Server roles and applications have different requirements. Verify vendor support and the complete dependency chain. ### Planning to add the GUI later You cannot convert the installed option. A change requires a clean installation or replacement server. ### Treating Desktop Experience as insecure by definition Desktop Experience has more components, but security depends on patching, access control, firewall rules, backups, monitoring, and operations. ### Treating Core as automatically hardened A smaller attack surface does not prevent weak passwords, exposed RDP, excessive privileges, outdated software, or missing backups. ### Using Server Core for an RDS desktop server RD Session Host is not included in Server Core. Use Desktop Experience for regular employee desktop sessions. ## Recommended choice by scenario | VPS scenario | Recommended option | |---|---| | First Windows VPS for a general administrator | Desktop Experience | | RDP workspace for one or more users | Desktop Experience | | Accounting, ERP, tax, or legacy app server | Desktop Experience unless vendor verifies Core | | Dedicated IIS web server | Server Core after dependency validation | | Dedicated domain controller | Server Core | | DNS or DHCP server | Server Core | | Hyper-V host | Server Core | | File server managed by an MSP | Server Core after agent compatibility checks | | Small office server with mixed roles | Desktop Experience, although separating roles is better | | Automated multi-server environment | Server Core where supported | | Proof of concept with unknown requirements | Desktop Experience or test both options before production | ## What Raff recommends For a Windows VPS used as an interactive server, business-software host, or Remote Desktop workspace, start with Desktop Experience. It provides the broadest compatibility and the simplest administration model for small teams. Choose Server Core when all four conditions are true: 1. The exact server role is supported. 2. Every required application and agent supports Core. 3. The administrator can manage and recover the server remotely. 4. No users need a normal Windows desktop session. This approach captures the security and footprint benefits of Core without creating avoidable compatibility or support problems. :::cta Deploy Windows Now Deploy the Windows VM that matches your application, management model, and Remote Desktop requirements. ::: ## Verification scope This decision guide was reviewed against Microsoft Learn documentation current on July 31, 2026. It applies to Windows Server 2025, 2022, 2019, and 2016 installation options. Role and application support can change by Windows Server version and software release, so verify the exact role service and vendor support before production deployment. ## What's next - [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist) — establish the first-login baseline after deployment - [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison) — choose the Windows Server release - [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) — connect to a Desktop Experience or Server Core VM - [25 PowerShell Commands Every Windows VPS Admin Needs](/windows-server/powershell) — build the command-line skills needed for Server Core - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) — secure the server before production - [Raff Windows Server Hub](/windows-server) — browse Windows Server deployment and administration resources ## Sources - Microsoft Learn — [Server Core vs Server with Desktop Experience install options](https://learn.microsoft.com/en-us/windows-server/get-started/install-options-server-core-desktop-experience) - Microsoft Learn — [What is the Server Core installation option?](https://learn.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core) - Microsoft Learn — [Manage a Server Core server](https://learn.microsoft.com/en-us/windows-server/administration/server-core/server-core-manage) - Microsoft Learn — [Roles, role services, and features included in Server Core](https://learn.microsoft.com/en-us/windows-server/administration/server-core/server-core-roles-and-services) - Microsoft Learn — [Roles, role services, and features not in Server Core](https://learn.microsoft.com/en-us/windows-server/administration/server-core/server-core-removed-roles) - Microsoft Learn — [Install the Server Core Application Compatibility Feature on Demand](https://learn.microsoft.com/en-us/windows-server/get-started/server-core-app-compatibility-feature-on-demand) - Date last verified: 2026-07-31 --- ### Local Office Server to Cloud Windows VPS Migration URL: https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration Description: Plan a local office server to cloud Windows VPS migration for small businesses, including apps, files, users, RDP/RDS, backups, testing, cutover, and rollback. A local office server to cloud Windows VPS migration helps small businesses move files, business apps, Remote Desktop access, databases, and backups away from one physical office machine into a cloud-hosted Windows Server environment. The safest approach is a side-by-side migration: inventory the old server, build the new Windows VPS, test users and apps, run final sync, cut over carefully, and keep rollback ready. Raff Technologies provides Windows VMs for teams that want a cloud Windows Server destination for remote access, shared workloads, and office server replacement. A local server can work well for years. Then the business changes. People work from home, a second location opens, the server hardware ages, backups become unclear, and the office internet or power becomes a single point of failure. Moving to a cloud Windows VPS can reduce dependence on one office server, but the migration should not be rushed. The server may hold file shares, accounting software, Microsoft Access databases, SQL Server, Remote Desktop users, printers, certificates, scheduled tasks, DNS records, and vendor software. A clean migration plan protects the business from downtime, broken access, and data loss. ## Quick verdict: when local server to cloud migration makes sense Use this table before moving an office server to a cloud Windows VPS. | Situation | Cloud Windows VPS fit | Why | |---|---|---| | The office server is aging or out of warranty | Strong fit | Avoids buying and maintaining another physical server. | | Users need access from home or multiple offices | Strong fit | A cloud Windows Server is easier to reach from different locations. | | Business apps run on Windows Server | Strong fit after testing | Apps can run in a centralized Windows environment. | | File shares need better backup planning | Good fit | One central server can have clearer backup and restore policy. | | Staff need Remote Desktop access | Good fit with RDS planning | RDP/RDS access should be designed before migration. | | The server hosts SQL Server or app databases | Depends | Database migration, backups, and app testing need separate planning. | | The business relies on local USB devices | Depends | Scanners, dongles, label printers, and serial devices must be tested. | | Branch internet is unreliable | Risky | Cloud-hosted access depends on connectivity. | | The workload needs high availability | Not a single VPS decision | Plan redundancy, failover, and architecture first. | The best fit is a small business that wants to replace local server hardware while keeping a familiar Windows Server environment for apps, files, and remote users. :::cta Talk to Windows Engineer Need help planning a local office server migration? Talk to Raff before moving production users, apps, files, and databases. ::: ## What changes when the office server moves to the cloud A local office server usually lives in one branch: a closet, cabinet, back office, or small server room. Users reach it through the local network, mapped drives, Remote Desktop, VPN, or nearby workstations. A cloud Windows VPS changes the operating model. | Area | Local office server | Cloud Windows VPS | |---|---|---| | Server location | Inside one office | Hosted in the cloud | | Hardware responsibility | Business owns and replaces hardware | Cloud VM replaces the physical server role | | Remote access | VPN, office firewall, or ad hoc RDP | RDP/RDS/RD Gateway/VPN can be designed from the start | | File access | LAN shares or mapped drives | RDP/RDS access, VPN/private access, or controlled SMB pattern | | Business apps | Installed on local server or office PCs | Centralized on Windows VPS where supported | | Backups | Often local, manual, or inconsistent | VM backups, snapshots, file/app backups, and off-server copies | | Downtime risk | Office power, hardware, and internet can block work | Users can connect from other locations if local office is down | | Scaling | Buy or replace hardware | Resize VM or split workloads | Cloud does not remove responsibility. The business or MSP still needs Windows updates, app support, user access, security, backups, restore testing, and documentation. The difference is that the server is no longer tied to one physical office. ![Comparison visual showing local office server model versus cloud Windows VPS model for users, apps, files, and backups](https://raff-images.s3.raffusercloud.com/local_server_vs_cloud_windows_vps_operating_model_webp_cc659df50a.png) ## Local server migration is not just file copy A common mistake is treating migration as “copy files from old server to new server.” That misses the parts that actually break business workflows. Migration can involve: | Migration area | Examples | |---|---| | Users and access | Local users, domain users, admin accounts, groups | | File shares | SMB shares, NTFS permissions, mapped drives, folder ownership | | Business apps | Accounting, tax, ERP, inventory, Access, legacy tools | | Databases | SQL Server, app databases, Access back ends, vendor data | | Remote access | RDP, RDS, RD Gateway, VPN, firewall rules | | Printers and devices | Label printers, scanners, PDF printers, USB devices | | Scheduled tasks | Reports, exports, sync jobs, maintenance scripts | | Certificates | IIS, RD Gateway, internal app certificates | | DNS and names | Server names, IPs, records, app connection strings | | Backups | Source backup, destination backup, off-server copies, restore test | If the old server has been running for years, assume it has hidden dependencies until proven otherwise. ## Choose side-by-side migration for safer cutover Microsoft describes several Windows Server move/upgrade methods, including in-place upgrade, clean install, migration, cluster rolling upgrade, and edition conversion. Each method has trade-offs for downtime, complexity, and hardware requirements. For local server to cloud Windows VPS migration, side-by-side migration is usually the safer pattern. ```text Old local server stays online → New Windows VPS is built → Apps, files, and users are tested → Final data sync happens → Users cut over → Old server stays available for rollback ``` This approach is safer than changing the old server in place because the business can test the new environment before production users depend on it. ![Architecture visual showing side-by-side migration from a local office server to a cloud Windows VPS](https://raff-images.s3.raffusercloud.com/local_server_cloud_vps_side_by_side_migration_webp_8767b51646.png) ## Step 1: inventory the old office server Start with discovery. Do not migrate what you cannot describe. Document: | Area | What to capture | |---|---| | Server basics | Name, OS version, IP address, domain/workgroup status | | Server roles | File server, AD DS, DNS, DHCP, RDS, IIS, SQL Server, print server | | Applications | App name, version, install path, vendor support, license info | | Users | Admins, staff users, groups, service accounts | | File shares | Share names, folder paths, NTFS permissions, mapped drives | | Databases | SQL instances, databases, jobs, logins, maintenance plans | | Scheduled tasks | Reports, exports, backups, scripts, sync jobs | | Devices | Printers, scanners, label printers, USB dongles, serial devices | | Certificates | IIS, RD Gateway, VPN, internal application certificates | | Backups | Tool, schedule, destination, retention, last successful restore | | Integrations | APIs, email SMTP, accounting exports, warehouse tools | The output should be a migration map, not a vague note that says “move server data.” ## Step 2: decide what should move, rebuild, or retire A migration is a good chance to clean up the old server. Do not move years of clutter into the new environment automatically. Sort items into four groups: | Group | Meaning | |---|---| | Move | Still active and should migrate to the Windows VPS | | Rebuild | Still active, but should be installed/configured cleanly | | Replace | Better handled by SaaS, managed service, or a newer architecture | | Retire | Old, unused, duplicate, or risky; should not move | Examples: | Old server item | Possible decision | |---|---| | Active shared company folders | Move | | Accounting software data | Move or rebuild with vendor guidance | | Old employee desktops | Archive or retire | | Duplicate backup zip files | Retire after confirmed backup | | SQL Server database | Move with backup/restore test | | Legacy Access app | Test before moving | | Print server role | Move only if still needed | | Unused installers | Retire | | Old user accounts | Disable or exclude | The goal is not only to migrate. It is to make the new environment cleaner than the old one. ## Step 3: size the cloud Windows VPS Size the destination based on users, apps, storage, and growth. Do not size only by the old server specs. Use this starting model: | Workload | Starting size | When to move up | |---|---:|---| | 1 admin or light app user | 2 vCPU / 4 GB RAM | If apps or reporting tools run on the server | | 3 light remote users | 4 vCPU / 8 GB RAM | If users run Office apps, browser tools, or PDFs | | 3 business app users | 4 vCPU / 16 GB RAM | If accounting, Access, tax, or legacy apps run daily | | 5 active users | 4 vCPU / 16 GB RAM | If users stay logged in through RDP/RDS all day | | 10 active users | 8 vCPU / 32 GB RAM | If the VPS becomes a shared workplace | | SQL/ERP/heavy business app | 8-16 vCPU / 32-64 GB RAM | If database, reports, and users compete for resources | Plan storage separately. Include production files, app data, database files, user profiles, logs, backups, reports, exports, and at least 12 to 24 months of expected growth. :::cta View Pricing Compare Raff Windows VM plans when sizing CPU, memory, storage, and monthly cost for a local server to cloud migration. ::: ## Step 4: plan user access before migration Remote access should be designed before users move. Use this model: | Access need | Planning direction | |---|---| | One or two admins manage the VPS | Restricted admin RDP can work | | Staff need daily desktop sessions | Plan RDS Session Host and RDS CALs | | Users connect from different locations | Consider RD Gateway or another controlled access layer | | Users need mapped file shares from endpoints | Use VPN/private access or a supported SMB pattern | | Users only need a web application | Do not expose full desktop access unnecessarily | | MSP manages the server | Standardize access, monitoring, and documentation | Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs an RDS Client Access License. If staff use the new VPS as a daily desktop environment, licensing must be addressed before production. Direct RDP can be fine for administrator access. It should not become the default plan for every business user without security review. ## Step 5: back up the old server before touching it Before you change anything, protect the source environment. Create and verify: | Backup item | Why | |---|---| | Full server backup | Recover if migration work damages the old server | | File backup | Restore shares and user files | | Database backup | Recover SQL or app database cleanly | | System state backup | Important if AD or server roles are involved | | App-specific backup | Required for accounting, ERP, tax, Access, and vendor apps | | Configuration export | IIS, firewall rules, certificates, scheduled tasks, app configs | | Restore test | Proves backup is usable | A backup that has never been restored is not proof. Test at least one file restore, one folder restore, and one business-critical app or database restore before cutover. ## Step 6: build the cloud Windows VPS cleanly Build the destination before moving production data. Prepare: | Item | Checklist | |---|---| | Windows Server version | Choose a supported version for apps and roles | | VM size | Match expected users, app load, and storage growth | | Admin users | Use named admin accounts | | Firewall | Allow only required access paths | | RDP/RDS/RD Gateway | Configure according to access model | | Updates | Patch Windows before production cutover | | Security | Apply baseline hardening before users connect | | Monitoring | Track CPU, RAM, disk, backups, failed logins | | Backups | Enable backup policy before production data is moved | | Documentation | Record server name, IPs, access, roles, and owners | Do not move production data into an unfinished server. The destination should be patched, secured, backed up, and documented before cutover. ## Step 7: migrate files and permissions carefully File migration is one of the most visible parts of an office server move. Users care about folder names, mapped drives, and whether they can find their files Monday morning. For file shares, check: | File migration item | What to verify | |---|---| | Share names | Keep, rename, or simplify deliberately | | NTFS permissions | Preserve or redesign permissions | | Share permissions | Confirm effective access | | Security groups | Use groups instead of per-user permissions | | Mapped drives | Update GPO, scripts, shortcuts, or user instructions | | Long paths | Identify files that may fail to copy | | Open files | Schedule final copy during low activity | | Archive folders | Avoid moving unnecessary clutter | | Backup | Confirm destination file backup policy | Microsoft’s Storage Migration Service can inventory servers, transfer data to newer Windows servers or Azure virtual machines, and optionally transfer server identity so apps and users can access data without changing links or paths. That makes it relevant when the migration scope is primarily file server data. ![File migration visual showing shared folders, NTFS permissions, mapped drives, and final sync moving from local server to Windows VPS](https://raff-images.s3.raffusercloud.com/local_server_file_share_migration_to_windows_vps_webp_c8c613e56e.png) ## Step 8: migrate business applications with vendor support in mind Business applications are often more complex than files. Before migration, confirm: | App item | What to check | |---|---| | Installer | Do you have the installer and version? | | License | Does the license allow VM/cloud/RDS use? | | Vendor support | Will the vendor support this deployment? | | Data path | Where does the app store production data? | | Service accounts | Which accounts run services or jobs? | | Dependencies | .NET, ODBC, runtimes, drivers, Office/Access runtime | | Printer workflow | Reports, PDFs, labels, and print drivers | | Device workflow | Scanners, USB, serial, barcode, label devices | | Firewall | Required ports and outbound connections | | Rollback | How to return to the old app if testing fails | Do not judge success by whether the app launches. Test real workflows: create a record, run a report, print, export, import, email, sync, and close the day. ## Step 9: migrate SQL Server and databases separately SQL Server migration needs its own plan. Copying database files manually is not the same as a validated migration. For SQL Server, check: | SQL item | What to plan | |---|---| | Instances | Default and named instances | | Databases | Size, recovery model, compatibility level | | Logins | SQL logins, Windows logins, orphaned users | | Jobs | SQL Agent jobs, maintenance, alerts | | Backups | Full, differential, and log backups where needed | | Connection strings | Apps may point to old server name or IP | | Firewall | SQL ports and app connectivity | | Permissions | Database users, roles, and ownership | | Restore test | Confirm the application works after restore | Microsoft documents copying SQL Server databases by backup and restore, and its SQL Server backup/restore guidance covers backup strategies and security considerations. For many SMB migrations, backup/restore is a clean way to test the database on the new server before cutover. If the old office server hosts SQL Server, test the app against the restored database on the Windows VPS before moving users. ## Step 10: handle Active Directory and DNS carefully If the old local server is a domain controller, DNS server, DHCP server, or FSMO role holder, migration needs extra caution. Check: | AD/DNS item | What to verify | |---|---| | Domain controller role | Is the old server a DC? | | DNS | Do clients and apps rely on this server for DNS? | | DHCP | Does it assign IP addresses? | | FSMO roles | Which server holds each role? | | GPOs | Logon scripts, mapped drives, security policy | | Users/groups | Active users, stale accounts, service accounts | | Replication | AD health before migration | | Time sync | Domain time source | | Decommission plan | How the old server will be removed safely | Microsoft provides documentation for transferring FSMO roles in Active Directory Domain Services. If AD is involved, treat this article as the planning guide and use a dedicated AD migration plan for the technical steps. :::cta Talk to Windows Engineer Review Active Directory, DNS, file shares, SQL Server, RDS, and business app dependencies before cutting over your migration. ::: ## Step 11: test from real user locations A local-to-cloud migration changes network paths. Test from where people actually work. Test: | Test area | Example | |---|---| | Office users | Users in the main office can connect and work | | Remote users | Users at home or branch locations can connect | | Admin access | Admin RDP or support access works | | RDS sessions | Users can sign in, work, and sign out | | File access | Users can open, edit, save, and find files | | App workflows | Business apps complete normal tasks | | Database access | Apps connect to SQL or other data stores | | Reports | Reports generate and export correctly | | Printing/scanning | Printers, PDFs, labels, scanners work | | Backups | Destination backup jobs complete | | Restore | At least one restore test succeeds | Do not let only the IT admin test the system. Include the users who actually run the daily workflows. ## Step 12: schedule cutover and final sync Cutover is where planning becomes execution. A practical cutover sequence: 1. Announce the downtime window. 2. Confirm latest source backup. 3. Freeze writes on the old server. 4. Stop app services or user access if needed. 5. Run final file sync. 6. Restore or attach final database copy. 7. Update DNS, mapped drives, shortcuts, or connection strings. 8. Start services on the Windows VPS. 9. Test admin login. 10. Test user login. 11. Test files, apps, reports, printing, and backups. 12. Confirm users can work. 13. Keep the old server available but controlled. 14. Monitor the first workday closely. The best cutover is boring. Everyone knows the order, the rollback trigger, and who owns each step. ## Step 13: keep rollback ready Rollback is not a sign of failure. It is a safety plan. Define: | Rollback item | Question | |---|---| | Trigger | What problem forces rollback? | | Owner | Who makes the rollback decision? | | Timing | How long after cutover is rollback still practical? | | Data state | How will new writes be handled? | | Old server | Is it intact and reachable? | | DNS/access | How do users return to old paths? | | Communication | Who tells users what to do? | Do not wipe the old server immediately after the first successful login. Keep it available until the new cloud environment is proven stable. ## Step 14: monitor after migration The first week after migration matters. Monitor: | Signal | Why | |---|---| | CPU | Detect undersizing or app spikes | | RAM | Identify RDS or app pressure | | Disk free space | Prevent file, profile, and backup failures | | Backup success | Confirm protection is working | | Failed logins | Detect access issues or attacks | | Event logs | Catch services, drivers, and app errors | | SQL jobs | Confirm database maintenance and backups | | Scheduled tasks | Ensure reports and exports still run | | User complaints | Reveal real workflow bottlenecks | | RDP/RDS sessions | Understand peak concurrent usage | Migration is complete only when the new environment is stable, backed up, documented, and users can complete real work. ## Local server to cloud migration checklist by workload Different workloads need different checks. | Workload | Migration focus | |---|---| | File server | Shares, NTFS permissions, mapped drives, backup, final sync | | RDP/RDS server | User profiles, RDS CALs, RD Gateway, printers, performance | | SQL Server | Backup/restore, logins, jobs, connection strings, app testing | | Active Directory | DC health, DNS, FSMO, GPOs, replication, decommission | | Accounting software | Vendor support, data path, printers, backups, user testing | | Access/legacy apps | File paths, split design, RDP/RDS testing, backups | | Tax software | Seasonal users, client files, vendor support, backups | | ERP/inventory | Database, reports, integrations, devices, warehouse workflows | | IIS/.NET | Sites, app pools, certificates, bindings, web.config, databases | A local server migration is rarely one thing. It is usually several small migrations inside one project. ## How Raff fits local server to cloud migration Raff fits this use case when a small business wants to replace a local Windows Server with a cloud Windows VPS for remote users, business apps, shared files, databases, and centralized access. Raff Windows VMs can serve as the destination for office server replacement, Remote Desktop environments, cloud file servers, SQL Server tools, Access and legacy apps, tax software, ERP/inventory workloads, and MSP-managed client environments. The Raff Windows Server migration page also organizes migration guidance for teams moving Windows workloads to newer or cloud-hosted environments. Raff is not a replacement for vendor support, licensing review, or application testing. The clean model is: use Raff for the Windows VM infrastructure, then migrate with a clear plan for users, apps, files, databases, access, backups, cutover, and rollback. :::cta Explore Data Protection Protect your local server migration with backup, snapshot, and restore planning before moving production workloads. ::: ## Final pre-cutover checklist Before production cutover, confirm: | Check | Done | |---|---| | Source backup completed | ☐ | | Source restore test completed | ☐ | | Destination Windows VPS built and patched | ☐ | | Destination backups enabled | ☐ | | Users and admins documented | ☐ | | RDP/RDS/RD Gateway access tested | ☐ | | RDS CAL requirements reviewed | ☐ | | File shares copied and permissions verified | ☐ | | Apps installed and tested | ☐ | | SQL databases restored and app-tested | ☐ | | Printers/scanners/reports tested | ☐ | | DNS/mapped drives/connection strings planned | ☐ | | Cutover window approved | ☐ | | Rollback plan written | ☐ | | Old server preserved after cutover | ☐ | | Post-migration monitoring assigned | ☐ | ![Pre-cutover checklist visual for moving a local office server to a cloud Windows VPS](https://raff-images.s3.raffusercloud.com/local_server_cloud_vps_cutover_checklist_webp_ede0671677.png) If any line is unclear, pause before moving production users. :::cta Deploy Windows Now Create a Raff Windows VM when your team is ready to move Windows workloads from local office hardware to the cloud. ::: ## What's next - Review Raff’s [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) if you are planning a migration. - Read [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) for the full planning checklist. - Read [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) if you are still deciding whether to replace local hardware. - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing CPU, RAM, and storage. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production data. - Read [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) before exposing remote access. - Read [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) if file shares are part of the move. - Review [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) and [pricing](https://rafftechnologies.com/pricing) when planning the destination server. ## Sources - Microsoft Learn — [Plan Your Windows Server Upgrade Path](https://learn.microsoft.com/en-us/windows-server/get-started/install-upgrade-migrate) - Microsoft Learn — [Upgrade and migrate roles and features in Windows Server](https://learn.microsoft.com/en-us/windows-server/get-started/upgrade-migrate-roles-features) - Microsoft Learn — [Storage Migration Service overview](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/overview) - Microsoft Learn — [Migrate a file server by using Storage Migration Service](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/migrate-data) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [Back up and restore of SQL Server databases](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/back-up-and-restore-of-sql-server-databases) - Microsoft Learn — [Copy databases with backup and restore](https://learn.microsoft.com/en-us/sql/relational-databases/databases/copy-databases-with-backup-and-restore) - Microsoft Learn — [Transfer FSMO roles in Active Directory Domain Services](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/manage-fsmo-roles) - Microsoft Learn — [Backup and Storage overview for Windows Server](https://learn.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/backup-and-storage-overview) - Raff — [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) --- ### Windows VPS for Multi-Location Small Businesses URL: https://rafftechnologies.com/windows-server/windows-vps-multi-location-business Description: Learn when a Windows VPS makes sense for multi-location small businesses, including remote access, shared apps, files, backups, RDS, and security. ## In short A Windows VPS can help multi-location small businesses centralize Windows apps, shared files, Remote Desktop access, and backups instead of maintaining a separate server in every office. It works best when users need the same Windows environment from different branches, home offices, or client sites. Raff Technologies provides Windows VMs for teams that need a cloud-hosted Windows Server, but user count, latency, RDS licensing, security, backups, and application behavior must be planned before production. Multi-location businesses often grow into infrastructure complexity without planning for it. One office starts with a local server. A second office joins through VPN. A third location starts copying files manually. Remote users ask for access. Then business software, shared folders, accounting data, legacy apps, and support responsibilities become harder to manage. A Windows VPS can simplify that model by giving the business one cloud-hosted Windows Server environment instead of several small office servers. But centralization only works when the access model, storage plan, backup strategy, and user workflow are clear. ## Quick verdict: when a Windows VPS fits multiple offices Use this table before centralizing a multi-location Windows workload. | Business situation | Windows VPS fit | Why | |---|---|---| | Multiple offices need the same Windows app | Good fit | A centralized Windows environment reduces app duplication across branches. | | Branch users need Remote Desktop access | Good fit with RDS planning | Users can connect to one server instead of one office machine. | | Offices share files, reports, or exports | Good fit with file server planning | Shared folders can be centralized with permissions and backups. | | Business is replacing an aging office server | Good fit | Avoids buying another physical server for each location. | | Remote users connect from changing locations | Good fit with secure access planning | RD Gateway, RDS, VPN, or controlled access can be designed. | | Large files move constantly inside each office | Depends | Local storage may still be better for heavy LAN file workflows. | | Internet is unreliable at branch locations | Risky | Cloud access depends on connectivity. | | Strict compliance or data-residency rules apply | Review first | Access, logging, retention, and data location must be reviewed. | The strongest use case is a team that needs one Windows workspace for shared business apps, files, and user access across several locations. :::cta Explore Windows VM Use Raff Windows VM when multiple offices need one cloud-hosted Windows environment for remote access, files, and business apps. ::: ## The problem with separate office servers Separate office servers can work for a while. They become harder to manage as the business grows. ![Comparison visual showing separate branch office servers versus one centralized Windows VPS for multi-location businesses](https://raff-images.s3.raffusercloud.com/branch_servers_vs_centralized_windows_vps_webp_b061c42f5e.png) Common problems include: | Problem | What happens | |---|---| | Different files in different offices | Users are not sure which version is current. | | App installs vary by location | Support becomes inconsistent. | | VPN access gets messy | Each branch adds more firewall and user complexity. | | Backups are inconsistent | One office may be protected while another is not. | | Hardware ages at different times | Refresh planning becomes unpredictable. | | IT support depends on physical access | Troubleshooting slows down when nobody is on-site. | | Security policies drift | User accounts, permissions, and patches differ by location. | | Remote users become exceptions | Workarounds become the normal operating model. | A multi-location business should not depend on a server closet in one branch unless that branch has the power, internet, backup, monitoring, and support process to act like a real data center. ## What changes with a cloud Windows Server A cloud Windows Server moves the shared Windows environment away from one office and into a hosted Windows VM. Users connect from branch offices, home offices, or remote locations. ![Architecture visual showing multiple business locations accessing one Windows VPS for apps, files, and remote desktop sessions](https://raff-images.s3.raffusercloud.com/multi_location_windows_vps_access_architecture_webp_39feaabc89.png) The operating model changes like this: | Area | Local/branch server model | Windows VPS model | |---|---|---| | Server location | One or more offices | Cloud-hosted Windows VM | | User access | LAN, VPN, or branch-specific setup | RDP/RDS, RD Gateway, VPN, or controlled access | | Business apps | Installed per office or on local server | Centralized on one Windows environment | | Files | Spread across offices or one branch server | Centralized shared folders where appropriate | | Backups | Often inconsistent by location | One backup policy for the central server | | Scaling | Buy hardware or upgrade office server | Resize VM or split roles | | Support | Depends on branch hardware and network | MSP/team can support a known cloud environment | | Downtime | Office power/network can block access | Users can connect from other locations if a branch is down | Cloud does not remove administration. You still need Windows updates, access controls, backups, restore tests, app support, licensing, and monitoring. But it reduces dependency on a single physical office server. ## Multi-location access should be designed first Remote access is the first design decision. Do not migrate business apps or files before deciding how users will connect. Use this model: | Access need | Recommended direction | |---|---| | One or two admins maintain the server | Restricted admin RDP can work | | Staff need daily Windows desktop sessions | Plan RDS Session Host and RDS CALs | | Users connect from multiple networks | Consider RD Gateway or controlled access | | Users only need a web app | Do not give full desktop access unnecessarily | | Users need mapped file shares | Use VPN/private networking or supported SMB pattern | | MSP manages the environment | Standardize access policy and documentation | Microsoft describes Remote Desktop Services as a Windows Server platform for securely delivering managed desktops and applications to users in the office, at home, or from branch and partner locations. That is exactly the multi-location pattern many small businesses face. For staff desktop sessions, licensing matters. Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs an RDS Client Access License. Plan that before the server becomes a daily workplace. ## Direct RDP, RD Gateway, and RDS are not the same Small businesses often use “RDP” to describe everything remote. That creates confusion. Use this simple split: | Model | What it means | Best fit | |---|---|---| | Direct admin RDP | Admin connects straight to the server | One or two administrators | | RDS Session Host | Multiple users get desktop/app sessions | Staff working inside the server | | RD Gateway | Controlled gateway for RDS access | Remote users across locations | | VPN/private access | User joins a private network before access | Mapped drives or internal apps | | Web app access | Users access browser-based software | IIS or SaaS-style apps | Microsoft’s RD Gateway documentation says RD Gateway enables secure, encrypted connections to RDS resources over the internet without requiring VPN access. For multi-location businesses, that matters because branch users often need access without turning every office router into a fragile remote-access hub. ## Sizing depends on concurrent users across all locations Do not size a Windows VPS by the number of offices. Size it by peak concurrent users and workload type. A business with three offices may only have four active users at a time. Another business with two offices may have 20 users working inside the server all day. Use this starting point: | Multi-location workload | Starting size | When to move up | |---|---:|---| | 1-2 admin users | 2 vCPU / 4 GB RAM | If apps or reporting tools run on the server | | 3 light users | 4 vCPU / 8 GB RAM | If users open many browser tabs, PDFs, or documents | | 3 business app users | 4 vCPU / 16 GB RAM | If accounting, Access, tax, or legacy apps run daily | | 5 active users | 4 vCPU / 16 GB RAM | If multiple users stay logged in during the workday | | 10 active users | 8 vCPU / 32 GB RAM | If the server is a shared workplace | | Heavy ERP or SQL workload | 8-16 vCPU / 32-64 GB RAM | If database, reports, and RDS sessions compete | The existing Raff sizing guide should be the next internal link from this article. It breaks down Windows VPS sizing for 1, 3, 5, and 10 remote users in more detail. :::cta View Pricing Compare Raff Windows VM plans when sizing CPU, memory, storage, and monthly cost for multiple office locations. ::: ## Shared business apps are the strongest use case A Windows VPS is especially useful when several offices need the same Windows business software. Good fits include: | Workload | Why centralization helps | |---|---| | Accounting software | Users access one environment instead of separate office installs. | | Tax software | Seasonal staff can connect from different locations. | | Microsoft Access apps | App and data can stay close inside the Windows environment. | | ERP or inventory tools | Branch users can work from one operational system. | | Legacy Windows apps | Old apps can run in a consistent server environment. | | SQL Server tools | Admin tools and app clients can be centralized. | | IIS/.NET apps | Internal web apps can live on a cloud Windows Server. | | Reporting tools | Teams can use the same reports and exports. | This does not mean every app should run on one Windows VPS forever. As usage grows, you may split roles: RDS Session Host, database server, file server, and app server. For small teams, though, one properly planned Windows VPS can be a practical starting point. ## Shared files need a controlled file server plan Multi-location businesses often want one place for files. A Windows VPS can work as a cloud file server, but access must be designed carefully. Use a Windows VPS file server when: | File pattern | Fit | |---|---| | RDP/RDS users work inside the server | Strong fit | | Business apps need shared paths | Good fit after testing | | Branches need one controlled folder structure | Good fit | | Files need backup and permission control | Good fit | | Users want direct SMB from anywhere | Risky without secure design | | Users need real-time co-authoring | SaaS collaboration tools may be better | | Large media files move all day | Test before production | Microsoft’s SMB documentation describes SMB as the protocol Windows uses for file sharing. Microsoft’s SMB feature guidance also highlights modern SMB features such as signing and encryption. The practical point is simple: SMB is powerful, but it should be used through a controlled access model, not casually exposed. If the business mainly needs app uploads, static assets, or public object storage, a Windows file server may not be the right model. Use object storage for object-based application storage, not mapped-drive workflows. ## Backups become simpler when the workload is centralized One reason multi-location businesses move to a cloud Windows Server is backup consistency. It is easier to protect one central workload than several branch PCs and office servers with different habits. ![Layered visual showing backup and security planning for a multi-location Windows VPS workload](https://raff-images.s3.raffusercloud.com/multi_location_windows_vps_backup_security_stack_webp_1f674a06f5.png) A practical backup model: | Backup layer | Purpose | |---|---| | VM backup | Recover the whole Windows VPS | | Snapshot before changes | Roll back after updates, migrations, or app upgrades | | File-level backup | Restore shared folders and individual documents | | App-aware backup | Protect SQL Server, accounting, ERP, or Access data | | Off-server copy | Reduce risk from VM, account, or ransomware incidents | | Restore test | Prove recovery works before an emergency | Backups should be discussed before migration. If branch users depend on the server daily, the business should know how much data it can lose and how quickly the server should be restored. Use RPO and RTO language: | Term | Meaning | |---|---| | RPO | How much data loss is acceptable | | RTO | How long the business can be down | A five-office company may still accept a 24-hour RPO for some files. A two-location accounting firm may need a much tighter target during deadlines. The right backup frequency depends on the business, not the server type. :::cta Explore Data Protection Protect your multi-location Windows workload with backup and snapshot planning before moving production data. ::: ## Security must cover every location A multi-location setup increases access complexity. Each office, home user, laptop, and admin account becomes part of the security picture. Plan these controls: | Security area | Recommendation | |---|---| | User accounts | Use named users, not shared logins | | Admin access | Separate admin accounts from daily users | | Remote access | Avoid broad direct RDP exposure | | Firewall rules | Restrict allowed access paths | | RDS/RD Gateway | Use a controlled access model where needed | | Backups | Restrict who can delete or modify backups | | Permissions | Use groups and least privilege | | Patching | Schedule Windows and app updates | | Logs | Review failed logins and access events | | Offboarding | Remove users quickly when staff leave | Do not assume a branch office is safe just because users sit in a company building. Laptops move, passwords get reused, and office networks change. The Windows VPS should have its own access policy. ## Network quality affects user experience A cloud Windows Server depends on internet quality. If a branch has unreliable connectivity, users will feel it through RDP, file access, or app latency. Check: | Network factor | Why it matters | |---|---| | Latency | Higher latency makes Remote Desktop feel delayed | | Packet loss | Causes freezes, disconnects, and poor app experience | | Upload speed | Matters for scans, file uploads, and PDFs | | Download speed | Matters for file retrieval and session responsiveness | | Wi-Fi quality | Local Wi-Fi can make RDP feel slow | | Branch firewall | Can block or interrupt access | | ISP reliability | Office outage can affect everyone at that branch | Before blaming the Windows VPS, test from each office. If only one branch has issues, the problem may be local connectivity, Wi-Fi, DNS, firewall policy, or endpoint configuration. Raff’s RDP performance tuning guide should be linked from this article because RDP performance depends on the full path: client, network, server resources, display settings, and workload. ## Migration should happen in phases Do not move every location in one rushed cutover unless the workload is simple. Multi-location migrations need sequencing. A practical migration plan: 1. Inventory current servers, apps, files, users, and locations. 2. Identify which office currently acts as the “main” location. 3. List peak concurrent users across all locations. 4. Decide the remote access model. 5. Choose the first Windows VPS size. 6. Build a test Windows VPS. 7. Install business apps and shared folders. 8. Copy non-production data first. 9. Test from each office location. 10. Configure backups and run a restore test. 11. Move a small user group first. 12. Schedule production cutover outside peak hours. 13. Keep rollback access to the old environment temporarily. 14. Monitor usage and adjust size or access rules. The goal is not only to get users connected. The goal is to make each location confident that the new system is more reliable than the old patchwork. ## When not to centralize on one Windows VPS A single Windows VPS is not always the right design. Pause when: | Situation | Better next step | |---|---| | Many users need heavy desktop sessions | Consider stronger RDS architecture or split roles | | Database workload is large | Separate database server may be needed | | High availability is required | Design redundancy, not one VM | | Branch internet is unreliable | Fix connectivity or keep local fallback | | Large files are location-specific | Local storage or sync strategy may be better | | Compliance requirements are strict | Review policy, logging, retention, and access | | App vendor does not support hosted/RDS use | Get vendor-supported deployment guidance | | Business wants fully managed desktops | Consider managed desktop/RDS/VDI options | A Windows VPS is a practical building block. It is not a universal replacement for every branch server, application, or desktop strategy. ## How Raff fits multi-location Windows workloads Raff fits this use case when a small business wants one cloud-hosted Windows Server environment for remote offices, branch users, shared business apps, RDP/RDS access, cloud file server use cases, or office server replacement. Raff Windows VMs can provide the Windows Server environment. From there, the business or MSP should configure users, applications, backups, security rules, RDS licensing, and monitoring. The Raff Windows Hub supports this planning with guides on sizing, backup strategy, RD Gateway vs direct RDP, cloud file servers, Access and legacy apps, tax software, MSP environments, RDS CALs, and RDP performance. Raff is not a substitute for planning the application architecture. If the business needs multi-region high availability, advanced compliance, fully managed desktops, or complex Active Directory design, review the architecture before buying a single VM. :::cta Deploy Windows Now Create a Raff Windows VM when your team is ready to centralize Windows workloads in the cloud. ::: ## Recommended path by business type | Business type | Recommendation | |---|---| | Two-office small business | Start with one Windows VPS for shared apps or files if internet is reliable. | | Multi-location accounting office | Plan RDS access, backups, and app support before production. | | Retail or branch business | Centralize admin apps and reports, but test local device needs. | | Tax firm with seasonal users | Size for peak season, not off-season. | | MSP-managed business | Document access, backups, monitoring, and offboarding per client. | | Legacy app user | Test app behavior over RDP/RDS before migration. | | File-heavy business | Validate file size, latency, and backup growth first. | | Compliance-heavy business | Review security, retention, and audit requirements before launch. | The safest first step is a test Windows VPS with real users from each location. Test login, app launch, file access, printing, backups, and restore before moving production. ## What's next - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing CPU, RAM, and storage. - Read [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) if you are replacing branch hardware. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production data. - Read [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) before exposing remote access. - Read [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) if shared folders are part of the plan. - Read [Windows VPS for Business Software](https://rafftechnologies.com/windows-server/windows-vps-for-business-software) if you host several SMB apps. - Read [RDS CAL Licensing on Windows Server](https://rafftechnologies.com/windows-server/rds-cal-licensing-guide) before rolling out staff desktop sessions. - Review [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) and [pricing](https://rafftechnologies.com/pricing) when planning the production server. ## Sources - Microsoft Learn — [Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) - Microsoft Learn — [Deploy Remote Desktop Gateway role for Remote Desktop Services](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remote-desktop-gateway-role) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [What is SMB File Sharing for Windows and Windows Server?](https://learn.microsoft.com/en-us/windows-server/storage/file-server/file-server-smb-overview) - Microsoft Learn — [SMB features in Windows and Windows Server](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-feature-descriptions) - Raff — [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) - Raff — [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) - Raff — [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) - Raff — [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) --- ### Deploy Windows Server 2025 on Raff: Image Choice, VM Creation, and First Boot URL: https://rafftechnologies.com/windows-server/deploy-windows-server-2025-raff Description: Deploy a Windows Server 2025 VPS on Raff, choose the right image and licensing path, create the VM, confirm it reaches Running, and verify the first boot before continuing to server setup. To deploy a **Windows Server 2025 VPS** on Raff, open the Windows VM creation flow, choose the `us-east` region and a VM size for your workload, select Windows Server 2025, choose the appropriate licensing path, set and save a strong Administrator password, and create the VM. When its status becomes **Running**, copy the public IPv4 address, connect over RDP, and verify the operating system and network state before installing anything. This guide stops at **first boot**. For updates, hostname changes, firewall review, Defender, administrator accounts, storage checks, and recovery setup, continue with the [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist). ## This guide covers provisioning, not post-deployment configuration Raff Technologies already has separate Windows Hub pages for choosing a Windows Server version, connecting over Remote Desktop Protocol (RDP), and configuring a new server after the first login. This page owns one specific job: ```text Choose image → choose VM size → choose licensing path → create Windows VM → wait for Running → get public IP → make first RDP connection → verify Windows Server 2025 booted correctly ``` It does **not** duplicate: - [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison) for operating-system selection; - [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) for client-by-client RDP instructions and troubleshooting; - [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist) for the first 30 minutes after deployment; - [Windows Server Licensing on Raff](/windows-server/windows-licensing) for detailed Evaluation, SPLA, and BYOL licensing guidance. If you have already created the VM and can see the Windows desktop, skip directly to the initial setup checklist. ## Windows Server 2025 is the right image for new validated workloads Windows Server 2025 is a Long-Term Servicing Channel release. Microsoft lists mainstream support through **November 13, 2029** and extended support through **November 14, 2034**. That long support runway makes Server 2025 a sensible default for a new environment **when the software you plan to run supports it**. Before deploying, check the application vendor if the server will run: - accounting or tax software; - enterprise resource planning (ERP) software; - legacy Microsoft Access applications; - older Open Database Connectivity (ODBC) drivers; - specialized printer or scanner drivers; - older SQL Server versions; - endpoint security or remote monitoring agents; - software with strict Windows Server certification requirements. If the vendor only supports Server 2022, use Server 2022 rather than creating a Server 2025 VM and discovering the compatibility issue after migration. For the detailed decision, use [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison). ## Step 1 — Open the Raff Windows VM creation flow Sign in to the Raff dashboard and open the Windows VM creation page. ![Raff Windows VM creation screen with Windows Server 2025 image and licensing options selected](https://raff-images.s3.raffusercloud.com/raff_windows_server_2025_vm_creation_d355706676.png) Direct dashboard path: ```text /home/create-product/vms/windows ``` You can also start from the [Raff Windows VM product page](/products/windows-vm) and continue to deployment. The creation screen is where you define the VM before Raff provisions the operating system. You will need to make five decisions: 1. region; 2. VM size; 3. Windows Server image; 4. licensing path; 5. Administrator password. **Verification:** Do not continue until the creation page is specifically configured for a Windows VM rather than a Linux VM. ## Step 2 — Choose `us-east` and size the VM for the workload Choose the Raff `us-east` region for the deployment. Then select a VM size based on what the server will actually run. Windows Server itself is only the baseline. IIS, SQL Server, Remote Desktop Services (RDS), business applications, antivirus, background services, and concurrent users all consume additional CPU and memory. A useful decision pattern is: | Workload | Sizing approach | |---|---| | Lab, testing, or light administration | Start with a smaller Windows VM and scale if needed | | IIS or a light internal application | Size for application CPU, memory, and expected traffic | | SQL Server | Prioritize memory, storage behavior, database size, and query load | | RDP/RDS users | Size for concurrent sessions and applications, not total employee count | | ERP or accounting software | Follow the software vendor's supported requirements first | | Mixed app + database workload | Leave headroom or consider separating roles as usage grows | Do not choose a larger VM simply because it runs Windows Server 2025. Choose it because the **workload** needs the capacity. Review current options on [Raff Windows VM](/products/windows-vm) and [Raff pricing](/pricing) before creating a production server. **Verification:** Confirm the selected VM size has enough CPU, memory, and storage for the first workload you plan to install. ## Step 3 — Select the Windows Server 2025 image and licensing path Choose **Windows Server 2025** from the Windows image selector. Raff's Windows flow supports different licensing scenarios. The important distinction at creation time is whether this is a production deployment or a temporary evaluation/testing environment. ### Use a licensed Windows Server 2025 image for production Use the licensed path when the VM is intended to become a normal production Windows Server and you want Windows licensing provided through the hosted service. This is the cleaner path for: - production business applications; - long-running RDP or RDS environments; - IIS workloads; - SQL Server hosts; - file servers; - MSP client environments; - persistent internal infrastructure. Raff is a Microsoft Service Provider License Agreement (SPLA) partner, so hosted Microsoft licensing can be provided through the applicable Raff Windows licensing workflow. ### Use the Evaluation image for testing Microsoft's Windows Server 2025 Evaluation edition expires after **180 days**. Microsoft also states that Evaluation installations need internet activation during the initial evaluation period to avoid automatic shutdown behavior. Use Evaluation when you are: - checking application compatibility; - building a temporary lab; - testing a migration; - validating Server 2025 before committing to a production build. Do not treat Evaluation as a permanent production licensing model. For the licensing details and BYOL considerations, use [Windows Server Licensing on Raff](/windows-server/windows-licensing). **Verification:** Before creating the VM, confirm that the selected image says **Windows Server 2025** and that the licensing option matches the intended use. :::cta Deploy Windows Now Create your Windows Server 2025 VM from the current Raff Windows deployment flow. ::: ## Step 4 — Set the Administrator password and save it immediately During VM creation, set a strong password for the Windows `Administrator` account. Use a password manager and generate a long, unique password. Do not reuse a password from another server, Microsoft account, email account, or customer environment. The current Raff Windows workflow expects you to set this password during creation. The password is not meant to remain visible in the dashboard afterward, so save it **before you leave the creation flow**. Your first-login credentials will normally be: ```text Username: Administrator Password: the password you set during VM creation ``` If you later lose the password, the VM details page provides a password-reset action. The detailed recovery workflow is covered in [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp). Do not put the password in: - a server name; - a ticket subject; - a shared spreadsheet; - an ordinary chat message; - a screenshot for documentation. **Verification:** Confirm the password is saved in an approved password manager before clicking the final create/deploy action. ## Step 5 — Create the VM and wait for `Running` Submit the VM creation request. The VM will need time to provision the virtual hardware, Windows image, networking, and initial operating-system state. Do not start troubleshooting RDP while the VM is still being created. ![Raff Windows Server 2025 VM details showing Running status and public IPv4 address](https://raff-images.s3.raffusercloud.com/raff_windows_server_2025_vm_running_ip_903e33b876.png) After creation: 1. open **Compute → All Virtual Machines**; 2. select the new Windows VM; 3. wait until its status is **Running**; 4. open the VM details page; 5. copy its **Public IPv4** address. Keep the VM name and public IP together in your server inventory so you know which environment you are connecting to later. **Verification:** The VM should show **Running** and have a public IPv4 address before you attempt the first RDP connection. ## Step 6 — Make the first RDP connection Once the VM is Running, connect to the Windows desktop with RDP. Use: ```text Computer / PC name: Username: Administrator Password: ``` On Windows, you can use the built-in Remote Desktop Connection client. On macOS and mobile platforms, Microsoft provides Windows App. Linux users can use an RDP client such as Remmina or FreeRDP. This article intentionally does not repeat the complete client setup or troubleshooting flow. Follow [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) if you need platform-specific instructions, certificate-warning guidance, password reset, or fixes for port 3389 and credential errors. A first-time certificate warning is expected when connecting directly to a new server by IP with the default RDP certificate. Confirm that you are using the correct VM IP before accepting it. **Verification:** You should reach the Windows Server desktop and be able to open an elevated PowerShell window. ## Step 7 — Verify that Windows Server 2025 booted correctly Before installing IIS, SQL Server, RDS roles, business software, agents, or other workloads, verify the operating system. ![PowerShell on a Raff Windows Server 2025 VM showing the operating system version and build after first boot](https://raff-images.s3.raffusercloud.com/raff_windows_server_2025_first_boot_powershell_2e37eb063d.png) Open **PowerShell as Administrator** and run: ```powershell Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsBuildNumber, OsArchitecture ``` Confirm that the output identifies Windows Server 2025. Then check the network state: ```powershell Get-NetIPConfiguration ``` Record: - computer name; - Windows product name; - OS build number; - public IP from the Raff dashboard; - current network adapter configuration. You can also confirm that the Remote Desktop Services service is running: ```powershell Get-Service TermService ``` Expected status: ```text Running ``` Do **not** manually replace the guest network configuration with a static IP, gateway, or DNS server just because this is a cloud VM. An incorrect guest-level network change can break RDP access. Follow the provider networking model and only change guest networking when the workload requires it and you have a recovery path. **Verification:** The Windows product and build are correct, PowerShell opens normally, and networking is present. At that point, provisioning is complete. ## Provisioning ends here; initial server setup starts next A VM reaching the Windows desktop does not mean it is production-ready. The next phase should cover: - Windows Update; - hostname and time zone; - a named administrator account; - Windows Firewall; - Microsoft Defender; - storage and free-space checks; - snapshot or backup planning; - a baseline record before workload installation. Those actions belong in the [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist). Keeping the handoff explicit prevents two common problems: installing production software before the base OS is ready, and mixing infrastructure provisioning with application troubleshooting. ## Common Windows Server 2025 deployment mistakes ### Choosing Server 2025 before checking software support Server 2025 has a long Microsoft support runway, but an application vendor may still certify only Server 2022. Check the complete software stack before production deployment. ### Losing the Administrator password The first password is operationally important. Save it during creation rather than assuming the dashboard will show it later. ### Connecting before the VM reaches Running An RDP timeout during provisioning does not necessarily mean Windows or the firewall is broken. Wait until the dashboard reports the VM as Running and shows its public IP. ### Installing the workload immediately after first login Patch and baseline the server first. A clean initial state makes later troubleshooting much easier. ### Changing the Windows network adapter without a reason A bad static IP, gateway, or DNS change can remove remote access. Confirm the provider networking model before altering the guest configuration. ### Treating administrative RDP as a multi-user desktop service Windows Server administrative access and a real RDS Session Host deployment are different. If several employees will use the server every day, review [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) and the [RDS CAL licensing guide](/windows-server/rds-cal-licensing-guide). ## Deployment checklist | Check | Ready when | |---|---| | Workload supports Server 2025 | Vendor/support requirements are confirmed | | Region | `us-east` selected | | VM size | CPU, RAM, and storage fit the intended workload | | Image | Windows Server 2025 selected | | Licensing | Licensed, Evaluation, or other approved path selected intentionally | | Administrator password | Strong, unique, and saved securely | | VM state | Dashboard shows Running | | Network | Public IPv4 is visible in VM details | | First RDP | Administrator can reach the desktop | | OS verification | PowerShell confirms Windows Server 2025 | | Handoff | Initial setup checklist is the next task | If all ten checks pass, the Windows Server 2025 VPS has been provisioned correctly and is ready for post-deployment setup. ## What's next - [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist) — complete the first 30 minutes of server configuration. - [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) — detailed Windows, macOS, Linux, and mobile connection instructions. - [Windows Server 2019 vs 2022 vs 2025](/windows-server/windows-server-version-comparison) — confirm the operating-system choice before production. - [Windows Server Licensing on Raff](/windows-server/windows-licensing) — understand Evaluation, SPLA, and BYOL paths. - [Raff Windows VM](/products/windows-vm) — review the Windows VM product. - [Raff pricing](/pricing) — review current VM pricing before deployment. ## Sources - Microsoft Lifecycle — Windows Server 2025: https://learn.microsoft.com/en-us/lifecycle/products/windows-server-2025 - Microsoft Learn — Windows Server release information: https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info - Microsoft Evaluation Center — Windows Server 2025: https://www.microsoft.com/en-us/evalcenter/download-windows-server-2025 - Raff Windows VM: https://rafftechnologies.com/products/windows-vm - Raff Windows Server Hub: https://rafftechnologies.com/windows-server --- ### Managed vs Unmanaged Windows VPS: Which Should You Choose? URL: https://rafftechnologies.com/windows-server/managed-vs-unmanaged-windows-vps Description: Compare managed and unmanaged Windows VPS hosting, including support responsibilities, security, updates, backups, monitoring, and which model fits different business workloads. A managed Windows VPS means the hosting provider or service team handles more server administration tasks, while an unmanaged Windows VPS gives the customer administrator control and responsibility for maintaining the server. The right choice depends on whether your team wants infrastructure control or someone else to handle operating-system operations. Raff Windows VPS provides the infrastructure layer: Windows Server virtual machines, administrator access, deployment options, and cloud resources. Customers who need application management, patching, monitoring, or ongoing administration should define those responsibilities separately. ## Managed and unmanaged Windows VPS solve different problems The main difference between managed and unmanaged Windows VPS hosting is responsibility. | Area | Managed Windows VPS | Unmanaged Windows VPS | |---|---|---| | Windows updates | Usually handled by provider | Customer responsibility | | Security configuration | Provider-assisted or included depending on service | Customer responsibility | | Application installation | May be included | Customer responsibility | | Troubleshooting | Provider handles more layers | Customer handles server issues | | Administrator access | May be limited depending on provider | Full administrator control is common | | Custom configuration | Depends on provider policies | Customer controls configuration | | Cost | Usually higher | Usually lower | Neither model is automatically better. The correct choice depends on who should own the server operations. ## Unmanaged Windows VPS gives maximum control An unmanaged Windows VPS is closer to owning a remote Windows Server. The provider supplies the virtual machine and infrastructure, while the customer manages the operating system and software. This model fits teams that have: - Windows Server administrators; - IT staff; - developers who need administrator access; - MSPs managing their own clients; - application owners who understand their software requirements. Typical responsibilities include: - Windows updates; - firewall configuration; - user accounts; - application installation; - database configuration; - security hardening; - monitoring; - backups and restore testing. The advantage is flexibility. The customer decides how the server is configured. The trade-off is that the customer also owns more operational work. ## Managed Windows VPS reduces administration work Managed hosting is designed for customers who want someone else to handle more of the server lifecycle. A managed Windows VPS service may include: - operating system updates; - monitoring; - security checks; - troubleshooting; - backup management; - application support; - user administration. The exact scope depends on the provider. Before choosing managed hosting, confirm what is actually included. Important questions: - Are Windows updates included? - Who responds when an application fails? - Are backups configured and tested? - Is security hardening included? - Are third-party applications supported? - Is Remote Desktop Services administration included? A managed label alone does not define the service boundary. ## Security responsibilities change between the two models Security is one of the biggest differences between managed and unmanaged Windows VPS hosting. ![Managed vs unmanaged Windows VPS responsibility model showing who handles updates, security, backups, monitoring, troubleshooting, and server management](https://raff-images.s3.raffusercloud.com/windows_vps_responsibility_model_managed_vs_unmanaged_png_adea522c2a.png) With an unmanaged server, the customer usually owns: - administrator account security; - firewall rules; - RDP exposure; - Windows Defender configuration; - patch schedules; - user permissions; - security monitoring. With managed hosting, some of these tasks may move to the provider. A secure Windows VPS still requires clear ownership. Every production server should have: - strong administrator credentials; - regular updates; - limited remote access; - backups; - tested recovery procedures; - documented users and applications. ## Backups and recovery need clear ownership Backups are often where managed and unmanaged expectations become unclear. A provider may offer infrastructure-level backups, snapshots, or recovery tools, but customers should understand: - what data is protected; - backup frequency; - retention period; - restore process; - who performs recovery. For business applications, a backup plan should include restore testing rather than only creating backup copies. ## MSPs and technical teams often choose unmanaged VPS Managed service providers, developers, and IT teams often prefer unmanaged Windows VPS environments because they already have operational processes. They may want control over: - software installation; - security policies; - client environments; - automation scripts; - monitoring tools; - application stacks. For these users, paying for management they do not need can add unnecessary cost. ## Small businesses often need to evaluate support requirements Small businesses without internal IT staff should focus less on the VPS label and more on who will operate the server. A Windows VPS may require someone to handle: - user access; - software updates; - application issues; - printer configuration; - backups; - security settings. If nobody owns those tasks, a lower-cost unmanaged VPS can become difficult to operate. In that case, a managed provider, MSP partner, or internal IT service may be the better fit. ## How Raff fits the Windows VPS decision Raff provides Windows VPS infrastructure with Windows Server deployment, administrator access, and cloud VM resources. Raff customers manage their own operating system and applications unless additional services are separately arranged. This model works well for: - developers; - IT teams; - MSPs; - businesses with technical staff; - organizations that want control over Windows Server. Before deploying a production Windows VPS, define who owns: - Windows administration; - application support; - security updates; - backups; - user management; - troubleshooting. Clear ownership prevents support gaps later. :::cta Deploy Windows Now Create a Windows VM on Raff when your team wants administrator control over its Windows Server environment. ::: ## Choose managed Windows VPS if... Choose managed hosting when: - your team does not manage Windows Server regularly; - you need someone else to handle routine administration; - server issues need a dedicated operations owner; - application support is part of the service agreement. ## Choose unmanaged Windows VPS if... Choose unmanaged hosting when: - you need full administrator control; - your team manages Windows servers already; - you run custom applications; - you need flexibility for configuration; - you want direct control over updates and software. ## Decision checklist | Question | If yes | |---|---| | Do you have someone who manages Windows Server? | Unmanaged may fit | | Do you need custom software and full control? | Unmanaged may fit | | Do you need someone else to handle updates? | Managed may fit | | Do you need application support included? | Managed may fit | | Is the server business-critical? | Define backup and support ownership first | ## What's next - [Windows VPS Sizing for Remote Users](/windows-server/windows-vps-sizing-remote-users) - [Windows VPS for MSP Client Environments](/windows-server/windows-vps-for-msp-client-environments) - [Windows Server Initial Setup Checklist](/windows-server/windows-server-initial-setup-checklist) - [Raff Windows VM](/products/windows-vm) --- ### Windows Server Sizing by Workload: IIS, SQL Server, File Server, and Background Services URL: https://rafftechnologies.com/windows-server/windows-server-sizing-by-workload Description: Size a Windows Server by workload instead of user count alone. Compare practical CPU, RAM, storage, and role-splitting guidance for IIS, SQL Server, file servers, and background services. **Windows Server sizing** should start with the server role, not a generic CPU-and-RAM formula. IIS usually needs CPU headroom and memory for app pools; SQL Server is often memory- and storage-sensitive; file servers are driven by capacity, file behavior, and access patterns; background services depend on job concurrency and burst load. Start conservatively, leave headroom, monitor peak usage, and split roles when one workload starts competing with another. A 4 vCPU / 8 GB Windows VM can behave very differently depending on whether it runs a small IIS site, SQL Server, shared files, scheduled automation, or all four at once. That is why Raff treats the **workload role as the first sizing variable** before comparing VM configurations. If your main question is how many resources you need for **1, 3, 5, or 10 Remote Desktop users**, use [Windows VPS Sizing for Remote Users](/windows-server/windows-vps-sizing-remote-users). This guide owns a different decision: sizing Windows Server by the services running on it. ## Windows Server sizing starts with the role The operating system sets a baseline, but the workload determines the real requirement. Microsoft publishes minimum Windows Server hardware requirements, but minimum requirements are not production sizing targets. Start by classifying the server into one primary role: | Primary role | Resource that usually deserves the most attention | Common secondary concern | |---|---|---| | IIS web/application server | CPU and RAM | App pool behavior, logs, HTTPS, application dependencies | | SQL Server | RAM and storage behavior | CPU, TempDB, backups, query concurrency | | File server | Storage capacity and growth | Access pattern, backups, antivirus scanning, SMB behavior | | Background services / automation | CPU bursts and RAM | Schedule overlap, queues, logs, retry behavior | | RDP/RDS server | RAM per concurrent session | CPU, profiles, application mix, licensing | | Domain controller | Predictable baseline capacity | DNS, directory size, authentication volume, redundancy | | Mixed-role server | Contention between roles | Troubleshooting and recovery complexity | The safest sizing process is: ```text Identify primary role → estimate normal load → estimate peak load → leave operational headroom → monitor after launch → resize or split roles when contention appears ``` Do not start by asking, "How much RAM does Windows Server need?" Start with, "What will this server spend most of its time doing?" ## A workload sizing matrix gives a practical starting point The table below is a planning baseline for small and mid-sized Windows workloads. It is not a performance guarantee. Application vendors, database size, request volume, user concurrency, antivirus, backup jobs, and custom software can move the requirement materially. | Workload | Practical starting point | Move up when | |---|---:|---| | Small IIS site or internal web app | 2–4 vCPU / 4–8 GB RAM | Multiple app pools, heavier .NET apps, CPU bursts, or memory growth appear | | Production IIS / ASP.NET workload | 4 vCPU / 8–16 GB RAM | Several sites, background workers, report generation, or sustained traffic share the VM | | Small SQL Server / staging database | 4 vCPU / 8–16 GB RAM | Database cache, reporting, backups, or query concurrency create pressure | | Small production SQL Server | 4–8 vCPU / 16–32 GB RAM | SQL memory demand, TempDB activity, reporting, or mixed app/database roles compete | | Small file server | 2–4 vCPU / 4–8 GB RAM | Users also connect over RDP, indexing is heavy, or security/backup agents add load | | 5–10 user file/app server | 4–8 vCPU / 16–32 GB RAM | File access, profiles, business apps, and backups run at the same time | | Light automation / background services | 2–4 vCPU / 4–8 GB RAM | Jobs overlap, queues grow, or processes stay resident in memory | | Heavy scheduled processing | 4–8+ vCPU / 8–32+ GB RAM | Batch windows miss targets or workers compete with interactive workloads | These ranges are deliberately broad. The role tells you **which direction to watch**, while monitoring tells you whether the chosen size is actually enough. :::cta Deploy Windows Now Choose a Raff Windows VM for the workload, then monitor CPU, memory, storage, and application behavior before scaling further. ::: ## IIS server sizing is driven by application behavior For IIS, size the application rather than the IIS role itself. A static site, an ASP.NET Core API, a legacy ASP.NET Framework application, and ten isolated app pools can all place very different demands on the same Windows Server. A practical IIS starting model: | IIS workload | Starting point | Main thing to watch | |---|---:|---| | Static or very light internal site | 2 vCPU / 4 GB RAM | CPU bursts and available memory | | Small ASP.NET Core app | 2–4 vCPU / 4–8 GB RAM | App working set and request peaks | | Production business web app | 4 vCPU / 8–16 GB RAM | App pools, background work, GC pressure, response time | | Several production sites | 4–8 vCPU / 16+ GB RAM | Per-pool memory, CPU contention, recycle behavior | | IIS plus local SQL Server | Start larger or split roles | SQL and IIS competing for RAM and storage | IIS capacity is often less about a permanent CPU requirement and more about bursts. Authentication, application startup, report generation, image processing, PDF creation, compression, antivirus scanning, and deployment activity can create short periods of much higher demand than normal traffic. Memory becomes especially important when you use multiple application pools. One production site per app pool gives cleaner isolation, but every worker process has its own memory footprint. If the server hosts several apps, add the working sets together rather than sizing from the largest single site. For app-pool configuration after deployment, use [IIS Application Pool Tuning for Production](/windows-server/iis-app-pool-tuning). A useful operating rule is to avoid sizing an IIS production server so tightly that a recycle, deployment, or traffic burst immediately pushes it into paging or sustained high CPU. ## SQL Server sizing should prioritize memory and storage behavior SQL Server changes the sizing model because memory is part of database performance. SQL Server deliberately uses memory for data and plan caching, so a database VM with too little RAM can create unnecessary storage reads and poor query response times. Use these starting points: | SQL workload | Starting point | Notes | |---|---:|---| | Learning or temporary test | 2–4 vCPU / 4–8 GB RAM | Fine for installation validation and light queries | | Small app or staging database | 4 vCPU / 8–16 GB RAM | Watch buffer memory, TempDB, and backup duration | | Small production database | 4–8 vCPU / 16–32 GB RAM | Better starting point for business applications | | SQL-heavy production workload | 8+ vCPU / 32+ GB RAM | Size from real database behavior, not user count | | SQL plus RDS or IIS on same VM | Add headroom or split | Roles can compete directly for memory and storage | Microsoft recommends configuring SQL Server memory so the operating system and other processes retain enough RAM. In practice, that means the VM needs capacity for **Windows plus SQL Server plus everything else running on the server**. This is why a SQL Server should not be sized from database file size alone. A 30 GB database with heavy reporting can be more demanding than a 300 GB mostly archival database. Review: - active database working set; - concurrent queries; - report and export jobs; - TempDB usage; - backup window; - transaction log growth; - antivirus and monitoring overhead; - whether IIS, ERP, or RDS also runs on the same VM. Raff's [SQL Server 2025 installation guide](/windows-server/install-sql-server-2025-windows-server-vps) uses 4 vCPU / 8–16 GB as a small app or staging starting range and 4–8 vCPU / 16–32 GB for small production databases. Treat those as initial planning values, then validate against the workload. When SQL Server begins competing with an application server for memory, separating the roles usually creates a cleaner scaling and troubleshooting path. ## File server sizing is driven by capacity, growth, and access pattern A Windows file server usually needs less CPU than a database server, but storage planning matters much more. Capacity must include not only today's shared folders but also growth, user profiles, logs, exports, backup staging, and application files. Use this starting model: | File server workload | Starting point | Storage planning | |---|---:|---| | Small shared-folder server | 2 vCPU / 4–8 GB RAM | Current data + growth + recovery space | | File server with 3–5 RDP users | 4 vCPU / 8–16 GB RAM | Add user profiles and application files | | 5–10 users with files and apps | 4–8 vCPU / 16–32 GB RAM | Plan for simultaneous file, app, and backup activity | | Document-heavy business | CPU may stay modest | Storage capacity, file count, scanning, indexing, backup windows matter more | | File server plus database/app roles | Size for the other roles too | File storage is no longer the only requirement | For file servers, watch: - free disk space; - file-count growth; - large folders with many small files; - antivirus and endpoint protection scanning; - Windows Search or indexing; - backup and snapshot windows; - remote access latency; - SMB behavior; - user profile growth if the server also hosts RDP/RDS sessions. Do not fill the server close to capacity. A full Windows volume can disrupt user saves, application exports, updates, logs, and backups. If the server is primarily for shared folders, read [Windows VPS as a Cloud File Server](/windows-server/windows-vps-cloud-file-server) for permissions, SMB access, storage growth, and backup planning. ## Background services need sizing around concurrency and bursts Background services can look light during normal observation and then consume most of the server during a scheduled run. The important variable is not the number of Windows services; it is **what those services do at the same time**. Common background workloads include: - Windows services for business applications; - scheduled PowerShell tasks; - import/export jobs; - API workers; - queue consumers; - PDF or report generation; - file conversion; - data synchronization; - antivirus or EDR scans; - backup agents; - monitoring agents; - integration services. A practical starting point: | Background workload | Starting point | Watch for | |---|---:|---| | Few lightweight services | 2 vCPU / 4 GB RAM | Resident memory and log growth | | Several scheduled jobs | 2–4 vCPU / 4–8 GB RAM | Jobs overlapping at the same time | | Data import/export workers | 4 vCPU / 8–16 GB RAM | CPU bursts, disk activity, database calls | | Heavy report or conversion jobs | 4–8+ vCPU / 16+ GB RAM | Batch duration and interactive slowdown | | Workers sharing a production app VM | Add headroom | User-facing app latency during job windows | The scheduling model matters. Four tasks that each need one CPU core are manageable when they run sequentially. The same four jobs launched at 02:00 together may saturate the VM. If scheduled work repeatedly hurts IIS, SQL Server, RDS, or file access, moving those workers to a separate Windows VM can be more predictable than continually increasing one mixed-role server. ## Domain controller sizing should stay simple and redundant A small Active Directory Domain Services (AD DS) environment usually does not need a large VM, but domain controllers should be treated as infrastructure rather than places to stack unrelated workloads. For a small environment, a modest VM can be enough. What matters more is: - directory size; - authentication volume; - DNS activity; - Group Policy processing; - replication; - backup and recovery planning; - having another domain controller where the environment requires resilience. Microsoft's AD DS capacity guidance recommends measuring the workload and leaving capacity for failure scenarios rather than sizing only for the average day. Avoid putting SQL Server, heavy IIS applications, or large RDS workloads on a domain controller just to save one VM. Role separation improves security, maintenance, and troubleshooting. ## CPU sizing should be based on sustained pressure and burst behavior vCPU matters most when the workload is actively computing. Web requests, report generation, compression, encryption, SQL queries, PowerShell jobs, antivirus scans, and application code all create CPU demand. Use CPU monitoring to distinguish normal bursts from a real capacity problem: | Pattern | Interpretation | |---|---| | Short CPU spikes during normal work | Usually acceptable | | High CPU only during scheduled job | Review scheduling or worker separation | | Sustained high CPU during normal usage | Add CPU or investigate application bottleneck | | High CPU plus low memory availability | Fix both constraints; adding CPU alone may not help | | One process dominates CPU | Tune or isolate that workload before resizing everything | Do not upgrade CPU because a single screenshot shows 100% utilization. Measure during normal and peak periods, identify the process creating the load, and determine whether the demand is expected. ## RAM sizing should leave operational headroom RAM is often the first practical constraint on mixed Windows workloads. Windows, application processes, SQL Server, RDP sessions, antivirus, backup software, file cache, and monitoring all compete for the same memory. A simple planning model is: ```text Required RAM = Windows baseline + application working set + database/cache memory + active user sessions + security/backup/monitoring overhead + operational headroom ``` For production workloads, do not aim for a VM that sits near full memory during ordinary use. Sustained memory pressure can create paging, slow application response, longer batch jobs, and poor RDP responsiveness. Raff's remote-user sizing guide uses **20–30% memory headroom** as a practical monitoring target for active RDP environments. The same principle is useful for mixed Windows workloads: leave room for spikes, updates, scans, backups, and service restarts rather than sizing to the exact current working set. ## Storage sizing should include working data and recovery operations Storage sizing has two separate questions: 1. How much capacity does the workload need? 2. What kind of storage activity does the workload generate? Include: - Windows Server and updates; - application binaries; - databases and logs; - shared files; - user profiles; - temporary files; - application logs; - backup staging; - export/import folders; - growth for the next 12–24 months; - free space for maintenance and recovery operations. A file server can need a large volume with modest CPU. SQL Server may need much less total capacity but be more sensitive to database and TempDB I/O. An IIS server may use little storage until application logs, uploads, or generated files start accumulating. Capacity and performance are different sizing dimensions. Treat both explicitly. ## Network requirements depend on where the clients and other roles live Network demand changes with architecture. | Architecture | Network consideration | |---|---| | IIS and SQL on same VM | Less network dependency, more local resource contention | | Separate IIS and SQL VMs | Private network quality and database connection latency matter | | File server used through RDP | User display traffic and file activity stay server-side | | Direct remote file access | Latency and SMB access design become important | | Background worker calling APIs | Outbound reliability and queue retry design matter | | Multi-location business | WAN quality can matter more than raw VM size | Before increasing VM resources for a "slow server," confirm the bottleneck is actually inside the VM. RDP latency, client Wi-Fi, DNS, an external API, or a database on another host can all make a healthy Windows Server feel slow. ## Mixed roles should be split when contention becomes visible Small teams often start with one Windows VM because it is simple. That is reasonable when the workload is small and the operational risk is understood. A single-server pattern might be: ```text Windows VM ├── IIS ├── SQL Server ├── background worker └── shared files ``` The problem appears when those roles compete for the same resources or maintenance window. Split roles when: - SQL Server consumes memory needed by IIS or RDS; - backups slow down user-facing apps; - report jobs create visible CPU spikes; - file scanning or indexing affects database/app latency; - one application restart should not affect another role; - security policy requires stronger separation; - scaling one role forces you to overprovision every other role; - troubleshooting cannot clearly identify which workload caused the issue. A cleaner production architecture is often: ```text IIS / application VM ↓ Private network ↓ SQL Server VM Optional separate file or worker VM when needed ``` Role separation costs more than one VM, but it gives each workload its own capacity envelope, maintenance cycle, access rules, monitoring, and scaling path. ## Raff Windows VM sizing should start simple and remain resize-aware Raff Windows VMs are suitable for Windows workloads where the buyer wants administrator control over IIS, SQL Server, file services, business applications, automation, and remote administration. For sizing, the useful approach is not to find one "correct" server forever. Start with a configuration that has sensible headroom for the identified role, then measure the production workload. Use these signals after launch: | Metric | Healthy pattern | Resize or redesign signal | |---|---|---| | CPU | Short bursts with lower normal usage | Sustained high usage during normal workload | | RAM | Meaningful free memory during peak activity | Persistent memory pressure or paging | | Storage | Predictable growth and free space | Rapid growth, low free space, or long I/O queues | | Application response | Stable during normal and peak use | Slowdowns align with resource saturation | | Batch duration | Completes inside required window | Jobs overrun or interfere with users | | Backups | Complete inside maintenance window | Backup activity regularly affects production | | Role contention | Workloads coexist cleanly | One role repeatedly slows another | Review current configurations on [Raff Windows VM](/products/windows-vm) and [Raff pricing](/pricing). Choose from the live product options instead of copying an old plan price or screenshot into a sizing decision. ## A server-role checklist prevents under-sizing and over-sizing Before choosing the VM, answer these questions: | Question | Why it matters | |---|---| | What is the primary server role? | Identifies the dominant resource pattern | | What else runs on the same VM? | Reveals role contention | | What is the peak workload window? | Average usage can hide the bottleneck | | How much data exists today? | Establishes storage baseline | | How fast is data growing? | Prevents capacity surprises | | Does SQL Server run locally? | Changes RAM and storage planning materially | | Do users run desktop sessions? | Adds RDS/RAM/profile requirements | | Are there scheduled jobs? | Reveals burst CPU and I/O demand | | What backup window is acceptable? | Backup activity can influence sizing | | Can the application be split later? | Determines scaling path | | What happens if one role fails? | Helps decide whether role separation is justified | If these questions are answered before deployment, the first VM choice becomes much easier to defend and adjust. ## What's next - [Windows VPS Sizing for Remote Users](/windows-server/windows-vps-sizing-remote-users) — size 1, 3, 5, and 10-user RDP/RDS workloads. - [IIS Application Pool Tuning for Production](/windows-server/iis-app-pool-tuning) — tune app pools after choosing IIS capacity. - [Install SQL Server 2025 on a Windows Server VPS](/windows-server/install-sql-server-2025-windows-server-vps) — deploy and configure the database role. - [Windows VPS as a Cloud File Server](/windows-server/windows-vps-cloud-file-server) — plan shared files, storage, SMB access, and backups. - [Raff Windows VM](/products/windows-vm) — review current Windows VM configurations. - [Raff pricing](/pricing) — compare current pricing before deployment. ## Sources - Microsoft Learn — Hardware Requirements for Windows Server: https://learn.microsoft.com/en-us/windows-server/get-started/hardware-requirements - Microsoft Learn — Capacity planning for Active Directory Domain Services: https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/active-directory-server/capacity-planning-for-active-directory-domain-services - Microsoft Learn — Server memory configuration options for SQL Server: https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/server-memory-server-configuration-options - Microsoft Learn — Performance Tuning for SMB File Servers: https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/file-server/smb-file-server - Microsoft Learn — IIS application pool defaults: https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/applicationpooldefaults/ - Raff — Windows VPS Sizing for Remote Users: https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users - Raff — Windows VM: https://rafftechnologies.com/products/windows-vm - Raff — Pricing: https://rafftechnologies.com/pricing --- ### Windows Server Performance Monitoring: CPU, RAM, Disk, and Network URL: https://rafftechnologies.com/windows-server/windows-server-performance-monitoring Description: Monitor Windows Server performance with built-in tools. Learn which CPU, RAM, disk, network, and application metrics to track before resizing or troubleshooting a Windows VPS. Windows Server performance monitoring helps you understand whether a slow server is caused by CPU pressure, memory limits, storage activity, network problems, or application behavior. Use built-in Windows tools such as Task Manager, Resource Monitor, and Performance Monitor (PerfMon) to establish a baseline before changing VM size or application settings. This guide focuses on monitoring a Windows VPS after deployment. It does not replace workload-specific tuning guides for IIS, SQL Server, or Remote Desktop. Instead, it provides the measurement process needed before deciding whether to tune, resize, or redesign. ## Windows Server monitoring starts with a baseline A server should be measured before it is changed. A single screenshot of high CPU or low memory does not explain the cause. Start by recording: - normal CPU usage; - available memory; - disk activity; - network throughput; - running services; - application workload during busy periods. A useful monitoring cycle is: ```text Measure baseline → identify bottleneck → change one variable → measure again ``` This prevents unnecessary upgrades and helps separate infrastructure problems from application problems. ## CPU monitoring shows compute pressure CPU usage is one of the first metrics administrators check, but sustained usage matters more than short spikes. Watch: | Metric | What it shows | |---|---| | Processor % Processor Time | Overall CPU utilization | | Processor Queue Length | Waiting work because CPU is busy | | Process CPU usage | Which application consumes CPU | Short bursts during login, updates, backups, or reports are normal. Sustained high CPU during normal operation suggests either application tuning or additional compute capacity may be needed. ## Memory monitoring shows whether the VPS has enough RAM Memory pressure is one of the most common causes of slow Windows Server sessions. Monitor: | Metric | Why it matters | |---|---| | Available MBytes | Remaining memory headroom | | Pages/sec | Paging activity caused by memory pressure | | Process working set | Memory used by applications | A server with low available memory may appear to have a CPU problem because Windows starts paging data to disk. For workloads such as SQL Server, IIS, and RDS, memory should be reviewed together with the application role. ## Disk monitoring identifies storage bottlenecks Slow applications are often caused by storage pressure rather than CPU. Monitor: | Metric | Meaning | |---|---| | % Disk Time | Disk activity level | | Avg. Disk sec/Transfer | Storage latency | | Current Disk Queue Length | Waiting storage requests | | Free Disk Space | Capacity risk | Check storage during the same period when users report slow performance. A quiet disk during normal hours does not prove the server is healthy during backups, reports, or database operations. ## Network monitoring helps separate server and connection problems Remote users often describe every issue as "the server is slow," but the problem may be network-related. Monitor: - Network Interface Bytes Total/sec; - packet errors; - connection stability; - bandwidth usage; - latency from user locations. A healthy Windows VPS can still feel slow if the user's connection has high latency or packet loss. ## Performance Monitor (PerfMon) provides historical data Task Manager shows the current state. Performance Monitor records trends over time. ![Windows Server Performance Monitor showing CPU, memory, disk, and network counters on a Raff Windows VM](https://raff-images.s3.raffusercloud.com/windows_server_perfmon_cpu_memory_disk_network_35e97a1dbb.png) Open it with: ```text perfmon ``` Useful counters include: - Processor\% Processor Time - Memory\Available MBytes - Memory\Pages/sec - PhysicalDisk\Avg. Disk sec/Transfer - Network Interface\Bytes Total/sec - Process\% Processor Time ## Creating a Data Collector Set for monitoring A Data Collector Set allows Windows Server to collect performance information automatically. Basic workflow: 1. Open Performance Monitor. 2. Expand Data Collector Sets. 3. Create a User Defined Data Collector Set. 4. Add CPU, memory, disk, and network counters. 5. Select a collection interval. 6. Start the collection. 7. Review the generated report. A short controlled collection session is enough to verify the workflow. Longer production monitoring periods reveal workload patterns over days or weeks. ## Task Manager, Resource Monitor, and PerfMon have different roles | Tool | Best use | |---|---| | Task Manager | Quick current-state checks | | Resource Monitor | Process-level investigation | | Performance Monitor | Historical trends and baselines | Use the simplest tool that answers the question. Move to PerfMon when the problem is intermittent or happens outside your observation window. ## Monitor applications based on workload Different Windows Server roles need different measurements. ### IIS servers Watch: - worker process memory; - CPU usage by application pool; - request response time; - application errors. ### SQL Server workloads Watch: - memory usage; - database activity; - disk latency; - query performance. ### Remote Desktop servers Watch: - RAM usage per session; - CPU during peak login times; - profile growth; - disk activity. ### File servers Watch: - storage capacity; - SMB activity; - disk latency; - backup windows. ## Monitoring helps decide whether to resize A VM upgrade is not always the answer. Use monitoring data to decide: | Finding | Likely action | |---|---| | CPU saturated consistently | Add CPU or optimize application | | Memory constantly low | Add RAM or reduce workload competition | | Disk latency high | Review storage workload or architecture | | Network issue only for remote users | Investigate client/network path | | One application causes pressure | Tune or isolate that workload | The goal is not to buy the largest VM. The goal is to match resources to the actual workload. :::cta Deploy Windows Now Deploy a Windows VM and monitor real workload behavior before scaling your infrastructure. ::: ## Raff Windows VM monitoring approach Raff Windows VM customers can use Windows-native monitoring tools to understand workload behavior after deployment. A practical process is: 1. Deploy the VM. 2. Record a baseline during normal usage. 3. Monitor peak workload periods. 4. Identify the limiting resource. 5. Resize or separate workloads when needed. This approach applies whether the server runs IIS, SQL Server, business applications, automation, or Remote Desktop workloads. ## Common monitoring mistakes ### Reacting to one CPU spike Short spikes are normal. Look for repeated patterns. ### Monitoring only CPU RAM, storage, and network problems often appear as application slowness. ### Changing multiple things at once Measure one change at a time so you know what improved the result. ### Skipping baseline collection Without baseline data, troubleshooting becomes guesswork. ## Monitoring checklist | Check | Completed when | |---|---| | CPU baseline recorded | Normal and peak usage understood | | Memory baseline recorded | RAM pressure identified | | Disk metrics reviewed | Storage bottlenecks ruled out | | Network checked | Connectivity issues separated from server issues | | PerfMon configured | Historical data available | | Workload metrics identified | Application-specific monitoring added | ## What's next - Windows VPS Sizing by Workload — choose CPU, RAM, and storage based on server role. - IIS Application Pool Tuning for Production — optimize IIS workloads. - MSSQL Memory Tuning on a Windows VPS — tune SQL Server memory safely. - RDP Performance Tuning for Smooth Remote Desktop — troubleshoot user session performance. ## Sources - Microsoft Learn — Monitor Windows Server performance - Microsoft Learn — Performance Monitor documentation - Microsoft Learn — Windows Server performance tuning guidance --- ### Windows Server Licensing on Raff: SPLA, BYOL, Evaluation, and RDS URL: https://rafftechnologies.com/windows-server/windows-licensing Description: Understand Windows Server licensing on Raff: 180-day evaluation, Raff-provided SPLA licensing, customer BYOL under Microsoft outsourcing rights, RDS licensing, core minimums, and Microsoft 365 Apps. Windows Server licensing on a cloud VM is not just a product-key question. The correct path depends on **who owns the license, where the VM runs, whether the workload is production, and whether users need Remote Desktop Services or Microsoft 365 Apps**. Raff supports Windows Server workloads through Microsoft service-provider licensing and customer-managed licensing scenarios. Microsoft’s Product Terms and your own agreement ultimately control your rights, so treat this page as practical infrastructure guidance rather than a substitute for your Microsoft licensing agreement. ## In short For most Raff Windows VM users, the choices are straightforward: use the **180-day Windows Server evaluation** for short-term testing, use **Raff-provided SPLA licensing** for production when you do not want to bring Microsoft licenses, or evaluate **BYOL under Microsoft outsourcing rights / Flexible Virtualization Benefit** when your organization already owns eligible subscription licenses or licenses with active Software Assurance. Windows Server BYOL is **not** the same as License Mobility through Software Assurance. ## The three Windows Server licensing paths are different | Licensing path | Best fit | Key requirement | Production use | |---|---|---|---| | **Windows Server evaluation** | Labs, testing, migration checks | Evaluation edition expires after 180 days | Do not treat it as the production licensing path | | **Raff-provided SPLA** | Most hosted production VMs | Raff licenses the hosted Windows Server workload under SPLA | Yes, when configured under the applicable SPLA terms | | **Customer BYOL** | Organizations with eligible Microsoft licenses | Rights depend on the license program, Software Assurance/subscription status, and outsourcing model | Yes, when the customer’s Microsoft terms permit it | The biggest mistake is treating these paths as interchangeable. They are governed by different Microsoft licensing rules. ## Windows Server evaluation lasts 180 days Microsoft provides Windows Server 2025 as a **180-day evaluation**. Microsoft also states that the evaluation edition must be activated over the internet within the first 10 days to avoid automatic shutdown. Use an evaluation VM for tasks such as: - application compatibility testing; - proof-of-concept deployments; - migration rehearsals; - learning Windows Server roles; - short-lived development and lab environments. Do not build a production licensing plan around repeated evaluation extensions or rearm commands. If the workload is becoming business-critical, move it to a properly licensed production path. Microsoft supports converting eligible Windows Server evaluation installations to retail editions, subject to the edition-conversion rules for the installed version. Always check the target editions first before assuming an in-place conversion is available. ## SPLA is Raff’s service-provider licensing path Microsoft’s **Services Provider License Agreement (SPLA)** is designed for service providers that offer hosted Microsoft software to customers. Raff is a Microsoft SPLA partner and can provide Windows Server licensing for eligible hosted workloads through this model. Under SPLA, Windows Server is licensed under the service-provider use rights rather than by transferring a retail key to the VM. Microsoft’s current SPLA guidance describes Windows Server as a **Per Core (OS)** product. Per-core SPLA licensing generally permits users to access the licensed server software without separate Windows Server SALs, although certain Windows Server functionality requires additional SALs. That distinction is important for Remote Desktop Services. ### SPLA does not make RDS free If a workload uses Windows Server Remote Desktop Services functionality to provide graphical user sessions, Microsoft’s current SPLA use rights list a **Windows Server Remote Desktop Services SAL** for each user who is authorized to use that functionality. So the practical model is: ```text Windows Server under Raff SPLA + RDS SALs when users consume RDS functionality ``` Do not assume that the Windows Server SPLA license automatically covers multi-user RDS access. For a deeper explanation, see [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide). ## BYOL for Windows Server uses outsourcing rights, not License Mobility This is the most important correction to older Windows Server licensing advice. **Windows Server is not covered by License Mobility through Software Assurance.** Microsoft explicitly distinguishes Windows Server from server applications such as SQL Server that can use License Mobility. For Windows Server on a shared cloud environment operated by an eligible outsourcer, the relevant modern Microsoft path is generally the **Flexible Virtualization Benefit**. Microsoft introduced the Flexible Virtualization Benefit in October 2022. It allows customers with qualifying **subscription licenses or licenses with active Software Assurance** to deploy eligible Microsoft software on shared or dedicated servers operated by an **Authorized Outsourcer**. Microsoft specifically notes that this benefit applies to products that are not covered by License Mobility, including Windows Server. ### A License Mobility verification form is not the Windows Server path Do not use the SQL Server License Mobility workflow as a template for Windows Server. Microsoft’s Flexible Virtualization Benefit guidance says the benefit does **not** require the License Mobility verification form used for License Mobility through Software Assurance. Your Microsoft agreement, license type, Software Assurance/subscription status, and the hosting arrangement still need to qualify. If you want to bring your own Windows Server licenses to Raff, confirm the exact entitlement with your Microsoft licensing reseller or licensing specialist before deployment. ## BYOL can be licensed by VM when the eligibility rules are met Microsoft’s current Windows Server licensing guidance allows Standard and Datacenter to be licensed either by physical cores or, for eligible customers, **by virtual machine**. The per-VM option is available when the licenses are subscription licenses or have active Software Assurance. When licensing Windows Server by VM: - license the virtual cores allocated to the VM; - apply a minimum of **8 core licenses per VM**; - maintain the qualifying subscription or active Software Assurance rights required for the per-VM model; - obtain the Windows Server access licenses required by your Microsoft agreement for users/devices that access the server. When licensing Windows Server based on physical cores, Microsoft continues to apply a minimum of **8 core licenses per physical processor and 16 core licenses per server**. This is why a 4-vCPU VM does not necessarily mean “four Windows Server core licenses” in a BYOL calculation. ## Standard and Datacenter have different virtualization rights Windows Server Standard and Datacenter use the same core-based licensing framework, but the virtualization rights differ when licensing physical servers. At a high level: - **Standard** grants rights for a limited number of Windows Server operating system environments per fully licensed physical server and can be stacked for additional OSEs. - **Datacenter** permits any number of Windows Server OSEs on the properly licensed physical server. For an individual customer VM licensed using the eligible per-VM model, the VM licensing rules are usually the more relevant calculation than host-wide virtualization rights. ## Access licenses still matter under customer BYOL Microsoft’s standard Windows Server commercial licensing model is **Per Core/CAL**. That means customer-owned Windows Server licenses normally require the applicable access licenses for users or devices accessing the server software. If Remote Desktop Services is used, the separate RDS access-license requirements also apply. This differs from the SPLA service-provider model, where Microsoft uses the SPLA licensing models and service-provider use rights instead of the customer’s normal CAL model. Keep these models separate: ```text Customer BYOL → Windows Server core licenses + applicable CALs + RDS CALs if needed Raff SPLA → SPLA Windows Server licensing + RDS SALs if RDS functionality is used ``` ## RDS licensing depends on who provides the Windows license The infrastructure can look identical while the licensing documents are different. | Windows licensing model | Multi-user RDS access | |---|---| | Customer-owned Windows Server | RDS CALs under the customer’s Microsoft licensing terms | | Raff-provided SPLA Windows Server | RDS SALs under SPLA for authorized RDS users | | Two administrative RDP sessions | Intended for server administration, not as a substitute for an RDS user environment | For normal employees using a shared Windows desktop to run accounting software, ERP software, Office apps, or other line-of-business tools, design the environment as an RDS workload rather than trying to use the two administrative sessions as a multi-user licensing workaround. ## SQL Server follows different BYOL rules Do not copy Windows Server BYOL rules directly to SQL Server. SQL Server is one of the server applications that Microsoft identifies as eligible for **License Mobility through Software Assurance** when the applicable requirements are met. SQL Server can also be deployed under the Flexible Virtualization Benefit in eligible Authorized Outsourcer scenarios. For SQL Server licensed by VM under the per-core model, Microsoft applies a minimum of **four core licenses per VM**. Raff can also license eligible Microsoft server products under the applicable service-provider licensing model where offered. For production SQL Server licensing, confirm the exact edition and licensing route separately from the Windows Server OS license. ## Microsoft 365 Apps needs Shared Computer Activation for multi-user servers If several users sign in to the same Windows Server and use Microsoft 365 Apps, Microsoft requires **Shared Computer Activation (SCA)** for that shared-computer scenario. Microsoft currently lists SCA support for plans including: - plans with Microsoft 365 Apps for enterprise, such as Office 365 E3 or Microsoft 365 E5; - Microsoft 365 Business Premium; - eligible subscription Project and Visio desktop plans. Microsoft states that **Microsoft 365 Business Standard does not include Shared Computer Activation support**. Each user still needs their own qualifying Microsoft 365 license. One user activating Office does not activate Microsoft 365 Apps for every user on the RDS server. ### Current Windows Server support dates for Microsoft 365 Apps As of August 2026: - **Windows Server 2025:** Microsoft 365 Apps is supported while Server 2025 remains in Mainstream Support, currently through October 2029. - **Windows Server 2022:** mainstream support for Microsoft 365 Apps on Server 2022 ends in October 2026; Microsoft says security updates for Microsoft 365 desktop apps on Server 2022 continue through October 10, 2028, with feature updates stopping at Version 2608. - **Windows Server 2019 and 2016:** Microsoft 365 Apps support ended October 14, 2025, although Microsoft provides a limited security-update runway through October 10, 2028 for those existing configurations. If Microsoft 365 Apps is central to a new RDS deployment, Windows Server 2025 has the cleaner current support horizon. ## Azure Hybrid Benefit is an Azure benefit **Azure Hybrid Benefit** is a Microsoft Azure-specific benefit. It does not become a generic discount mechanism simply because the same organization owns Windows Server licenses with Software Assurance. Outside Azure, evaluate the customer’s standard outsourcing rights, Flexible Virtualization Benefit, or the hosting provider’s own service-provider licensing model instead. ## OEM licenses are not a normal cloud BYOL path OEM Windows Server licenses are associated with the hardware on which they were originally supplied. Do not assume an OEM license purchased with an office server can be reassigned to a Raff VM. For cloud BYOL, focus on qualifying Microsoft commercial subscription licenses or licenses with the appropriate active Software Assurance / outsourcing rights. ## Raff recommends choosing the licensing model before production From an operational perspective, licensing becomes much easier when it is decided before the VM becomes business-critical. Use this decision framework: | Situation | Starting direction | |---|---| | Short-term lab or compatibility test | Windows Server evaluation | | Production VM with no existing Microsoft entitlement | Raff-provided SPLA | | Existing qualifying Microsoft subscription / active SA | Review BYOL under Flexible Virtualization / outsourcing rights | | Multi-user Windows desktop under Raff SPLA | Windows SPLA + appropriate RDS SALs | | Multi-user Windows desktop under customer BYOL | Windows Server licenses + applicable CALs + RDS CALs | | Microsoft 365 Apps for multiple RDS users | Qualifying Microsoft 365 licenses + Shared Computer Activation | The cheapest-looking option is not always the simplest option. BYOL can make sense for organizations that already maintain Microsoft commercial licensing, while SPLA is usually simpler when the goal is a hosted Windows VM without managing transferable license entitlements. :::cta View Pricing Compare Raff Windows VM plans, then confirm the Microsoft licensing path that applies before moving a production workload. ::: ## Next steps - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) - [Windows Server Version Comparison](/windows-server/windows-server-version-comparison) - [Deploy Windows Server 2025 on Raff](/windows-server/deploy-windows-server-2025-raff) - [Raff Windows VM](/products/windows-vm) - [Raff Pricing](/pricing) ## Sources - Microsoft Licensing — Service Provider License Agreement (SPLA) licensing guidance - Microsoft Services Provider Use Rights — Windows Server - Microsoft Licensing — Flexible Virtualization Benefit licensing guidance - Microsoft Licensing — Outsourcing licensing guidance - Microsoft Licensing — Windows Server licensing FAQ and virtualization guidance - Microsoft Product Terms — Windows Server - Microsoft Evaluation Center — Windows Server 2025 - Microsoft Learn — Convert Windows Server editions and license types - Microsoft Learn — Shared Computer Activation for Microsoft 365 Apps - Microsoft Learn — Windows Server end of support and Microsoft 365 Apps - Sources verified: 2026-08-08 --- Microsoft licensing terms can vary by agreement, program, product version, and deployment model. Microsoft Product Terms and the customer’s executed licensing agreement control if they conflict with this guide. --- ### Windows Server Hardening Checklist: Secure Your VPS Before Production URL: https://rafftechnologies.com/windows-server/windows-server-hardening-checklist Description: Harden a Windows Server VPS before production with practical controls for accounts, RDP, Windows Firewall, Defender, SMB, audit logging, patching, services, backups, and Microsoft security baselines. Windows Server hardening reduces the attack surface of a VPS before it becomes a production system. The goal is not to apply hundreds of settings blindly. It is to start with high-impact controls, preserve a recovery path, verify each change, and then move toward Microsoft’s supported security baseline for the server version and role you actually run. For Windows Server 2025, Microsoft now provides a role-aware OSConfig security baseline with more than 300 settings. That baseline covers network exposure, credentials, auditing, Defender, SMB, log retention, and other controls that are broader than this SMB-focused checklist. ## In short Before production, audit administrator access, keep Windows Firewall enabled, reduce RDP exposure, require Network Level Authentication, keep Microsoft Defender active, remove SMBv1, review SMB signing, enable useful security auditing, patch on a controlled schedule, and document every change. On Windows Server 2025, use Microsoft’s official security baseline as the long-term reference instead of treating a manual checklist as a complete compliance standard. ## The production hardening checklist starts with risk reduction | Area | Production check | |---|---| | Recovery | Take a current backup or snapshot before high-risk changes | | Accounts | Review local users and the local Administrators group | | Authentication | Apply an intentional lockout/password policy and require NLA for RDP | | RDP | Restrict administrative access to trusted sources where practical | | Firewall | Keep all Windows Firewall profiles enabled and review inbound allow rules | | Defender | Confirm real-time, behavior, and script scanning are active | | SMB | Keep SMBv1 disabled; review SMB signing and guest access | | Auditing | Record logons, lockouts, account changes, and process creation | | PowerShell | Enable script block logging where appropriate and protect sensitive logs | | Updates | Patch on a controlled schedule and prioritize actively exploited issues | | Services | Remove or disable unnecessary roles and services only after validation | | Documentation | Record changes, owner, reason, validation, and rollback plan | Do not apply security changes in bulk to a remote server without a recovery path. Authentication, firewall, RDP, SMB, Defender, and service changes can lock out administrators or break production software. ## Microsoft’s Windows Server 2025 baseline is the reference point Windows Server 2025 has an official Microsoft security baseline delivered through OSConfig. Microsoft describes it as a role-aware baseline with more than 300 settings and recommends testing and customizing the baseline for the server role rather than manually configuring hundreds of controls one by one. The current baseline includes controls that: - keep Windows Firewall enabled with a default-deny inbound posture; - disable SMBv1 and legacy name-resolution protocols such as LLMNR; - strengthen SMB signing and authentication behavior; - reduce anonymous and guest access; - strengthen credential protections; - enable broad advanced auditing; - capture process creation with command-line data; - increase Security log capacity; - harden Defender and exploit protections. For Windows Server 2022 and older supported releases, Microsoft’s Security Compliance Toolkit remains the practical source for Microsoft-recommended Group Policy baselines. This Raff checklist focuses on the controls that are easiest to understand and validate on a standalone or small-business VPS. It is not a replacement for Microsoft’s complete baseline, CIS Benchmarks, DISA STIGs, or a formal security program. ## The original Raff lab evidence remains useful The existing screenshots in this article were captured during a Raff Windows Server 2025 Datacenter Evaluation lab on May 24, 2026. ![PowerShell output showing a Raff Windows VPS running Windows Server 2025 Datacenter Evaluation with build number, CPU count, and memory details.](https://raff-images.s3.raffusercloud.com/01_hardening_test_environment_edc6037983.png) | Item | Value | |---|---| | OS | Windows Server 2025 Datacenter Evaluation | | Build | 26100 | | CPU | 4 vCPU | | RAM | Approximately 8 GB | | Test date | 2026-05-24 | | Engineer | Serdar Tekin | That lab verified the inspection commands for local users, administrators, account policy, Windows Firewall, RDP rules, Microsoft Defender preferences, and audit policy. It did not apply every hardening control in this article, and this August update does not claim a fresh end-to-end hardening test. ## Administrator access should be reviewed before anything else Run PowerShell as Administrator and inventory local users: ```powershell Get-LocalUser | Select-Object Name, Enabled, LastLogon ``` Then inspect the local Administrators group: ```powershell Get-LocalGroupMember -Group "Administrators" | Select-Object Name, ObjectClass ``` ![PowerShell output showing local users and members of the local Administrators group on a Windows Server VPS.](https://raff-images.s3.raffusercloud.com/02_local_admin_users_audit_1da1a03661.png) Investigate unknown accounts before removing them. Disable obsolete test users, keep the Guest account disabled, and avoid shared administrator credentials. Check the Guest account: ```powershell Get-LocalUser Guest | Select-Object Name, Enabled ``` If it is enabled and no legacy application explicitly requires it: ```powershell Disable-LocalUser -Name "Guest" ``` For routine work inside the server, use a non-administrator account and elevate only when administrative rights are required. Renaming the built-in Administrator account can be part of a managed security baseline, but it is not a substitute for strong credentials, restricted RDP exposure, monitoring, and least privilege. If you rename it, document the new identity and recovery process first. ## Account lockout should follow a deliberate baseline Check the current local account policy: ```powershell net accounts ``` ![03-account-policy-status.png](https://raff-images.s3.raffusercloud.com/03_account_policy_status_afb7774d97.png) Do not treat one lockout threshold as universally correct. Microsoft’s current Windows Server 2025 OSConfig baseline uses a three-attempt threshold with a 15-minute duration and reset window, while other Microsoft baseline guidance can use different values depending on the product and management model. A stricter threshold slows password guessing but also increases the risk of denial-of-service through deliberate lockouts. For domain environments, configure the policy centrally. For standalone VPS deployments, document the chosen threshold and test administrative recovery before enforcing it. The important production checks are: - lockout is intentionally configured rather than left to chance; - recovery access exists if the primary admin is locked out; - failed logons are monitored; - local administrator passwords are unique; - shared admin accounts are avoided. ## Windows Firewall and RDP should reduce public exposure Keep Windows Firewall enabled on all profiles: ```powershell Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction ``` Inspect the current Remote Desktop rule group: ```powershell Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Select-Object DisplayName, Enabled, Direction, Action, Profile | Format-Table -AutoSize ``` ![04-firewall-and-rdp-status.png](https://raff-images.s3.raffusercloud.com/04_firewall_and_rdp_status_bc691e1fd6.png) Microsoft recommends keeping Windows Firewall enabled and using explicit allow rules for required traffic. For a VPS, start from the rule that inbound access should exist only when the workload needs it. For RDP administration: - restrict source IPs where operationally possible; - prefer a VPN or private administrative path when available; - keep RDP limited to named administrators or intended RDS users; - do not expose SMB, SQL Server, WinRM, or management ports broadly to the internet; - keep a recovery path available before changing remote-access rules. For the detailed firewall workflow, see [Configure Windows Firewall on a Windows VPS](/windows-server/configure-windows-firewall). ## Network Level Authentication should remain enabled for RDP Network Level Authentication requires the user to authenticate before Windows creates a full remote desktop session. Microsoft recommends NLA for most environments because it reduces the resources exposed to unauthenticated connections. Check the RDP NLA policy value: ```powershell Get-ItemProperty ` 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` -Name UserAuthentication ``` A `UserAuthentication` value of `1` means NLA is required. Do not disable NLA simply to make an old RDP client connect. Upgrade the client or document the compatibility exception and its risk. ## SMBv1 should stay removed and SMB signing should be reviewed SMBv1 has significant security weaknesses and is not installed by default on Windows Server 2019 and later. Verify that the server is not relying on it: ```powershell Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol ``` If an old application requires SMBv1, upgrading or replacing that dependency is safer than re-enabling the protocol. Windows Server 2025 also strengthens SMB signing defaults, and Microsoft’s Server 2025 security baseline requires signing on the client and server sides. Review the effective settings: ```powershell Get-SmbClientConfiguration | Select-Object RequireSecuritySignature Get-SmbServerConfiguration | Select-Object RequireSecuritySignature ``` If you enforce SMB signing on an environment that uses old NAS devices or third-party SMB servers, test compatibility first. Do not disable signing merely to make unauthenticated guest access work. Keep TCP 445 off the public internet. If users need file access across locations, use a private network, VPN, or another controlled access design. ## Microsoft Defender should remain an active security layer Verify Defender’s main protection settings: ```powershell Get-MpPreference | Select-Object DisableRealtimeMonitoring, DisableBehaviorMonitoring, DisableScriptScanning ``` ![PowerShell output showing Microsoft Defender real-time, behavior, and script scanning settings on Windows Server.](https://raff-images.s3.raffusercloud.com/05_defender_status_9cc732b829.png) For a normal protected baseline, these values should not show Defender’s real-time, behavior, or script scanning as disabled. Update signatures with: ```powershell Update-MpSignature -Verbose ``` Attack Surface Reduction rules and Controlled Folder Access can add meaningful protection, but they can also interfere with ERP clients, Office automation, scripts, installers, and legacy applications. Test them in audit or controlled rollout modes before enforcing them on a production workload. Do not disable antivirus globally to solve an application problem. Use vendor-documented exclusions only when they are necessary and narrowly scoped. :::cta Explore Security Review Raff security options alongside the Windows Server controls you manage inside the VM. ::: ## Audit policy should capture the events you will actually investigate Check the audit state for high-value categories: ```powershell auditpol /get /subcategory:"Logon" auditpol /get /subcategory:"Account Lockout" auditpol /get /subcategory:"User Account Management" auditpol /get /subcategory:"Process Creation" ``` ![06-audit-policy-status.png](https://raff-images.s3.raffusercloud.com/06_audit_policy_status_9712e21156.png) Microsoft’s Server 2025 baseline enables broad advanced auditing and includes process creation with command-line capture. For a smaller VPS, at minimum make sure you can investigate: - successful and failed logons; - account lockouts; - user-account changes; - administrator and privilege changes; - process creation; - firewall activity relevant to exposed services. Example audit-policy commands: ```powershell auditpol /set /subcategory:"Logon" /success:enable /failure:enable auditpol /set /subcategory:"Logoff" /success:enable auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable auditpol /set /subcategory:"User Account Management" /success:enable /failure:enable auditpol /set /subcategory:"Process Creation" /success:enable ``` For complete production policy, use Microsoft’s advanced audit recommendations or the official baseline rather than stopping at these five categories. ## Security logs need enough retention to be useful A Security log that rolls over too quickly can erase the exact events needed during an incident review. Microsoft’s Server 2025 baseline increases Security log capacity; its baseline documentation references at least 192 MB. Check the current maximum size: ```powershell wevtutil gl Security | Select-String maxSize ``` For a production VPS, choose a log size based on event volume and retention needs rather than an arbitrary number. If the server generates many RDP, authentication, file-share, or application events, increase the Security log and monitor rollover behavior. Also consider sending critical logs to a separate logging or monitoring system so compromise of the server does not remove the only copy of the evidence. ## Failed logons should be monitored, not merely recorded Windows Security event ID `4625` records failed logon attempts. Review recent failures: ```powershell Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4625 StartTime=(Get-Date).AddHours(-24) } ``` A spike in failed RDP logons should trigger a review of: - RDP exposure; - source-IP restrictions; - administrator usernames; - password policy; - stale accounts; - patch state; - whether the server should be reachable directly from the internet at all. Do not rely on lockout policy alone as an anti-brute-force control. ## PowerShell logging improves incident visibility PowerShell script block logging records the content of processed script blocks in the Microsoft-Windows-PowerShell/Operational log, including event ID 4104. Enable it through Group Policy when possible. A registry-based configuration is also available: ```powershell $basePath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' New-Item -Path $basePath -Force | Out-Null Set-ItemProperty -Path $basePath -Name EnableScriptBlockLogging -Value 1 ``` PowerShell logs can contain sensitive values such as tokens, connection strings, or credentials accidentally placed in scripts. Microsoft recommends considering Protected Event Logging when Script Block Logging is used beyond diagnostics. ## Unused services and roles should be removed carefully Reducing unnecessary services lowers attack surface, but randomly disabling services can break applications or management functions. List running services: ```powershell Get-Service | Where-Object Status -eq 'Running' | Sort-Object Name | Format-Table Name, DisplayName ``` Use this process before disabling anything: 1. Identify the service or Windows role. 2. Confirm whether Windows or the application uses it. 3. Check Microsoft or vendor documentation. 4. Take a recovery snapshot if the change is material. 5. Disable only the unnecessary component. 6. Reboot if required. 7. Test the complete workload. For example, disable Print Spooler only on servers that truly do not print and do not run PDF, accounting, ERP, or other software that depends on printing components. ## IPv6 should not be disabled without a specific reason Do not disable IPv6 as a generic hardening step. Microsoft warns that Windows components can depend on IPv6 behavior, and disabling it without a documented requirement can cause unexpected networking problems. The safer rule is simple: leave IPv6 enabled unless the network design specifically requires a change and the workload has been tested after that change. ## Patching is part of hardening A hardened server with old security updates is still exposed. Use a controlled patch process: - review Microsoft release health; - monitor actively exploited vulnerabilities; - take a backup or snapshot before significant patch windows; - patch during a planned maintenance window; - reboot intentionally; - verify both Windows and the hosted application afterward. CISA’s Known Exploited Vulnerabilities catalog is a useful signal for vulnerabilities that are being exploited in the wild, but patch priority should also consider whether the affected feature is installed and exposed on your server. For the full workflow, see [Windows Update Strategy on Production Servers](/windows-server/windows-update-strategy). ## Backups and snapshots are recovery controls, not security substitutes Take a snapshot before high-risk configuration changes, but do not treat snapshots as the only backup strategy. A practical production recovery model includes: - application-aware backups where required; - VM or disk-level recovery points; - at least one copy outside the live server; - documented recovery credentials; - periodic restore testing. A snapshot is valuable when a hardening change breaks the server. It does not replace ransomware-resistant or off-server backups. ## Every security change should have an owner and rollback plan Keep a small hardening changelog: | Field | Example | |---|---| | Date | 2026-08-08 | | Control | Required NLA for RDP | | Owner | Windows administrator | | Reason | Reduce unauthenticated RDP exposure | | Validation | RDP login tested from approved source | | Rollback | Restore previous policy or snapshot | This makes future troubleshooting much faster and prevents a later administrator from undoing a security control because nobody knows why it exists. ## A practical SMB hardening order reduces lockout risk Use this order for an existing Windows VPS: 1. Confirm backup/snapshot and recovery access. 2. Audit users and administrators. 3. Review account and lockout policy. 4. Confirm Windows Firewall is enabled. 5. Review RDP exposure and NLA. 6. Verify SMBv1 is disabled and review SMB signing. 7. Confirm Defender protection is active. 8. Enable useful audit policy and log retention. 9. Review PowerShell logging. 10. Patch Windows and exposed applications. 11. Remove unnecessary services and roles carefully. 12. Document and re-test the workload. 13. Compare the result with Microsoft’s official security baseline. This sequence improves security without starting with the controls most likely to lock you out. ## Common hardening mistakes create avoidable outages ### Applying a baseline without testing the workload Security baselines deliberately change authentication, SMB, RDP, auditing, credential, and protocol behavior. Test before production rollout. ### Disabling Windows Firewall to fix connectivity Fix the specific rule or application listener. Do not make the server broadly reachable because one service does not connect. ### Using RDP lockout policy as the only brute-force defense Reduce exposure first. Use NLA, source restrictions, named accounts, monitoring, and a deliberate access architecture. ### Re-enabling SMBv1 for an old device Treat the device or application as a legacy dependency that needs replacement or isolation rather than weakening the entire server. ### Enforcing Defender controls without an audit period ASR and Controlled Folder Access can block legitimate business software. Test them against the real application workflow. ### Disabling services because the names look unfamiliar Unknown does not mean unnecessary. Research, snapshot, change one item, and test. ### Calling a checklist “compliant” This article is operational guidance, not certification. Compliance frameworks require their own scope, evidence, controls, and validation. ## Raff’s role is the infrastructure layer Raff gives you control of the Windows VM and related infrastructure features; operating-system hardening inside the VM remains an administrator responsibility unless a separate managed service explicitly covers it. For a small production Windows workload, the priority is to make secure defaults repeatable: restricted administration, host firewall, current patches, Defender, modern SMB, meaningful logs, tested backups, and documented changes. ## What's next - [Configure Windows Firewall on a Windows VPS](/windows-server/configure-windows-firewall) - [Windows Update Strategy on Production Servers](/windows-server/windows-update-strategy) - [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) - [Raff Windows Server Hub](/windows-server) - [Raff Windows VM](/products/windows-vm) - [Raff Security](/products/security) ## Sources - Microsoft Learn — [Deploy Windows Server 2025 security baselines with OSConfig](https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines) - Microsoft Learn — [Microsoft Security Compliance Toolkit](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10) - Microsoft Learn — [Windows Firewall](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/) - Microsoft Learn — [Remote Desktop and Network Level Authentication](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remotepc/remote-desktop-allow-access) - Microsoft Learn — [SMB security hardening](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-security-hardening) - Microsoft Learn — [Control SMB signing behavior](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-signing) - Microsoft Learn — [Detect, enable, and disable SMBv1, SMBv2, and SMBv3](https://learn.microsoft.com/en-us/windows-server/storage/file-server/troubleshoot/detect-enable-and-disable-smbv1-v2-v3) - Microsoft Learn — [Advanced audit policy configuration](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/advanced-audit-policy-configuration) - Microsoft Learn — [PowerShell logging](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_logging) - CISA — [Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) - Sources verified: 2026-08-08 --- ### Windows Server Patch Management: Production Update Strategy URL: https://rafftechnologies.com/windows-server/windows-update-strategy Description: Patch Windows Server safely in production with a risk-based update strategy, maintenance windows, rollback protection, staged deployment, reboot control, post-patch validation, and Windows Server 2025 Hotpatch guidance. Windows Server patch management is the process of assessing, testing, installing, rebooting, and validating operating-system updates without turning routine security maintenance into unplanned downtime. On a production Windows VPS, the right strategy is **risk-based**: patch actively exploited or highly exposed vulnerabilities quickly, stage normal monthly security updates through a small validation ring, and keep optional preview updates off production unless they solve a specific problem. Raff provides the Windows VM infrastructure and recovery controls. The server administrator still owns the Windows Update policy, application testing, maintenance window, and post-update verification. ## In short For production Windows Server, review Microsoft release health and security guidance, classify the update by risk, verify backups and rollback options, patch a test or low-risk system first when possible, then update production during a maintenance window. Reboot deliberately and validate the actual workload afterward. Do not use a blanket 7–14 day delay for every security update, and do not treat a VM snapshot as the only backup. ## Production patching starts with a risk decision | Update situation | Recommended response | |---|---| | Known exploitation affecting an exposed component | Prioritize testing and remediation immediately; compress the normal change window | | Critical/security update with no known exploitation | Validate quickly, then deploy through the normal production patch window | | Normal monthly cumulative security update | Stage through test/low-risk systems, then production after validation | | Out-of-band security update | Review the specific issue and affected component immediately | | Optional nonsecurity preview | Usually skip on production unless it fixes a problem you actually have | | Driver/firmware update | Install only when required and supported for the environment | | Windows Server version upgrade | Treat as a migration/upgrade project, not routine monthly patching | CISA maintains the Known Exploited Vulnerabilities catalog specifically so organizations can use evidence of exploitation as an input to vulnerability prioritization. Exposure also matters: an internet-facing service affected by a vulnerability usually deserves a shorter remediation window than a disabled component on an isolated test VM. The goal is not to install every update the minute it appears. The goal is to reduce security exposure without creating avoidable production outages. ## Automatic workstation-style updating is a poor production policy A production server can host RDS sessions, accounting software, SQL Server, IIS, ERP software, file services, automation jobs, or other workloads that users expect to stay available. ![02-windows-update-settings-screen.png](https://raff-images.s3.raffusercloud.com/02_windows_update_settings_screen_ef90ef520c.png) A production update policy should answer these questions before the next monthly release: - Who owns patch approval? - Which server is patched first? - What constitutes an emergency update? - When may the server reboot? - What recovery point exists before change? - Which application checks prove the patch succeeded? - Who communicates downtime to users? - How is the update documented afterward? Microsoft releases monthly Windows security updates on the second Tuesday of each month, commonly called Update Tuesday or Patch Tuesday. Those monthly releases are cumulative, so the operating model should be predictable even though individual risk levels vary. ## The original Raff lab evidence remains valid The existing screenshots and PowerShell checks in this article were captured on a Raff Windows Server 2025 Datacenter Evaluation VM on May 24, 2026. ![PowerShell output showing a Raff Windows VPS running Windows Server 2025 Datacenter Evaluation with build number, CPU count, and memory details.](https://raff-images.s3.raffusercloud.com/01_windows_update_test_environment_a4c4be52d8.png) | Item | Value | |---|---| | OS | Windows Server 2025 Datacenter Evaluation | | Build | 26100 | | CPU | 4 vCPU | | RAM | Approximately 8 GB | | Test date | 2026-05-24 | | Engineer | Serdar Tekin | That lab verified update-history inspection, pending-reboot detection, the PSWindowsUpdate community module, update scanning, and Raff dashboard recovery/reboot controls. It did **not** run a full production monthly patch cycle, so this August revision does not present patch success rates or downtime benchmarks. ## The monthly cycle should use deployment rings instead of a fixed delay A fixed “wait 7–14 days” rule can leave a vulnerable server exposed longer than necessary. A better process uses rings. | Ring | Example | Purpose | |---|---|---| | Ring 0 | Disposable test VM or lab | Confirm Windows boots and the update installs | | Ring 1 | Staging or low-risk server | Test the real application stack | | Ring 2 | Production server | Deploy after validation and risk review | A small business may not have three permanent servers. The same principle still works: create a temporary test VM, patch a lower-risk system first, or validate vendor advisories before patching the primary production server. A practical monthly rhythm is: 1. **Release day:** review Microsoft Security Update Guide and Windows release health. 2. **First validation window:** identify whether the update affects your server version and enabled roles. 3. **Test/low-risk deployment:** patch a representative system when available. 4. **Production window:** deploy after validation, without unnecessary delay. 5. **Emergency exception:** if exploitation or exposure changes the risk, bypass the normal waiting period and accelerate remediation. This model is more defensible than always patching immediately or always waiting two weeks. ## Preflight checks reduce avoidable patch failures Before installing updates, record the current state. A quick view of recently installed hotfixes is: ```powershell Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10 HotFixID, InstalledOn, Description ``` `Get-HotFix` is useful for a quick check, but it is not a complete inventory of every Windows update package. Use Windows Update history, DISM/package inventory, your patch-management platform, and Microsoft release information when you need full update accounting. Check for a pending component-servicing reboot: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' if (Test-Path $key) { Write-Warning 'Component servicing reboot pending' } else { Write-Output 'No component servicing reboot detected' } ``` ![PowerShell output showing recent Windows updates and a pending reboot check on a Windows Server VPS.](https://raff-images.s3.raffusercloud.com/03_update_history_and_pending_reboot_check_64a84eaed5.png) A production preflight should also confirm: - enough free disk space; - healthy Windows services; - application/database backup status; - current VM backup or recovery point; - administrative access outside the normal user workflow; - current application health; - maintenance-window communication; - any vendor advisory for the business application. For clustered, replicated, or multi-server applications, use the application vendor’s patch sequence rather than treating every server as independent. ## Windows release health and the Security Update Guide should be checked before deployment Before production installation, review Microsoft’s current information for the affected version and KB. Look for: - known issues; - installation failures; - authentication or networking regressions; - RDP/RDS issues; - printing issues; - .NET/application compatibility notes; - Known Issue Rollback information; - out-of-band replacement updates; - required servicing-stack or prerequisite information. Also check whether the vulnerability affects a role that is actually installed or exposed on the server. A CVE that affects a disabled feature can have a different operational priority from one affecting an internet-facing service. ## Snapshots are useful rollback points but not the whole backup plan Before a significant production patch window, create an appropriate recovery point in the Raff dashboard and confirm the application’s own backup is healthy where relevant. ![Raff dashboard controls used to create a recovery point or reboot a Windows Server VM before a planned maintenance window.](https://raff-images.s3.raffusercloud.com/05_raff_dashboard_snapshot_or_reboot_b9f7444509.png) Use snapshots for **short-term rollback before change**. Do not treat them as your only backup strategy. For example: - SQL Server should still have database-aware backups. - QuickBooks or ERP data should use the vendor-supported backup process. - Shared files should have file-level/off-server recovery. - Business-critical VMs should have a documented backup retention and restore process. A snapshot can help reverse an operating-system change. It does not replace app-consistent backups, off-server copies, or restore testing. For the broader recovery model, use [Windows VPS Backup Strategy for Small Businesses](/windows-server/windows-vps-backup-strategy-small-business). ## PSWindowsUpdate is an optional community tool The existing lab used **PSWindowsUpdate**, a PowerShell Gallery module, to scan for updates. It is useful for administrators who intentionally permit community PowerShell modules, but it is not a built-in Windows Server cmdlet and should not be presented as Microsoft’s required patch-management method. If your organization permits the module, review the package and repository before installation: ```powershell Find-Module PSWindowsUpdate -Repository PSGallery ``` Then install/import it according to your organization’s module policy: ```powershell Install-Module -Name PSWindowsUpdate -Repository PSGallery -Scope AllUsers Import-Module PSWindowsUpdate ``` A scan without installation: ```powershell Get-WindowsUpdate ``` ![PSWindowsUpdate scan showing available Windows Server updates without installing them.](https://raff-images.s3.raffusercloud.com/04_pswindowsupdate_scan_e91f94a9fe.png) The important distinction remains: ```text Assessment / scan ≠ Installation ``` If you do not permit third-party PowerShell modules, use Windows Update, SConfig on Server Core, WSUS, your endpoint/patch-management system, or another approved management platform. ## Update installation belongs inside a maintenance window A good maintenance window includes enough time for more than the update installer. Plan time for: 1. final health check; 2. application-safe shutdown steps if required; 3. update installation; 4. reboot; 5. possible second reboot; 6. service startup; 7. application smoke tests; 8. user-access verification; 9. rollback decision if validation fails. For manually managed small servers, it is often safer to control the restart explicitly rather than let a script reboot at an unknown point in the change window. If PSWindowsUpdate is part of your approved process, an install command can be: ```powershell Get-WindowsUpdate -Install -AcceptAll ``` Do not add automatic reboot behavior unless the maintenance workflow is specifically designed for unattended restarts and post-reboot validation. ## Server restart policy should be configured intentionally Microsoft’s current Windows Update guidance provides server-specific restart controls through Group Policy. For domain-managed or policy-managed servers, review: ```text Computer Configuration → Administrative Templates → Windows Components → Windows Update → Manage end user experience → Configure Automatic Updates ``` Microsoft documents a server option that can notify administrators for installation and restart rather than treating the machine like an unattended workstation. Also review the policy: ```text No auto-restart with logged on users for scheduled automatic updates installations ``` That policy only applies in the relevant scheduled Automatic Updates configuration, so test the effective policy rather than assuming one registry value controls every update-management tool. For Server Core, Microsoft’s **SConfig** tool provides an Update settings page and is preferable to ad-hoc legacy scripts for basic local configuration. The operating objective is simple: **Windows should not decide the production reboot window accidentally.** ## Post-patch validation must test the application, not only Windows Update After the server returns, validate the operating system first: ```powershell Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10 HotFixID, InstalledOn, Description ``` Re-check pending reboot state: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' if (Test-Path $key) { Write-Warning 'Component servicing reboot still pending' } else { Write-Output 'No component servicing reboot detected' } ``` Then check core system health: ```powershell Get-Service | Where-Object Status -eq 'Stopped' | Sort-Object DisplayName | Select-Object -First 30 Name, DisplayName, StartType ``` Do not assume every stopped service is a problem—many services are intentionally manual or trigger-started. Compare the output with the pre-patch baseline and the services required by the workload. Finally test the real application: | Workload | Minimum post-patch test | |---|---| | IIS | Load the site/API and review application/system errors | | SQL Server | Confirm database service, connection, and a safe test query | | RDP/RDS | Confirm administrative and intended user sign-in paths | | QuickBooks/accounting | Open the application and verify an approved test workflow | | File server | Open a share and test expected permissions | | ERP/LOB app | Start client/service and complete a safe business transaction/test | | Automation | Confirm scheduled task/service resumes normally | The patch window is not finished because the login screen appeared. It is finished when the production workload passes its smoke test. ## The rollback decision needs a deadline Do not spend an unlimited maintenance window debugging a bad patch while users wait. Define a rollback point before change, for example: ```text If the critical application is not healthy within the agreed validation window, stop troubleshooting and execute the documented rollback plan. ``` The rollback method depends on the failure: - uninstall the affected Windows update when supported; - use Known Issue Rollback where Microsoft provides it; - restore an application backup if the application data changed; - revert the VM recovery point when appropriate; - rebuild/restore from backup when rollback cannot safely repair the state. After recovery, document the failed KB, symptoms, logs, and vendor/Microsoft guidance before attempting the update again. ## Optional preview updates should normally stay off production Microsoft distinguishes monthly security releases from optional nonsecurity preview releases. A preview update can be useful when: - it fixes a production issue you are actively experiencing; - Microsoft or an application vendor recommends it for your problem; - you want to validate next month’s nonsecurity changes in a lab. For a healthy production Windows Server, do not install preview releases merely because they are available. Reduce change volume by deploying updates that have a clear security, reliability, or support purpose. ## Windows Server 2025 Hotpatch can reduce some reboot windows Windows Server 2025 Standard and Datacenter can use Microsoft Hotpatch when the machine meets the current Azure Arc-enabled Hotpatch requirements. Microsoft describes Hotpatch as applying certain OS security updates to in-memory code without restarting the machine. For eligible Azure Arc-connected Windows Server 2025 systems: - Azure Arc must be configured; - the supported Server 2025 edition is required; - Virtualization Based Security must meet Microsoft’s prerequisite; - Hotpatch must be enrolled/enabled; - baseline cumulative updates still periodically require rebooting. Hotpatch does **not** eliminate patch management. Microsoft’s model periodically refreshes the cumulative-update baseline, and non-Hotpatch updates such as some .NET, driver, firmware, or other updates can still require a restart. On Raff, Hotpatch should be treated as an optional customer-managed Microsoft capability, not as a default Raff Windows VM feature. ## Emergency patching uses the same controls on a shorter timeline An emergency does not mean abandoning change control. It means compressing it. When a vulnerability is actively exploited or presents unacceptable exposure: 1. Confirm whether the server is affected. 2. Apply immediate mitigations if Microsoft provides them. 3. Confirm current backups/recovery. 4. Test the update quickly where possible. 5. Schedule the earliest safe production window. 6. Patch and reboot if required. 7. Validate the application. 8. Monitor logs and service health afterward. CISA’s KEV catalog is a useful prioritization input, but it is not the only signal. Internet exposure, privileges required, exploit maturity, business criticality, and compensating controls all affect urgency. ## Patch records should be part of the server runbook For each production patch window, record: | Field | Example | |---|---| | Date/time | 2026-08-08 23:00 local | | Server | Accounting-RDS-01 | | Approved KBs | KB numbers installed | | Pre-check | Backup healthy, disk healthy, app healthy | | Recovery point | Snapshot/backup reference | | Reboots | 1 | | Validation | RDP, app login, file/database test passed | | Issues | None / ticket number | | Owner | Windows administrator | This turns patching into a repeatable operating process instead of a memory-based monthly task. ## Raff’s recommended production workflow is risk-based For a small production Windows workload, use this sequence: 1. Review Microsoft Security Update Guide and release health. 2. Determine whether the update affects installed/exposed components. 3. Check CISA KEV and other exploitation signals for urgent issues. 4. Validate backups and a short-term rollback point. 5. Patch a test or lower-risk system first when practical. 6. Notify users and begin the maintenance window. 7. Install the approved updates. 8. Reboot deliberately when required. 9. Validate Windows services and the actual application. 10. Roll back promptly if the agreed smoke test fails. 11. Record the installed KBs and outcome. 12. Remove temporary rollback snapshots after the change is stable according to your retention policy. :::cta Explore Windows VM Run production Windows workloads on Raff while keeping the operating-system patch policy, maintenance window, and application validation under your control. ::: ## Common patching mistakes create more risk than the update itself ### Waiting a fixed 14 days for every security update A delay can be reasonable for a low-risk monthly update, but known exploitation or an exposed vulnerable role can justify much faster remediation. ### Patching without a rollback path Know how you will recover before changing a business-critical server. ### Treating a snapshot as the only backup Snapshots are change rollback tools. Databases and business applications still need their own recovery strategy. ### Installing optional previews on healthy production servers Every unnecessary update increases change surface. Install previews only for a defined reason. ### Using a third-party PowerShell module without supply-chain review PSWindowsUpdate can be useful, but it is a community module. Apply your organization’s normal PowerShell Gallery/module review process. ### Allowing an automatic reboot to define the maintenance window Configure Windows Update and your management tooling so reboot timing matches the operational plan. ### Checking only whether Windows came back online Validate the application, data path, remote access, and required services. ### Leaving a pre-patch snapshot forever Short-term rollback points should have an expiration/cleanup process. Long-term recovery belongs in the backup strategy. ## What's next - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) - [Windows VPS Backup Strategy for Small Businesses](/windows-server/windows-vps-backup-strategy-small-business) - [Windows Server Performance Monitoring](/windows-server/windows-server-performance-monitoring) - [MSSQL Backup Strategy on a Windows VPS](/windows-server/mssql-backup-strategy) - [Raff Windows VM](/products/windows-vm) - [Raff Windows Server Hub](/windows-server) ## Sources - Microsoft Learn — [Update release cycle for Windows](https://learn.microsoft.com/en-us/windows/deployment/update/release-cycle) - Microsoft Learn — [Windows release health](https://learn.microsoft.com/en-us/windows/release-health/) - Microsoft Security Response Center — [Security Update Guide](https://msrc.microsoft.com/update-guide/) - Microsoft Learn — [Configure Group Policy settings for Automatic Updates](https://learn.microsoft.com/en-us/windows-server/administration/windows-server-update-services/deploy/4-configure-group-policy-settings-for-automatic-updates) - Microsoft Learn — [Manage device restarts after updates](https://learn.microsoft.com/en-us/windows/deployment/update/waas-restart) - Microsoft Learn — [Configure Windows Server with SConfig](https://learn.microsoft.com/en-us/windows-server/administration/server-core/server-core-sconfig) - Microsoft Learn — [Hotpatch for Windows Server](https://learn.microsoft.com/en-us/windows-server/get-started/hotpatch) - Microsoft Learn — [Manage Hotpatch on Azure Arc-enabled machines](https://learn.microsoft.com/en-us/azure/update-manager/manage-hot-patching-arc-machines) - CISA — [Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) - PowerShell Gallery — [PSWindowsUpdate](https://www.powershellgallery.com/packages/PSWindowsUpdate) - Sources verified: 2026-08-08 --- ### Configure Windows Firewall on a Windows VPS URL: https://rafftechnologies.com/windows-server/configure-windows-firewall Description: Configure Windows Firewall safely on a Windows Server VPS: check profiles, audit inbound rules, restrict RDP, create narrow port rules, enable firewall logging, test connectivity, and avoid remote lockouts. ## In short Configure Windows Firewall on a production VPS by keeping every firewall profile enabled, leaving inbound traffic blocked by default, and creating only the exceptions your workload actually needs. Scope rules by profile, protocol, application or port, and trusted source address where possible. Before changing RDP rules remotely, confirm a recovery path. Then test the service, review effective rules, enable useful firewall logging, document the change, and remove temporary rules. ## The safest firewall model is default-deny inbound Windows Firewall is a host-based firewall built into Windows Server. Microsoft’s current guidance keeps the firewall enabled and uses a **default block posture for inbound connections**, with explicit allow rules for required traffic. | Task | Recommended action | |---|---| | Check firewall state | Review Domain, Private, and Public profiles | | Publish a website | Allow only required HTTP/HTTPS traffic | | Administer with RDP | Restrict exposure to trusted sources where practical | | Run SQL Server | Prefer private/trusted access instead of public TCP 1433 | | Run SMB | Keep TCP 445 off the public internet | | Open an application port | Scope protocol, local port, profile, and remote address | | Troubleshoot connectivity | Confirm the application is listening before changing the firewall | | Audit a production server | Review inbound allow rules and firewall logs | For most Windows Server deployments, Microsoft recommends allowing outbound traffic by default because switching to default-deny outbound requires a complete inventory of every application and service that needs network access. Treat outbound blocking as an advanced policy, not a routine VPS hardening shortcut. ## What we tested on Raff The original lab for this guide was performed on a Raff Windows Server 2025 Datacenter Evaluation VM. ![PowerShell output showing Remote Desktop firewall rules with display name, enabled state, direction, action, and profile.](https://raff-images.s3.raffusercloud.com/03_rdp_firewall_rules_496503cd53.png) Test environment: | Item | Value | |---|---| | Environment | Raff Windows VM | | OS | Windows Server 2025 Datacenter Evaluation | | Build | 26100 | | CPU | 4 vCPU | | RAM | Approximately 8 GB | | Test date | 2026-05-24 | | Engineer | Aybars Altınyay | The lab verified: - Windows Firewall profile status; - existing Remote Desktop rules; - creation of a temporary inbound TCP rule; - verification of that rule; - cleanup of the temporary rule. The temporary test used TCP `54321`. It did not expose a real production application. This August 2026 revision preserves those screenshots and tested commands while adding current Microsoft guidance for production scoping, rule precedence, logging, and centrally managed firewall policy. ## Step 1 — Check every Windows Firewall profile Run PowerShell as Administrator: ```powershell Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction, AllowLocalFirewallRules ``` You should see the three main profiles: - Domain; - Private; - Public. ![PowerShell output showing Windows Server 2025 test environment and enabled Windows Firewall profiles on a Raff VPS.](https://raff-images.s3.raffusercloud.com/01_firewall_test_environment_and_profiles_f2234afc5c.png) For a production server, keep the firewall enabled on all profiles. Microsoft’s Windows Server 2025 security baseline uses an enabled firewall with a default-deny inbound stance across Domain, Private, and Public profiles. A value such as `NotConfigured` in a policy field does **not** mean the firewall is disabled. Always verify the `Enabled` state and remember that effective policy can combine local settings with Group Policy or other centralized management. ### Verify which network profile is active Before creating a rule that is limited to one profile, check the current network category: ```powershell Get-NetConnectionProfile | Select-Object InterfaceAlias, NetworkCategory, IPv4Connectivity, IPv6Connectivity ``` A firewall rule should normally be enabled only on the profiles where the workload needs it. Avoid using `-Profile Any` in production simply because it is convenient. ## Step 2 — Review existing RDP firewall rules before changing them Remote Desktop is one of the most sensitive inbound rule groups on a Windows VPS. Run: ```powershell Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Select-Object DisplayName, Enabled, Direction, Action, Profile | Format-Table -AutoSize ``` ![PowerShell output showing existing Remote Desktop firewall rules on a Windows Server VPS.](https://raff-images.s3.raffusercloud.com/02_rdp_firewall_rules_857a850de9.png) To inspect the source-address scope attached to those rules: ```powershell Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Get-NetFirewallAddressFilter | Select-Object Name, RemoteAddress ``` Windows Server normally uses TCP and UDP `3389` for direct RDP. Microsoft warns that exposing Remote Desktop directly to the internet increases risk and recommends a VPN when practical; full RDS environments can also use RD Gateway over HTTPS. Before changing RDP firewall rules on a remote server: 1. Confirm your current public source IP. 2. Confirm you have a dashboard/console/recovery path. 3. Record the existing rules. 4. Make one change at a time. 5. Test a second connection before closing the working session. For general RDP setup, see [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp). For multi-user environments, see [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds). ## Step 3 — Understand Windows Firewall rule precedence Firewall rules are not evaluated by a simple top-to-bottom list. Microsoft documents these important behaviors: 1. An explicit allow rule can permit traffic that the default inbound block would otherwise deny. 2. An explicit **block** rule takes precedence over a conflicting allow rule. 3. More-specific rules generally take precedence over less-specific rules, except where an explicit block rule conflicts. 4. Windows Firewall does not provide administrator-assigned weighted rule ordering. This matters when troubleshooting. Creating a new allow rule does not necessarily solve the problem if another explicit block rule matches the same traffic. Check matching block rules as well as allow rules: ```powershell Get-NetFirewallRule -Enabled True -Direction Inbound -Action Block | Select-Object DisplayName, Profile, Direction, Action ``` Do not solve a rule conflict by disabling Windows Firewall globally. ## Step 4 — Create a safe temporary test rule The original Raff lab used TCP port `54321` as a disposable demonstration port: ```powershell New-NetFirewallRule ` -DisplayName "Raff Test Inbound Rule TCP 54321" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 54321 ` -Action Allow ` -Profile Any ``` Then verify it: ```powershell Get-NetFirewallRule -DisplayName "Raff Test Inbound Rule TCP 54321" | Select-Object DisplayName, Enabled, Direction, Action, Profile ``` ![PowerShell output showing a temporary inbound Windows Firewall rule created for TCP port 54321.](https://raff-images.s3.raffusercloud.com/04_test_firewall_rule_created_c56078d401.png) `-Profile Any` is retained here because it matches the original controlled lab test. **Do not copy that scope blindly into production.** Production rules should target the profile or profiles where the application actually operates. Also remember that a firewall rule does not start a service. An application still has to bind and listen on that port. Check listeners with: ```powershell Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, OwningProcess | Sort-Object LocalPort ``` If nothing is listening on the intended port, opening the firewall will not make the application reachable. ## Step 5 — Remove the temporary test rule Delete temporary rules as soon as the test is complete: ```powershell Remove-NetFirewallRule -DisplayName "Raff Test Inbound Rule TCP 54321" ``` Verify cleanup: ```powershell if (Get-NetFirewallRule -DisplayName "Raff Test Inbound Rule TCP 54321" -ErrorAction SilentlyContinue) { Write-Output "Test firewall rule still exists" } else { Write-Output "Test firewall rule removed" } ``` ![PowerShell output confirming the temporary Windows Firewall test rule was removed.](https://raff-images.s3.raffusercloud.com/05_test_firewall_rule_removed_2b629d4aae.png) Temporary exceptions are easy to forget. Use distinctive names and delete them during the same change session. ## Step 6 — Build narrower rules for production workloads Microsoft recommends making inbound exceptions as specific as practical. A useful rule can combine: - direction; - protocol; - local port; - application or service; - network profile; - remote source address; - interface or authentication requirements where needed. ### Example: public HTTPS service For a public IIS site using HTTPS: ```powershell New-NetFirewallRule ` -DisplayName "Allow HTTPS TCP 443" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 443 ` -Action Allow ` -Profile Public ``` Use the profile that actually matches your network design rather than assuming `Public` on every server. ### Example: application port from one trusted source ```powershell New-NetFirewallRule ` -DisplayName "Allow App TCP 8080 from Office" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 8080 ` -RemoteAddress 203.0.113.10 ` -Action Allow ` -Profile Public ``` `203.0.113.10` is an example documentation address. Replace it with the real trusted source IP or approved subnet. ### Example: scope by application as well as port If a specific application should own the listener, a program rule can reduce accidental exposure: ```powershell New-NetFirewallRule ` -DisplayName "Allow Example Service TCP 8443" ` -Direction Inbound ` -Program "C:\Program Files\Example\service.exe" ` -Protocol TCP ` -LocalPort 8443 ` -RemoteAddress 203.0.113.0/24 ` -Action Allow ` -Profile Public ``` Use the real executable path and vendor-documented port requirements. Microsoft does not support wildcard executable paths in application firewall rules. ## Step 7 — Restrict RDP carefully when the source is stable If administrators connect from a fixed office/VPN IP, source restrictions can reduce who can even reach the RDP service. Do **not** disable the existing broad RDP rules until a replacement path is created and tested. A controlled example for TCP RDP is: ```powershell New-NetFirewallRule ` -DisplayName "RDP TCP 3389 from Admin IP" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 3389 ` -RemoteAddress 203.0.113.10 ` -Action Allow ` -Profile Public ``` If you intentionally use RDP over UDP as well, create a matching UDP rule for the same trusted source. Only after confirming the replacement access path works should you narrow or disable broader RDP allow rules. If the administrator’s public IP changes frequently, use a VPN, RD Gateway, or another controlled administrative access design rather than repeatedly opening 3389 to everyone. Microsoft’s RD Gateway role provides external RDS access over HTTPS and avoids exposing internal RDP ports directly to end users. ## Step 8 — Review common Windows Server ports by exposure, not habit | Port | Common use | Production guidance | |---|---|---| | TCP/UDP 3389 | RDP | Restrict source where practical; consider VPN/RD Gateway | | TCP 80 | HTTP | Open only for workloads that intentionally serve HTTP | | TCP 443 | HTTPS | Normal public web/API port when required | | TCP 1433 | SQL Server | Prefer private/trusted access; do not expose broadly | | TCP 445 | SMB | Keep off the public internet | | TCP 5985 | WinRM HTTP | Avoid broad public exposure | | TCP 5986 | WinRM HTTPS | Restrict to trusted management sources | | Custom ports | Business applications | Follow vendor requirements and scope narrowly | Do not use a “standard ports” table as permission to open everything. The application’s architecture decides which ports are necessary. ## Step 9 — Enable firewall logging for troubleshooting and audit Microsoft recommends logging dropped packets and successful inbound connections when firewall visibility is important. For production systems, Microsoft also recommends increasing the firewall log size to at least 20 MB and using separate log files per profile. Example: ```powershell Set-NetFirewallProfile -Profile Domain ` -LogBlocked True ` -LogAllowed True ` -LogMaxSizeKilobytes 20480 ` -LogFileName "$env:SystemRoot\System32\LogFiles\Firewall\pfirewall_Domain.log" Set-NetFirewallProfile -Profile Private ` -LogBlocked True ` -LogAllowed True ` -LogMaxSizeKilobytes 20480 ` -LogFileName "$env:SystemRoot\System32\LogFiles\Firewall\pfirewall_Private.log" Set-NetFirewallProfile -Profile Public ` -LogBlocked True ` -LogAllowed True ` -LogMaxSizeKilobytes 20480 ` -LogFileName "$env:SystemRoot\System32\LogFiles\Firewall\pfirewall_Public.log" ``` Review the effective settings: ```powershell Get-NetFirewallProfile | Select-Object Name, LogAllowed, LogBlocked, LogFileName, LogMaxSizeKilobytes ``` Firewall logs are useful for answering questions such as: - Is Windows dropping the connection? - Which source IP is trying to connect? - Is the request using the port you expected? - Is a new allow rule actually seeing traffic? For larger environments, forward relevant logs to centralized monitoring rather than relying only on files stored on the server. ## Step 10 — Check whether central policy overrides local rules Domain Group Policy, MDM/CSP policy, and local settings can all affect the effective firewall policy. Microsoft supports disabling **local policy merge** in stricter managed environments. When local rule merging is disabled, an administrator can create a local rule but centrally deployed policy may prevent that local rule from becoming effective. Check the profile view: ```powershell Get-NetFirewallProfile | Select-Object Name, AllowLocalFirewallRules, AllowLocalIPsecRules ``` If a server is centrally managed, troubleshoot the effective policy before repeatedly recreating local rules. In a domain environment, production firewall rules should normally be managed through the organization’s intended policy source rather than one-off local changes. ## Step 11 — Test the service from the correct side of the firewall Testing only from inside the server can give a false sense of success. ### Confirm the server is listening ```powershell Get-NetTCPConnection -State Listen | Where-Object LocalPort -eq 443 ``` ### Test from a remote Windows client ```powershell Test-NetConnection YOUR_SERVER_IP -Port 443 ``` For an IP-restricted rule, run the test from an **allowed** source and, when safe, from a **non-allowed** source. The desired result is not simply “the port is open”; it is “the right clients can connect and the wrong clients cannot.” If the remote test fails, check in this order: 1. Is the application running? 2. Is it listening on the expected local address and port? 3. Does an explicit block rule overlap the allow rule? 4. Is the rule enabled on the active profile? 5. Does the rule’s remote-address scope include the client? 6. Is a central policy overriding the local rule? 7. Is another network firewall or routing layer involved? ## A production firewall workflow should be repeatable Use this change sequence: 1. Identify the exact service and business reason. 2. Confirm its vendor-documented ports and protocols. 3. Confirm the service is listening. 4. Identify which clients actually need access. 5. Check the active network profile. 6. Preserve a recovery path before changing RDP/admin rules. 7. Create the narrowest practical rule. 8. Test from the intended client network. 9. Check logs if the test fails. 10. Document the rule name, owner, source scope, port, and reason. 11. Remove temporary or superseded rules. 12. Review exposed rules after major application or architecture changes. For broader host security, pair this workflow with the [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist). :::cta Explore Security Use Windows Firewall together with Raff security controls and a documented server-hardening process rather than relying on a single network rule. ::: ## Useful Windows Firewall PowerShell commands ### List enabled inbound allow rules ```powershell Get-NetFirewallRule -Enabled True -Direction Inbound -Action Allow | Select-Object DisplayName, Profile, Direction, Action | Sort-Object DisplayName ``` ### Show port filters for a rule ```powershell Get-NetFirewallRule -DisplayName "Rule Name" | Get-NetFirewallPortFilter ``` ### Show address filters for a rule ```powershell Get-NetFirewallRule -DisplayName "Rule Name" | Get-NetFirewallAddressFilter ``` ### Find rules by name ```powershell Get-NetFirewallRule | Where-Object DisplayName -Like "*RDP*" ``` ### Disable a rule without deleting it ```powershell Disable-NetFirewallRule -DisplayName "Rule Name" ``` ### Re-enable a rule ```powershell Enable-NetFirewallRule -DisplayName "Rule Name" ``` ### Remove a custom rule ```powershell Remove-NetFirewallRule -DisplayName "Rule Name" ``` ### Open the Advanced Security GUI ```text wf.msc ``` PowerShell is useful for repeatability; Windows Defender Firewall with Advanced Security is useful when you need to inspect profile, scope, program, port, and advanced rule properties visually. ## Common mistakes make firewall rules broader than intended ### Disabling Windows Firewall to troubleshoot an application Do not turn off the firewall as a production fix. Confirm the listener, rule, profile, address scope, and logs instead. ### Using `-Profile Any` for every production rule A lab rule can use `Any` for demonstration, but a production exception should normally be enabled only where the workload requires it. ### Creating a narrow RDP allow rule while leaving a broad allow rule enabled The broad rule still permits traffic. To actually restrict RDP, verify the replacement path and then narrow or disable the broader rule safely. ### Forgetting explicit block-rule precedence An explicit block can override an allow rule. Check for conflicts instead of creating duplicate allow rules. ### Opening SQL Server or SMB to everyone Database and file-sharing protocols should normally be limited to application servers, trusted IPs, private networks, VPN users, or another controlled network path. ### Assuming a listening port means the firewall allows it A listener and a firewall rule are two different conditions. Both must be correct for inbound connectivity. ### Assuming a firewall rule proves the application is secure A firewall reduces network exposure. It does not replace patching, strong authentication, least privilege, application security, monitoring, or backups. ## Raff’s recommendation is to keep the rule set small and explainable For production Windows workloads: - keep Windows Firewall enabled on all profiles; - preserve the default-deny inbound model; - keep outbound allow-by-default unless you operate a managed deny-by-default outbound policy; - scope inbound exceptions to the actual application, port, profile, and client sources; - reduce direct RDP exposure; - keep SMB and database ports away from the public internet; - enable firewall logging when the server needs operational visibility; - document every custom rule; - clean up test and superseded rules; - manage policy centrally when the server belongs to a domain or managed fleet. The objective is not to have many firewall rules. It is to have a small set of rules that an administrator can explain and validate. ## Tested on > Tested on Raff Windows Server 2025 Datacenter Evaluation, build 26100, 4 vCPU, approximately 8 GB RAM, on 2026-05-24 by Aybars Altınyay. The original lab verified firewall profile status, Remote Desktop rules, creation of a temporary TCP 54321 inbound rule, verification of that rule, and cleanup. The August 2026 update adds Microsoft-sourced production guidance without claiming those additional policy scenarios were re-tested in the lab. ## What's next - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) - [How to Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) - [Multi-User RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-vs-rds) - [Windows Server Patch Management Strategy](/windows-server/windows-update-strategy) - [Raff Windows VM](/products/windows-vm) - [Raff Security](/products/security) ## Sources - Microsoft Learn — [Windows Firewall overview](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/) - Microsoft Learn — [Windows Firewall rules and recommendations](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/rules) - Microsoft Learn — [Configure Windows Firewall logging](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/configure-logging) - Microsoft Learn — [Configure firewall rules with Group Policy](https://learn.microsoft.com/en-us/windows/security/threat-protection/windows-firewall/best-practices-configuring) - Microsoft Learn — [New-NetFirewallRule](https://learn.microsoft.com/en-us/powershell/module/netsecurity/new-netfirewallrule?view=windowsserver2025-ps) - Microsoft Learn — [Set-NetFirewallProfile](https://learn.microsoft.com/en-us/powershell/module/netsecurity/set-netfirewallprofile?view=windowsserver2025-ps) - Microsoft Learn — [Windows Server 2025 security baseline with OSConfig](https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines) - Microsoft Learn — [Remote Desktop access from outside a network](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remotepc/remote-desktop-allow-outside-access) - Microsoft Learn — [Remote Desktop Gateway](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remote-desktop-gateway-role) - Sources verified: 2026-08-08 --- ### Multi-User RDP: 2 Admin Sessions vs RDS Session Host URL: https://rafftechnologies.com/windows-server/multi-user-rdp-vs-rds Description: Compare Windows Server’s two administrative RDP connections with Remote Desktop Services Session Host for multi-user desktops, including licensing, roles, security, workgroup limits, and when SMB teams should use each model. Remote Desktop Protocol (RDP) is the connection protocol. Remote Desktop Services (RDS) is the Windows Server platform for delivering managed multi-user desktops and RemoteApp programs. The practical decision on a Windows VPS is therefore not “RDP or RDS” in the abstract. It is **Remote Desktop for Administration versus an RD Session Host deployment for end users**. Microsoft documents two concurrent remote connections for Windows Server administration without RDS CALs. Those connections are for administrators maintaining the server. They are not a substitute for licensing a shared desktop used by employees every day. ## In short Use the two built-in administrative RDP connections when one or two administrators occasionally maintain the server. Use **RD Session Host** when employees need their own Windows desktop sessions or RemoteApp access. Customer-owned RDS deployments require the applicable RDS CAL model; Raff-hosted SPLA deployments use RDS SALs for authorized users. A newly created RD Session Host has a 120-day licensing grace period, but that is a deployment window, not a production licensing strategy. ## The decision is administration versus user sessions | Scenario | Two admin RDP connections | RD Session Host | |---|---:|---:| | One administrator maintains Windows Server | Yes | Usually unnecessary | | Two administrators occasionally troubleshoot | Yes | Usually unnecessary | | Three or more employees need separate desktops | No | Yes | | Staff use QuickBooks, ERP, Office apps, or other desktop software daily | No | Yes | | Users access an IIS website from their own devices | Yes, for server admins only | Not required for website users | | Users connect directly to SQL Server from approved clients | Yes, for server admins only | Not required just for database access | | You want RemoteApp publishing | No | Yes | | You need collections and centralized session management | No | Yes | The key question is simple: **are people administering the server, or are people using the server as their workplace?** ## Remote Desktop for Administration has a two-connection limit Microsoft’s current Windows Server troubleshooting guidance states that Remote Desktop supports **two concurrent remote connections for administration** and that those connections do not require RDS CALs. To support more than two administrative connections or multiple end-user sessions, Microsoft directs administrators to install the RD Session Host role and use the appropriate RDS licensing model. That means the built-in two-session model is appropriate for: - server maintenance; - Windows Update checks; - application administration; - Event Viewer and log review; - PowerShell and Server Manager work; - occasional troubleshooting by one or two administrators. It is not intended to become a shared office desktop by creating many local users and rotating them through the same two connection slots. ## The original Raff lab confirmed the two-session behavior The screenshots in this article come from a Raff Windows Server 2025 Datacenter Evaluation lab performed on May 24, 2026. ![PowerShell output showing a Raff Windows VPS running Windows Server 2025 Datacenter Evaluation with build number, CPU count, and memory details.](https://raff-images.s3.raffusercloud.com/01_windows_server_2025_test_environment_ae1e8dac8c.png) | Item | Value | |---|---| | OS | Windows Server 2025 Datacenter Evaluation | | Build | 26100 | | CPU | 4 vCPU | | RAM | Approximately 8 GB | | Test date | 2026-05-24 | | Engineer | Serdar Tekin | The lab verified that two administrative RDP sessions could run concurrently, a third login was blocked until an existing session was disconnected, the main RDS roles were available but not installed on the fresh server, and those roles could be installed for further RDS testing. This August revision keeps that first-hand evidence but does not claim a fresh capacity or licensing benchmark. ## Two active admin sessions do not make the server an RDS host In the lab, two temporary administrator accounts were connected at the same time. ![PowerShell query user output showing two active administrative RDP sessions on a Windows Server VPS.](https://raff-images.s3.raffusercloud.com/05_two_admin_rdp_sessions_active_f22646e8a2.png) That behavior is normal Remote Desktop for Administration. The sessions exist so administrators can manage the operating system. A business should not design its staff workflow around those administrative slots. If users are signing in to run accounting software, ERP clients, Office applications, browser-based business tools, or another desktop application all day, the workload has moved into RDS territory even if only one or two people happen to be connected today. ## The third administrative connection shows the boundary clearly With two administrative sessions already active, the lab attempted another sign-in. ![Windows Remote Desktop warning showing that a third login is blocked because too many users are already signed in.](https://raff-images.s3.raffusercloud.com/06_third_rdp_session_limit_93ec97054f.png) The practical lesson is not “find a way around the limit.” The lesson is that Windows Server separates remote administration from multi-user desktop delivery. Changing a connection-limit Group Policy does not turn the built-in administrative mode into a properly designed RDS deployment. For end users, deploy RD Session Host and license the environment correctly. ## RD Session Host is the Windows Server multi-session role Microsoft defines **RD Session Host (RDSH)** as the RDS role that runs session-based desktops and RemoteApp programs. Multiple users can share one Windows Server while each user receives an isolated session. RDS can also include other roles depending on architecture: | Role | Purpose | |---|---| | RD Session Host | Runs the users’ desktops and RemoteApp programs | | RD Licensing | Issues and tracks RDS CALs in customer-owned CAL deployments | | RD Connection Broker | Reconnects users to sessions and manages collections/load balancing | | RD Gateway | Provides external RDP access over HTTPS rather than exposing internal RDP directly | | RD Web Access | Publishes desktops and RemoteApps through a web portal/feed | A very small deployment may use fewer components than a larger RDS farm. Do not assume that every server needs every role on the same VM. ## Terminal server: The old name for RDS Session Host Windows Server 2008 R2 renamed Terminal Services to Remote Desktop Services, and the terminal server role became RD Session Host. The architecture behind both names is identical: one Windows Server running isolated desktop sessions for multiple users over RDP. If a vendor requirement, an old runbook, or a consultant quote says "terminal server," read it as RD Session Host plus the licensing model described in this article. No current version of Windows Server 2019, 2022, or 2025 installs a component called Terminal Server; the name survives only in legacy documentation and search habits. ## A fresh Windows Server VPS is not an RD Session Host by default Before role installation, the Raff lab checked the main RDS components: ```powershell Get-WindowsFeature RDS-RD-Server, RDS-Licensing, RDS-Connection-Broker, RDS-Web-Access | Format-Table Name, DisplayName, InstallState -AutoSize ``` The features were available but not installed. ![PowerShell output showing Remote Desktop Services roles available but not installed on a fresh Windows Server VPS.](https://raff-images.s3.raffusercloud.com/07_rds_roles_available_before_install_e075b056b3.png) This is an important distinction: **RDP being enabled does not mean RDS Session Host has been deployed**. For a production RDS environment, choose the architecture first, then install only the roles required for that architecture using Microsoft’s supported deployment guidance. ## The original lab also verified RDS role installation During the May 2026 lab, the RDS role components were installed and checked after restart. ![PowerShell output showing Remote Desktop Services roles installed after reboot on a Windows Server VPS.](https://raff-images.s3.raffusercloud.com/09_rds_roles_installed_after_restart_8b2ad45d71.png) That screenshot proves the role state on that specific lab VM. It does not by itself prove a production-ready RDS deployment. Production still requires decisions about: - licensing; - user identities and groups; - session collections where applicable; - certificates; - external access architecture; - profile storage; - application multi-session compatibility; - backups; - monitoring; - capacity planning; - security hardening. ## Multi-user RDS must use the correct licensing model The old version of this article treated every Raff RDS environment as a customer RDS CAL deployment. That is too broad. There are two important models. ### Customer-owned Windows Server / BYOL deployment Microsoft’s standard RDS model uses **RDS Client Access Licenses (RDS CALs)**. Each user or device connecting to an RD Session Host running Windows Server needs the applicable RDS CAL. Two CAL modes exist: - **Per User** — assigned to a user identity; - **Per Device** — assigned to a connecting device. For domain-joined RDS deployments, Microsoft permits either Per User or Per Device mode. For **workgroup RDS deployments, Microsoft requires Per Device CALs; Per User CALs are not permitted**. ### Raff-provided SPLA deployment Raff is a Microsoft SPLA partner. In the hosted service-provider model, Microsoft uses **RDS Subscriber Access Licenses (RDS SALs)** rather than asking the customer to supply ordinary RDS CALs for the hosted service. Microsoft’s RDS role guidance states that service providers need enough RDS SALs to cover the authorized unique users that sign in to the hosted service each month. So the high-level distinction is: ```text Customer-owned / BYOL RDS → RDS CAL model Raff-provided SPLA RDS → RDS SAL model ``` For the detailed licensing decision, read [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) and [Windows Server Licensing on Raff](/windows-server/windows-licensing). ## The 120-day RDS grace period is not a licensing loophole Microsoft currently documents a **120-day licensing grace period** for a newly created RD Session Host. During that technical grace period, a license server is not required for the session host to accept RDS connections. After the grace period, a customer-owned CAL deployment needs a properly activated RD Licensing server, the correct licensing mode, and valid RDS CALs for users or devices to continue connecting. Do not design a production service around resetting or repeatedly relying on the grace period. Microsoft’s current troubleshooting guidance explicitly recommends implementing a license server and license pack rather than treating a grace-period reset as the solution. For Raff-hosted SPLA services, contractual SPLA licensing obligations are separate from the Windows technical grace-period mechanism. The existence of the 120-day Windows grace period does not create 120 days of free commercial licensing rights. ## Workgroup RDS has an important Per Device limitation A small Windows VPS is sometimes deployed as a standalone workgroup server rather than joining Active Directory. Microsoft’s current licensing configuration guidance says: - domain-joined RDS deployments can use Per User or Per Device CALs; - workgroup RDS deployments must use **Per Device** CALs; - Per User CALs are not permitted for the workgroup configuration. Microsoft has also added authentication requirements for workgroup RD Session Hosts communicating with an RD Licensing server after the security update for CVE-2024-38099. Do not weaken that authentication requirement just to make an old configuration work; Microsoft warns that disabling enforcement increases security risk. If a team is growing beyond a very small standalone deployment, identity architecture should be reviewed before adding more RDS users. ## RDS is for users who need desktops or RemoteApp Use RD Session Host when users need to work inside Windows Server itself. Common examples include: - QuickBooks Desktop and accounting applications; - ERP and inventory clients; - Microsoft Access or legacy Windows applications; - line-of-business software that must stay close to its data; - RemoteApp publishing; - a standardized shared Windows desktop for branch or remote staff. Microsoft describes RDS as a platform for delivering full desktops and individual RemoteApp programs. RD Session Host is specifically designed for multiple users sharing a Windows Server instance. ## RDS is unnecessary when users consume a server-side service directly Do not deploy RDS simply because many people use something hosted on the server. | User need | Better model | |---|---| | Visit an IIS website | Users connect over HTTPS; admins use ordinary admin RDP | | Connect to SQL Server from an approved client | Use database connectivity; admins use ordinary admin RDP | | Consume an API | Connect to the API endpoint | | Use a shared file service | Use a controlled file-sharing architecture | | Run a scheduled automation | Use Task Scheduler or a service account | | Administrators maintain the VM | Use the two administrative RDP connections | | Employees need Windows desktops/apps | Use RD Session Host | The deciding factor is not the number of people who benefit from the server. It is whether they need interactive Windows sessions on the server. ## A simple decision framework prevents overbuilding ```text Do users need to sign in to the Windows desktop to do their daily work? | |-- No | Run the application/service normally. | Keep RDP for administrators. | |-- Yes Are the connections only occasional server administration by up to two admins? | |-- Yes | Use Remote Desktop for Administration. | |-- No Deploy RD Session Host. Choose the licensing model. Plan identity, security, profiles, backups, and capacity. ``` :::cta Deploy Windows Now Deploy the Windows VM first, then choose admin-only RDP or a properly licensed RDS design based on how users will actually work. ::: ## Capacity planning belongs after the access-model decision Do not decide between admin RDP and RDS based on a CPU/RAM table. First determine the access model, then size the VM for the real applications and number of concurrent users. Microsoft’s current RDS planning guidance recommends sizing around user personas and actual CPU, memory, storage I/O, network, and application behavior. A multi-session server running browser-heavy office work behaves differently from one running accounting software or database reporting. For concrete planning ranges, use [Windows VPS Sizing for Remote Users: 1, 3, 5, 10 Users](/windows-server/windows-vps-sizing-remote-users). That article owns the sizing guidance so this comparison can stay focused on architecture and licensing. ## Security architecture changes when RDS becomes a user service An administrator connecting directly to a server is different from a workforce using the server all day. For a production RDS environment: - keep Network Level Authentication enabled; - restrict direct RDP exposure where practical; - use Windows Firewall deliberately; - consider RD Gateway for external access rather than exposing internal RDP broadly; - use non-administrator accounts for normal users; - protect administrator accounts separately; - configure auditing and monitoring; - patch Session Hosts and applications on a controlled schedule; - use valid certificates for released RDS services where required; - test application multi-session compatibility. Microsoft describes RD Gateway as a way to provide external RDP access through HTTPS while reducing direct exposure of internal RDP ports. The full security design depends on the size and sensitivity of the environment. For host-level controls, use the [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist). ## RemoteApp can be better than a full desktop If users need only one or two Windows applications, publishing those applications through RemoteApp can be cleaner than giving everyone a complete server desktop. RemoteApp can reduce user confusion and keep the environment closer to an application-delivery model. It does not remove RDS licensing requirements, and the application still needs to support multi-session use. Choose a full desktop when users need several tightly integrated applications, broad file access inside the session, or a traditional remote-workspace experience. Choose RemoteApp when the application itself is the product the user needs. ## Common mistakes blur the admin/RDS boundary ### Treating two admin sessions as two employee licenses The two built-in connections are for server administration. They are not a general-purpose two-user office desktop entitlement. ### Trying to bypass the two-session limit with Group Policy Changing connection limits does not replace RD Session Host or licensing. If users need multi-session desktops, build RDS correctly. ### Saying every Raff RDS user needs a customer RDS CAL That ignores SPLA. Customer-owned deployments use the applicable CAL model; Raff-provided hosted licensing uses the applicable SPLA SAL model. ### Buying Per User CALs for a workgroup deployment Microsoft does not permit Per User CAL mode for workgroup RDS. Use Per Device or redesign the identity model. ### Treating the 120-day grace period as production licensing The grace period exists to allow deployment and configuration. Plan valid licensing before it expires and before relying on the server for business-critical access. ### Installing every RDS role on one server by default Small and large RDS deployments have different architecture needs. Install the roles the design requires rather than copying a role list from a lab. ### Sizing from user count alone A five-user ERP server and a five-user light-office server can need very different resources. Measure the actual workload. ## Raff’s recommendation starts with the user workflow For a Windows VM that mainly runs IIS, SQL Server, APIs, automation, or another server-side workload, keep RDP as an administrative tool. One or two administrators can maintain the VM without turning it into an RDS environment. If employees need to sign in every day and run Windows applications inside the server, treat the project as RDS from the start. Plan the licensing model, user identities, external access, application compatibility, capacity, backups, and security before onboarding staff. For Raff-hosted licensing, confirm whether the workload will use Raff’s SPLA model. For customer-owned licensing, confirm the customer’s CAL and Windows Server rights separately. ## What's next - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - [Windows Server Licensing on Raff](/windows-server/windows-licensing) - [Windows VPS Sizing for Remote Users](/windows-server/windows-vps-sizing-remote-users) - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) - [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) - [Raff Windows VM](/products/windows-vm) ## Sources - Microsoft Learn — [Troubleshoot Remote Desktop disconnected errors](https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/troubleshoot-remote-desktop-disconnected-errors) - Microsoft Learn — [Remote Desktop Services overview](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [License Remote Desktop session hosts](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-license-session-hosts) - Microsoft Learn — [RDS licensing troubleshooting guidance](https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/troubleshoot-rds-licensing-guidance) - Microsoft Learn — [Remote Desktop Services access from anywhere](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-plan-access-from-anywhere) - Sources verified: 2026-08-08 --- ### How to Migrate Windows Server 2016 to 2025: Side-by-Side AD DS, File Shares, and SQL Guide URL: https://rafftechnologies.com/windows-server/migrate-windows-server-2016-to-2025 Description: Move from Windows Server 2016 before support ends. Plan a side-by-side migration to Windows Server 2025 on Raff for AD, files, SQL, apps, and cutover. ## In short Windows Server 2016 reaches **end of extended support on January 12, 2027**. After that date, Microsoft stops shipping security updates and patches. Servers keep running, but every new vulnerability stays open forever unless you pay for Extended Security Updates (ESU), which roughly costs 75% of a new license per year and doubles annually for three years. The right move for most small businesses is to migrate to **Windows Server 2025** before the deadline, using the **side-by-side method** Microsoft officially recommends: stand up a fresh Server 2025 VM, migrate AD DS, file shares, SQL Server, and apps across, then decommission the old box. This guide walks the full procedure step by step. **Need a hand? Raff Technologies migrates new customers onto Windows Server 2025 for free; you pay only for the destination VM.** The offer is below. ## Why this matters now (and why January 2027 is closer than it feels) There are three reasons not to wait: **1. Migrations take months in practice, not weeks.** A "one server" small-business environment running AD DS, file shares, SQL Server, and a line-of-business app is realistically a 4-8 week project when you factor in: testing the new server, validating app compatibility, scheduling the cutover during a maintenance window (which usually means a weekend, which usually means waiting two or three weeks for one that works), training users on any small workflow changes, and dealing with the inevitable "wait, what about X" discovery items. If you start in October 2026, you finish in December. If you start in December 2026, you miss the deadline. **The credible window to start is mid-2026.** **2. ESU costs explode.** Extended Security Updates are Microsoft's paid lifeline for organizations that genuinely can't migrate in time. Pricing: roughly **75% of the original license cost per year, doubling each subsequent year, capped at three years**. For Server 2016 Standard at ~$1,069 license cost, you're looking at roughly $802 (Year 1), $1,604 (Year 2), $3,208 (Year 3), per server. That's $5,614 over three years for one server, just to keep getting patches. A new Server 2025 Standard license is cheaper than two years of ESU. ESU only makes sense if you have a hard application dependency that can't migrate. **3. Compliance and cyber insurance.** Many frameworks (PCI DSS, HIPAA, SOC 2, ISO 27001) require that production systems run a vendor-supported OS. Cyber insurance policies increasingly include lifecycle clauses that void coverage for breaches involving unsupported software. If you're audited or breached after January 12, 2027 while running unpatched Server 2016, the financial exposure can dwarf the migration cost. ## Who this guide is for You run **one or two Windows Servers** for a 10 to 100 employee business. Typically that means a single VM doing **everything**: Active Directory Domain Services, file shares, SQL Server, line-of-business apps, sometimes Remote Desktop Services. The server has been ticking along for 8+ years. It probably runs Server 2016, sometimes Server 2012 R2 (which is even further out of support and treated effectively the same way here, with one extra hop in the upgrade path). If you have **multiple specialized servers** (separate DC, separate file server, separate SQL Server, separate RDS host), this guide still applies; you just repeat the relevant procedure per server. If you have **forest with multiple domains** or **multiple sites with replication**, you're in enterprise territory and should engage a consultant; the principles are the same but the operational complexity goes beyond what a single guide covers. This guide does **not** cover: - Upgrading the **Hyper-V host OS** if your Server 2016 is itself a hypervisor running guest VMs. That's a separate procedure. - **Exchange Server** migration. Exchange 2016 has its own EOL clock (October 14, 2025, already passed) and a completely different migration path. - **WSUS, ADFS, or Certificate Services** specifics. Each has its own migration nuances. ## What changed: why side-by-side beats in-place for 2026 **Microsoft's official recommendation for Server 2016 → 2025 is a side-by-side migration**, also called clean-install-and-migrate. From Microsoft Learn: > The recommended way to upgrade a domain is to use a clean OS install to promote new servers to DCs that run a newer version of Windows Server and demote the older DCs as needed. This method is preferable to upgrading the operating system of an existing DC, which is also known as an in-place upgrade. A clean OS install ensures you get the full Active Directory performance improvements included in new versions of Windows Server. Three reasons this matters: **1. In-place upgrades carry forward 8+ years of cruft.** Registry artifacts, half-uninstalled software, broken WMI providers, leftover services. A 2016 server that's been running since 2018 has accumulated layers of state nobody documented. In-place upgrade carries it all forward into 2025. Side-by-side gives you a clean machine. **2. AD DS in-place upgrades are riskier.** Schema changes are **irreversible**. Microsoft's own docs caution: "Changes to the domain and forest functional levels are irreversible." If something goes sideways during an in-place AD DS upgrade, your recovery is "restore from a verified backup," and many small businesses don't have one of those. Side-by-side gives you the old DC as a fallback throughout the migration. **3. The in-place path from 2016 to 2025 is technically supported but operationally awkward.** Microsoft supports direct 2016 → 2025 upgrades in some configurations, but adds prerequisites (manual `adprep /forestprep`, current cumulative updates, validated functional levels). Each prerequisite is another place to fail. **When in-place upgrade is acceptable:** homelab, single-purpose non-production server, fully backed-up environment where you've tested the restore. For production with real users and data, follow the side-by-side path below. ![Windows Server 2016 reaches end of support on January 12, 2027; migrate to Windows Server 2025 before then.](https://raff-images.s3.raffusercloud.com/windows_server_2016_end_of_support_thumbnail_png_ba27eb0deb.jpg) ## What you'll need - A new **Raff Windows Server 2025** VM with enough resources for your destination workload. For a typical 10-100 employee combined DC + file server + SQL + app server, recommend the **8 vCPU / 16 GB RAM / 180 GB NVMe** Windows plan ($70.49/month compute). Lighter workloads fit on the **4 vCPU / 8 GB / 120 GB** plan ($39.59/month compute). - **Network connectivity** between your existing Windows Server 2016 (on-premises, in a colo, or on another cloud like AWS, Azure, or GCP) and the new Raff Windows Server 2025. Typically a site-to-site IPsec VPN between your existing network and the Raff VPC where the new server lives. Raff's free migration offer below includes setting this up for you. - **Admin credentials** on both servers (Enterprise Admin and Schema Admin on the source domain). - **A current, tested backup** of the source server. Validate the restore works on a separate VM before you start. This is your fallback if anything goes wrong. - **A documented inventory** of what's on the old server: roles, installed apps, shares, scheduled tasks, custom services, users and groups, group policies, file shares with permissions, SQL databases, certificates, DNS zones. - **A maintenance window** for cutover (typically 4-8 hours, scheduled for a weekend evening). - **Estimated total time:** 4-8 weeks elapsed from kickoff to decommission. Active hands-on work is roughly 20-40 hours over that window. Before you dive into the procedure: if your destination is a Raff Windows Server 2025, you don't have to run this yourself. Raff plans and executes the full side-by-side migration for new customers, free beyond the destination VM's monthly cost, with a scheduled cutover you're in the room for. ## Phase 1: Pre-flight checks on the source server Before touching anything, validate the source server is healthy. Run these on the Server 2016 box. ### Check AD DS health ```powershell # Run AD DS diagnostics dcdiag /v # Replication health (only matters if you have multiple DCs) repadmin /replsummary repadmin /showrepl ``` Look for `passed` on every test in `dcdiag`. Any `failed` tests get fixed before migration. The most common failures are DNS misconfigurations and time sync drift; both need to be clean before adding a new DC to the domain. ### Check current functional level ```powershell # Check domain and forest functional levels Get-ADDomain | Format-List Name, DomainMode Get-ADForest | Format-List Name, ForestMode ``` You need **Windows Server 2016 domain and forest functional level** as the **minimum** to introduce a Server 2025 DC. If the levels show `Windows2016Domain` and `Windows2016Forest`, you're good. If they're lower (e.g., `Windows2012R2Domain`), raise them first using `Active Directory Domains and Trusts` console (right-click the domain, "Raise Domain Functional Level"). **Functional level raises are irreversible.** ### Check SYSVOL replication is DFSR (not FRS) ```powershell # Check SYSVOL replication engine Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\DFSR\Parameters\SysVols\Migrating Sysvols" -Name LocalState ``` If `LocalState` is `3` (ELIMINATED), you're on DFSR and good to go. If the key doesn't exist or has a different value, you're still on FRS, which is **not supported** for Server 2025 DCs. Migrate SYSVOL from FRS to DFSR before adding the 2025 DC. (Microsoft has a separate FRS-to-DFSR migration guide; this is rare on 2016 installs but common on environments that upgraded from older versions.) ### Identify FSMO role holders ```powershell # Find which DC holds each FSMO role netdom query fsmo ``` Output shows the Schema master, Domain naming master, PDC, RID master, and Infrastructure master. In a single-DC environment, all five roles are on your one server. Note them down; you'll transfer them to the new 2025 DC later. ### Inventory shares and permissions ```powershell # List all SMB shares with paths and descriptions Get-SmbShare | Format-Table Name, Path, Description -AutoSize # For each share, capture full ACL Get-SmbShare | ForEach-Object { Write-Host "`n=== Share: $($_.Name) ===" -ForegroundColor Cyan Get-SmbShareAccess -Name $_.Name | Format-Table } # Capture NTFS permissions on share root paths Get-SmbShare | Where-Object Special -eq $false | ForEach-Object { Write-Host "`n=== NTFS ACL: $($_.Path) ===" -ForegroundColor Cyan Get-Acl $_.Path | Format-List } ``` Save this output. You'll reference it after migration to confirm permissions transferred correctly. ### Inventory local users and groups ```powershell Get-LocalUser | Format-Table Name, Enabled, LastLogon, Description Get-LocalGroup | Format-Table Name, Description Get-LocalGroup | ForEach-Object { Write-Host "`n=== Group: $($_.Name) ===" Get-LocalGroupMember -Name $_.Name | Format-Table } ``` (In a domain environment, most users live in AD not local; this matters more for the file server and app server.) ### Document app dependencies For each line-of-business app installed: - Vendor name and product name with version - Whether it's certified for Server 2025 (check the vendor's compatibility matrix) - Where it stores data (SQL database, flat files in `C:\ProgramData\Vendor`, etc.) - License keys (often locked to hostname or hardware ID; you may need vendor support during the move) - Any service accounts it uses This step takes the longest. Don't skip it. The number-one cause of migration disasters is "we forgot about the QuickBooks server that the accounting team uses once a quarter." ## Phase 2: Prepare the new Windows Server 2025 Provision your new Raff Windows Server 2025 VM. Hostname can be whatever your naming convention dictates; we'll use `NEW-DC-01` in examples below. :::cta ### Initial server config ```powershell # Rename the server (if not done during provisioning) Rename-Computer -NewName "NEW-DC-01" -Restart # Set a static IP (recommended for DCs) $ipAddress = "10.0.0.20" # your network's appropriate static IP $prefixLength = 24 $gateway = "10.0.0.1" $dnsPrimary = "10.0.0.10" # the OLD Server 2016 DC's IP (temporarily) New-NetIPAddress -InterfaceAlias "Ethernet" ` -IPAddress $ipAddress ` -PrefixLength $prefixLength ` -DefaultGateway $gateway Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses $dnsPrimary ``` Point the new server's DNS at the **OLD Server 2016 DC** during the join phase. Once the new DC is promoted, you'll flip DNS to point at itself. ### Apply all Windows Updates ```powershell # Install PSWindowsUpdate module Install-Module -Name PSWindowsUpdate -Force -SkipPublisherCheck # Install all available updates Get-WindowsUpdate -Install -AcceptAll -AutoReboot ``` This can take 30-60 minutes on a fresh image. Don't skip it. Server 2025 cumulative updates often include AD DS fixes that matter for your migration. ### Join the existing domain ```powershell # Replace yourdomain.local with your actual AD domain name $domain = "yourdomain.local" $cred = Get-Credential # prompts for a Domain Admin credential Add-Computer -DomainName $domain -Credential $cred -Restart ``` After reboot, sign in with a Domain Admin account. ## Phase 3: Promote the new server to a domain controller ![Side-by-side AD migration: a new Windows Server 2025 domain controller promoted alongside the existing 2016 DC, with FSMO roles transferring to the 2025 server.](https://raff-images.s3.raffusercloud.com/active_directory_2016_to_2025_migration_diagram_png_a189dbbe9b.jpg) This is the step where Server Manager **automatically runs adprep** for you. Microsoft confirms in their official docs: > In Server Manager, under Add Roles and Features, install Active Directory Domain Services on the new Windows Server. This action automatically runs adprep on the earlier version forest and domain. You only need to run `adprep` manually for in-place upgrades. For our side-by-side path, Server Manager handles it. The schema version moves from **87 (Server 2016)** to **91 (Server 2025)** automatically as part of the AD DS role install. ### Install AD DS role ```powershell # Install AD DS with management tools Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools ``` Expected: `Success: True, Restart Needed: No`. ### Promote to domain controller ```powershell # Promote this server as an additional DC in the existing domain $dsrmPassword = Read-Host -Prompt "Enter DSRM password" -AsSecureString Install-ADDSDomainController ` -DomainName "yourdomain.local" ` -InstallDns:$true ` -Credential (Get-Credential) ` -SafeModeAdministratorPassword $dsrmPassword ` -DatabasePath "C:\Windows\NTDS" ` -SysvolPath "C:\Windows\SYSVOL" ` -LogPath "C:\Windows\NTDS" ` -NoGlobalCatalog:$false ` -SiteName "Default-First-Site-Name" ` -Force:$true ``` This runs `adprep /forestprep` and `adprep /domainprep` automatically as part of the promotion (you need to be a member of Enterprise Admins, Schema Admins, and Domain Admins for this to succeed). The server reboots when done. **Save the DSRM password somewhere safe.** Directory Services Restore Mode (DSRM) is your recovery path if AD DS gets corrupted. Losing this password is operationally painful. ### Verify replication After reboot, sign in and confirm the new DC is replicating with the old one: ```powershell # Check replication health between old and new DCs repadmin /replsummary repadmin /showrepl # Should show "Last attempt @ ... succeeded" for both directions ``` Both DCs should show successful replication in both directions. If you see errors, wait 15 minutes (initial replication can take time for large domains), then re-check. If errors persist, troubleshoot before moving on. Skipping this step has caused some of the worst AD DS disasters in the field. ### Verify the new DC sees all expected objects ```powershell # Count users and computers; should match what the old DC reports Get-ADUser -Filter * | Measure-Object | Select-Object Count Get-ADComputer -Filter * | Measure-Object | Select-Object Count Get-ADGroup -Filter * | Measure-Object | Select-Object Count ``` Numbers should match between old and new DC. Run the same commands on the old DC and compare. ## Phase 4: Transfer FSMO roles to the new DC FSMO (Flexible Single Master Operations) roles are five specific responsibilities that only one DC holds at a time. In a single-DC environment, all five live on the old Server 2016. We transfer them to the new Server 2025 DC. ### Transfer all five roles ```powershell # Transfer all FSMO roles to the new DC in one command Move-ADDirectoryServerOperationMasterRole ` -Identity "NEW-DC-01" ` -OperationMasterRole SchemaMaster, DomainNamingMaster, PDCEmulator, RIDMaster, InfrastructureMaster ``` Confirm the transfer worked: ```powershell netdom query fsmo ``` All five roles should now show the new server's name. ### Make the new DC the Global Catalog ```powershell # Verify the new DC is a Global Catalog (should be by default from Install-ADDSDomainController) Get-ADDomainController -Identity "NEW-DC-01" | Select-Object Name, IsGlobalCatalog ``` If `IsGlobalCatalog` is False, set it to True via Active Directory Sites and Services console (NTDS Settings on the new DC, properties, check "Global Catalog"). ### Update DNS clients to point at the new DC Now's the time to repoint every domain-joined machine's DNS to the new DC. If you use **DHCP**, update the DNS option on the DHCP scope to the new DC's IP and reduce the lease duration temporarily so clients pick up the new DNS quickly. For statically configured devices (printers, servers, IoT), update them one at a time. For the new DC itself: ```powershell # Point the new DC at itself for DNS Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses "127.0.0.1" ``` ## Phase 5: Migrate file shares with Storage Migration Service Microsoft's official tool for file server migration is **Storage Migration Service (SMS)**, run through **Windows Admin Center**. It's free, supported by Microsoft, and preserves share permissions, NTFS ACLs, local users and groups, and (optionally) the server's identity (so existing UNC paths keep working). **Important caveat from Microsoft Learn:** "The Storage Migration Service doesn't migrate domain controllers." That's why we did AD DS first as a separate procedure. SMS is for file server data only. ### Install Windows Admin Center and SMS Install **Windows Admin Center** on a management workstation (your daily-driver Win11 machine) or on the new Server 2025 itself. WAC is a free download from Microsoft. In WAC, install the **Storage Migration Service** extension if it's not already there. Install the **SMS proxy** on the destination Server 2025: ```powershell Install-WindowsFeature -Name SMS-Proxy ``` The proxy dramatically speeds up the transfer. ### Run the migration job In Windows Admin Center > Storage Migration Service: 1. **New job** > name it (e.g., "FileShares-2016-to-2025") > **Windows servers and clusters** 2. **Enter credentials** for the source Server 2016 (admin creds) 3. **Add source server** by hostname; SMS scans it and lists volumes, shares, local users, local groups 4. **Select what to migrate**: pick the volumes and shares you want 5. **Choose destination**: the new Server 2025 VM 6. **Map volumes**: tell SMS which source volume maps to which destination volume 7. **Transfer data**: SMS copies files, preserving NTFS ACLs and share permissions. Can run for hours depending on data size; SMB transfer is the bottleneck. 8. **Cut over** (optional): if you want the new server to take on the old server's hostname and IP so existing UNC paths keep working, run the cutover step. This step puts the source into maintenance mode and migrates the identity. SMS produces detailed reports at each step. Review them. Any files that failed to transfer get listed individually so you can investigate (typically these are files in use during the transfer; they get caught on the second pass). ### Verify file shares post-migration On the new server: ```powershell # List shares - should match the old server's share list Get-SmbShare | Format-Table Name, Path, Description -AutoSize # Verify permissions Get-SmbShare | ForEach-Object { Write-Host "`n=== $($_.Name) ===" -ForegroundColor Cyan Get-SmbShareAccess -Name $_.Name | Format-Table } ``` Compare against the inventory you captured in Phase 1. Any deltas get reconciled before the next phase. ## Phase 6: Migrate SQL Server (if present) If your Server 2016 hosts SQL Server (2016, 2017, 2019, or 2022), you migrate to **SQL Server 2025** on the new Windows Server 2025 alongside everything else. We covered the full SQL Server 2025 install procedure in our [SQL Server 2025 installation guide](/learn/install-sql-server-2025-windows-server-vps). ### High-level SQL migration steps 1. **Install SQL Server 2025** on the new Windows Server 2025 (follow the install guide above) 2. **Back up all databases** on the old SQL Server (`BACKUP DATABASE ... TO DISK = ...`) including system databases (master, msdb, model) 3. **Copy backups** to the new server (via SMB to a temporary network share) 4. **Restore user databases** on the new SQL Server (`RESTORE DATABASE ... FROM DISK = ... WITH MOVE`) 5. **Migrate logins** using the `sp_help_revlogin` procedure to preserve SIDs (otherwise users lose access) 6. **Migrate SQL Server Agent jobs** by scripting them out from the old server and applying to the new 7. **Update application connection strings** to point at the new server 8. **Validate** with a full app smoke test before decommissioning For full step-by-step SQL Server migration, see Microsoft's [Upgrade SQL Server documentation](https://learn.microsoft.com/en-us/sql/database-engine/install-windows/upgrade-sql-server). For hardening the new SQL Server, see our [SQL Server 2025 security hardening guide](/learn/sql-server-2025-security-hardening-vps). ## Phase 7: Migrate line-of-business apps This phase is the most variable because every app is different. The general pattern: 1. **Confirm Server 2025 compatibility** with the vendor (their official compat matrix, not a forum post). If the app is not certified for Server 2025, escalate to the vendor before proceeding. 2. **Install the latest version of the app** on the new Server 2025. Most vendors update for new OS releases; running the latest version often resolves compatibility issues anyway. 3. **Migrate the app's data**. If it's SQL-backed, you handled the database in Phase 6. If it's flat-file (typically `C:\ProgramData\Vendor\...` or `C:\Vendor\Data\...`), copy via SMB after a service stop. 4. **Migrate license keys**. Many apps are licensed to hostname or hardware ID. Contact the vendor to reissue or transfer the license to the new server. 5. **Update client config** to point at the new server (DNS records, app-specific config files, sometimes per-workstation client config). 6. **Smoke test** with a representative user before broad rollout. For apps like QuickBooks Desktop, Sage, ERP packages, document management systems, and similar, each has its own migration procedure documented by the vendor. Get the vendor involved early; their support can save you a week of guesswork. ![Cutover weekend checklist for a Windows Server 2016 to Windows Server 2025 migration showing Friday preparation, Saturday migration and validation, and Sunday cutover and monitoring tasks.](https://raff-images.s3.raffusercloud.com/Adsiz_tasarim_79d119fa8a.jpg) ## Phase 8: Demote the old domain controller After several days of running with both DCs side by side, all clients pointing at the new DC, and everything working, it's time to retire Server 2016. **Do not skip the verification period.** Microsoft's recommended approach is to run side by side for 1-2 weeks before demoting. This catches any user, app, or printer still pointing at the old DC for DNS or LDAP. ### Confirm nothing depends on the old DC ```powershell # On the old DC, watch for incoming auth requests Get-WinEvent -LogName "Security" -MaxEvents 100 | Where-Object { $_.Id -eq 4624 } | Format-Table TimeCreated, @{N='User';E={$_.Properties[5].Value}}, @{N='Source';E={$_.Properties[18].Value}} ``` If you see fresh successful logons, something is still using the old DC. Trace those sources, fix them, then re-check. ### Demote the old DC On the old Server 2016: ```powershell # Demote AD DS Uninstall-ADDSDomainController -RemoveApplicationPartitions -Force ``` You'll be prompted for a new local Administrator password (since the server changes from DC to standalone). Server reboots. After reboot, the old Server 2016 is a regular domain member. You can leave it powered on for another week as a sanity-check backstop, or shut it down. ### Remove the old DC from AD Even after demotion, the old DC's computer object lingers in AD. Clean it up: ```powershell # On the new DC, remove the old DC's metadata Remove-ADComputer -Identity "OLD-DC-01" -Confirm:$false ``` Also clean up in **Active Directory Sites and Services**: navigate to `Sites > Default-First-Site-Name > Servers`, right-click the old DC's server object, and delete. ## Phase 9: Raise functional levels (optional, irreversible) Once all DCs in your environment are Server 2025, you can raise the **domain and forest functional level** to Windows Server 2025. This unlocks the new 32K database page feature and some AD DS performance improvements. **Functional level raises are irreversible.** Don't do this until you're sure no future server in your environment will run Server 2016, 2019, or 2022. The only reason to delay raising is if you anticipate adding another older DC, which for most small businesses is a non-issue. ```powershell # Raise the domain functional level Set-ADDomainMode -Identity yourdomain.local -DomainMode Windows2025Domain # Raise the forest functional level Set-ADForestMode -Identity yourdomain.local -ForestMode Windows2025Forest # Verify Get-ADDomain | Format-List Name, DomainMode Get-ADForest | Format-List Name, ForestMode ``` If the commands fail, check that **all** DCs (you should only have one now) are running Server 2025 and that the previous functional levels are at least Windows Server 2016. ## Phase 10: Decommission the old server Once you've validated everything works on the new server for 2-4 weeks, decommission the old Server 2016. 1. **Final backup** of the old server image (in case something surfaces later) 2. **Power off** and leave the VM in stopped state for another 30 days as a final sanity-check backstop 3. **Delete the old server** from wherever it lives (on-premises Hyper-V/VMware/Proxmox, AWS EC2 console, Azure portal, GCP console, or your colo control panel) 4. **Update internal documentation**: server inventory, network diagrams, DR runbooks, asset register ## Common errors ### "Active Directory on this domain controller does not contain Windows Server 2025 ADPREP /FORESTPREP updates" You'll see this if the auto-adprep step somehow didn't run (rare with side-by-side, common with in-place upgrades). Fix: manually run `adprep /forestprep` from the Server 2025 install media on the **schema master**. The adprep tool lives in `support\adprep\` on the ISO. Run as administrator. Confirm schema version moves from 87 to 91. ### "Verification of replica failed" when adding the new DC Usually means functional levels don't meet the Server 2025 minimum. Check both domain and forest functional levels are at least Windows Server 2016. If they're below, you need to raise them first, which requires all existing DCs to be Server 2016+. ### Replication errors between old and new DCs The most common cause is firewall rules. AD DS replication needs **TCP/UDP 53 (DNS), TCP/UDP 88 (Kerberos), TCP/UDP 389 (LDAP), TCP 636 (LDAPS), TCP 3268-3269 (Global Catalog), TCP 135 (RPC endpoint mapper), and dynamic RPC ports** open between DCs. Since your old Server 2016 is in a different network (on-premises, colo, or another cloud) than the new Server 2025 on Raff, these ports need to be explicitly allowed across the site-to-site VPN, your existing firewall, and any cloud security groups in between. ### Storage Migration Service "access denied" on source server The SMS service account needs **Local Administrator** on the source server. Even if you provide Domain Admin credentials, they need to translate to local admin on the source machine. Add the credential's user or group to the local Administrators group on the source server before running the job. ### SQL Server logins broken after database migration Logins don't move automatically with `BACKUP/RESTORE`. Use `sp_help_revlogin` on the source server to script out logins with their SIDs preserved, then run the script on the destination. Without preserved SIDs, users get "orphan logins" with no permissions, even though the login name exists. ### Old shares still accessible via old hostname after demote If you used SMS cutover to transfer the old server's identity, the old hostname and IP now belong to the new server, and SMB clients route there transparently. If you didn't use cutover, the old hostname dies with the old server, and you need to update client UNC paths (or add a DNS CNAME pointing the old name at the new server's IP). ## Tested on Raff > **Sourced from:** Microsoft Learn (Windows Server documentation, June 2025–May 2026), with cross-references to Microsoft MVP technical blogs (4sysops, PeteNetLive, ALI TAJRAN), the official Microsoft Lifecycle Policy, and the Microsoft Windows Server end-of-support blog announcement (February 2026). The free migration offer in this guide is operationally backed by the Raff Technologies platform: Windows Server 2025 VMs are provisioned daily on AMD EPYC dedicated hardware in the us-east region; the Server 2025 deployment, AD DS install, role promotion, FSMO transfer, Storage Migration Service execution, SQL Server install, and end-to-end smoke tests described above have all been performed individually in Raff's lab as part of building this article series. No single VM was used to perform the entire 10-phase migration end-to-end, because doing so credibly requires a representative pre-migration environment (real domain, real users, real data, real apps). For your specific environment, that representative reality is your production. This is why the migration offer exists: we do this work as a service on top of the platform. ## What's next - [How to Set Up SMB over QUIC on Windows Server 2025 with a Let's Encrypt Certificate (No VPN Needed)](/learn/smb-over-quic-windows-server-vps): once you're on Server 2025, replace your file-server VPN with QUIC - [Install SQL Server 2025 on a Windows Server VPS](/learn/install-sql-server-2025-windows-server-vps): the install procedure referenced in Phase 6 - [SQL Server 2025 security hardening on a Windows Server VPS](/learn/sql-server-2025-security-hardening-vps): hardening to apply post-migration - [Host ASP.NET Core 10 on IIS on a Windows Server VPS](/learn/iis-aspnet-core-windows-server-vps): if you also run web apps on the migrated server ## Sources - Microsoft Windows Server Blog: [Planning ahead for Windows Server 2016 end of support](https://www.microsoft.com/en-us/windows-server/blog/2026/02/25/planning-ahead-for-windows-server-2016-end-of-support/) (February 25, 2026) - Microsoft Support: [Support for Windows Server 2016 will end in January 2027](https://support.microsoft.com/en-us/topic/support-for-windows-server-2016-will-end-in-january-2027-ffd9e92c-5027-4201-b6e1-ed46f8486b43) - Microsoft Learn: [Upgrade domain controllers to a newer version of Windows Server](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/deploy/upgrade-domain-controllers) - Microsoft Learn: [Raise the Active Directory domain and forest functional levels](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/raise-domain-forest-functional-levels) - Microsoft Learn: [Storage Migration Service overview](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/overview) - Microsoft Learn: [Migrate a file server by using Storage Migration Service](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/migrate-data) - 4sysops: [Upgrade domain controller and migrate Active Directory to Windows Server 2025](https://4sysops.com/archives/upgrade-domain-controller-and-migrate-active-directory-to-windows-server-2025/) (Leos Marek, May 2025) - Date last verified: 2026-05-23 --- *Microsoft, Windows Server, Windows 11, Active Directory, SQL Server, Hyper-V, Windows Admin Center, and Storage Migration Service are trademarks of Microsoft Corporation. Raff Technologies is an independent infrastructure provider and is not affiliated with, sponsored by, or endorsed by Microsoft Corporation.* --- ### Install SQL Server 2025 on a Windows Server VPS (Standard Developer, 2026 Guide) URL: https://rafftechnologies.com/windows-server/install-sql-server-2025-windows-server-vps Description: End-to-end install guide for SQL Server 2025 Standard Developer on a Windows Server VPS. Covers winget setup, Custom wizard, tempdb, firewall, and post-install CU application. ## In short Install SQL Server 2025 on a Windows Server VPS by choosing the right edition, running the full Custom setup wizard, configuring Mixed Mode only when your app needs SQL logins, setting clean data/log/backup paths, tuning TempDB, capping max server memory, applying the latest cumulative update, and opening TCP 1433 only to trusted IPs or private networks. Use Standard Developer for development and testing; use paid Standard or Enterprise for production. ## Which edition should you install? SQL Server 2025 introduced a clearer edition model. The most important decision is whether the server is for development, staging, testing, or production. | Edition | Production use? | Main limits | Best for | |---|---:|---|---| | **Standard Developer** | No | Same feature set as Standard, licensed for development and test only | Building and validating apps that will later run on paid Standard | | **Enterprise Developer** | No | Same feature set as Enterprise, licensed for development and test only | Testing Enterprise-only features without production use | | **Express** | Yes | 1 socket / 4 cores, 1,410 MB buffer pool, 50 GB per relational database | Small production databases, lightweight apps, learning | | **Standard** | Yes | 32 cores, 256 GB buffer pool | Most SMB and mid-market production workloads | | **Enterprise** | Yes | Operating system maximums for many scale limits | Large databases, advanced HA/DR, heavy analytics, Enterprise-only features | | **Evaluation** | Temporary | 180-day evaluation | Testing Enterprise features before licensing | **This guide uses Standard Developer** because it is free and practical for development, staging, and install validation. The installation flow for paid Standard is almost identical; the difference is the product key and licensing step. Do not run Developer edition in production. Developer editions are licensed for development and testing only. ![SQL Server 2025 edition decision flow showing when to choose Standard Developer, Express, Standard, Enterprise, or Evaluation for Windows VPS deployments.](https://raff-images.s3.raffusercloud.com/sql_server_2025_edition_decision_flow_png_e05d76f6bd.png) ## What you will build This guide installs a clean SQL Server 2025 instance on a Windows Server VPS. The target setup: ```text Windows Server VPS ↓ SQL Server 2025 ├── Database Engine ├── SQL Server Agent ├── TempDB ├── Data files ├── Log files ├── Backups └── Firewall / private access ``` For a small workload, the app and SQL Server can run on one VPS. As the workload grows, the cleaner production path is to split the application and database onto separate VMs connected over a private network. ![SQL Server 2025 architecture on a Windows Server VPS showing Database Engine, SQL Server Agent, TempDB, data files, log files, backups, firewall rules, and optional private app server access.](https://raff-images.s3.raffusercloud.com/sql_server_2025_windows_vps_architecture_png_229b36c3f3.png) ## What you'll need Before starting, prepare: - a Raff Windows Server VPS or similar Windows Server VPS; - Windows Server 2022 or Windows Server 2025; - local Administrator access; - no pending Windows reboot; - SQL Server 2025 installation media; - SQL Server Management Studio on your workstation or on the server; - a password manager for the `sa` password if you choose Mixed Mode; - a backup plan before production data is added. Recommended starting specs depend on the workload. | Workload | Suggested starting point | |---|---| | Learning or test install | 2–4 vCPU / 4–8 GB RAM | | Small app or staging database | 4 vCPU / 8–16 GB RAM | | Small production database | 4–8 vCPU / 16–32 GB RAM | | SQL-heavy production workload | 8+ vCPU / 32+ GB RAM | | ERP, reporting, or multi-user business workload | Size after reviewing database size, users, reports, and backup window | Do not size SQL Server only by vCPU count. RAM, NVMe storage, database behavior, backup windows, and application concurrency matter just as much. ## Quick context: what changed in SQL Server 2025 Before you install, know the practical SQL Server 2025 changes that affect a Windows VPS deployment: - SQL Server 2025 is version **17.x**. - SQL Server 2025 reached general availability as build **17.0.1000.7** on November 18, 2025. - Standard edition now supports up to **32 cores** and **256 GB buffer pool memory**. - Express edition now supports up to **50 GB** per relational database. - Web edition is discontinued. - Express with Advanced Services is discontinued because base Express now includes those features. - Standard Developer and Enterprise Developer are separate free developer editions. - Resource Governor is available in Standard and Standard Developer. - SQL Server 2025 adds AI-related features such as vector data type, vector functions, external AI model objects, and vector search. - Some SQL Server 2025 features remain preview-only and should not be treated as production-ready until Microsoft marks them generally available. The big takeaway: > SQL Server 2025 is a strong new baseline for new deployments, but production installs should still use only the features the workload actually needs. If you are bringing forward a SQL Server 2019 or 2022 workload that depends on removed or changed features, validate the workload before upgrading. ## Step 1 — Prepare the Windows Server VPS Connect to the Windows Server VPS over RDP as Administrator. Before running setup: 1. Install pending Windows updates. 2. Reboot the server. 3. Confirm you can reconnect over RDP. 4. Confirm the system drive has enough free space. 5. Create a clean SQL folder structure. Run PowerShell as Administrator: ```powershell New-Item -ItemType Directory -Path "C:\SQL\Data" -Force New-Item -ItemType Directory -Path "C:\SQL\Logs" -Force New-Item -ItemType Directory -Path "C:\SQL\Backups" -Force New-Item -ItemType Directory -Path "C:\SQL\TempDB" -Force ``` This keeps user databases, transaction logs, backups, and TempDB easier to manage than leaving everything under `C:\Program Files\Microsoft SQL Server\`. If you later use separate disks or volumes, keep the same idea with dedicated paths such as `D:\SQL\Data`, `L:\SQL\Logs`, and `T:\SQL\TempDB`. ## Step 2 — Get SQL Server 2025 media onto the server You have three practical options. ### Option 1 — Use winget to get the installer media `winget` is built into Windows Server 2025 and can locate SQL Server packages. ```powershell # See available SQL Server packages winget search --id "Microsoft.SQLServer" # Install SQL Server 2025 Developer media winget install --id Microsoft.SQLServer.2025.Developer ``` Important: if `winget` launches a one-click Basic installation, do not use that as the final production-style install. Basic setup can skip important choices such as TempDB, data paths, authentication, SQL Server Agent startup, and feature selection. For this guide, use the full **Custom** setup wizard from the extracted media. If the media is extracted to `C:\SQL2025\StdDev_ENU\`, launch: ```powershell Start-Process -FilePath "C:\SQL2025\StdDev_ENU\setup.exe" -Verb RunAs ``` ### Option 2 — Download media from Microsoft Download SQL Server 2025 from Microsoft’s SQL Server download page and choose **Download Media**. Use Download Media instead of Basic install so you can run the full setup wizard and control: - edition; - feature selection; - authentication; - service startup; - data directories; - TempDB; - MaxDOP; - memory; - firewall planning. ### Option 3 — Use Evaluation Center Use Evaluation Edition when you need to test Enterprise features for a limited time. This is useful for: - Enterprise feature testing; - upgrade validation; - proof-of-concept work; - temporary HA/DR lab work. Do not treat Evaluation Edition as a permanent production install. Do not run SQL Server setup from an ISO mounted through your local RDP client drive. Put the media on the Windows Server VPS itself or on a real network share reachable by the server. ## Step 3 — Run the install wizard From PowerShell on the Windows Server VPS, launch setup as Administrator: ```powershell Start-Process -FilePath "C:\SQL2025\StdDev_ENU\setup.exe" -Verb RunAs ``` ![SQL Server 2025 Installation Center showing the Installation tab with New SQL Server standalone installation option highlighted](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_installation_tab_2026_04_729d6e9fd8.png) The SQL Server Installation Center opens. Click: ```text Installation → New SQL Server standalone installation or add features to an existing installation ``` SQL Server Setup then walks through the installation screens. Most are straightforward. The sections below cover the decisions that matter on a Windows VPS. ### Edition ![SQL Server 2025 Setup Edition screen with Standard Developer selected from the free edition dropdown](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_edition_standard_developer_2026_04_ab91f225b9.png) For this guide, select: ```text Specify a free edition → Standard Developer ``` For production, choose: ```text Enter the product key → Paid Standard or Enterprise key ``` For a temporary Enterprise evaluation, choose Evaluation. Click **Next**. ### License terms, setup rules, Microsoft Update, and product updates Accept the license terms. If Microsoft Update is offered, enable it so Windows can check for Microsoft product updates. If the setup rule check reports a pending restart, cancel setup, reboot the server, reconnect, and run setup again. Do not ignore pending restart warnings. SQL Server setup is sensitive to restarts pending from Windows Update, uninstallers, drivers, and previous software installs. ### Install Rules — the Windows Firewall warning is expected ![SQL Server 2025 Setup Install Rules showing four passed checks and one Windows Firewall warning, expected and safe to proceed](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_install_rules_firewall_warning_2026_04_47b9e0cc55.png) A Windows Firewall warning is normal. Do not disable Windows Firewall. Continue the install and configure firewall rules intentionally after setup. Correct model: ```text Install SQL Server. Decide who needs remote access. Open only the required port. Restrict by source IP or private network. ``` ### Azure Extension for SQL Server — skip unless you need Azure Arc ![SQL Server 2025 Setup Azure Extension screen with the checkbox unticked, skipping Azure Arc registration for a self-hosted Raff Server](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_azure_extension_unticked_2026_04_d8ee9dca65.png) SQL Server setup may offer Azure Extension or Azure Arc registration. For a self-managed Windows VPS, leave this unchecked unless you specifically need: - Azure Arc management; - pay-as-you-go SQL billing through Azure; - Microsoft Entra integration through Arc; - Azure-connected SQL management features; - Azure-managed backup or compliance tooling. Most standalone Raff Windows VPS SQL Server installs do not need Azure Arc during initial setup. You can register later if a real requirement appears. ### Feature Selection — install only what you need ![SQL Server 2025 Feature Selection with Database Engine Services, SQL Server Replication, and Full-Text Search ticked — recommended minimum](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_feature_selection_recommended_2026_04_3ede160712.png) For most Windows VPS deployments, start with a small feature set. Recommended baseline: - **Database Engine Services** — required for SQL Server databases; - **SQL Server Replication** — useful if the workload may need replication later; - **Full-Text and Semantic Extractions for Search** — useful for many line-of-business applications. Leave optional features unchecked unless you know you need them: - AI Services and Language Extensions; - PolyBase Query Service for External Data; - Analysis Services; - Integration Services; - Scale Out Worker. A smaller install is easier to secure, patch, monitor, and troubleshoot. Add optional components later only when the requirement becomes real. ### Instance Configuration — use the default instance ![SQL Server 2025 Setup Instance Configuration with Default instance selected and MSSQLSERVER as the instance ID](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_instance_configuration_default_2026_04_cb0ed7c26a.png) Select: ```text Default instance: MSSQLSERVER ``` A default instance is easier for applications and administrators because connections can use: ```text server-name-or-ip ``` Use a named instance only when: - multiple SQL Server instances run on one VM; - you need side-by-side SQL versions; - a vendor app requires a specific instance name; - your architecture intentionally separates tenants or apps by instance. For a clean single-purpose VPS, the default instance is usually better. ### Server Configuration — change SQL Server Agent and enable instant file initialization ![SQL Server 2025 Server Configuration with SQL Server Agent startup type set to Automatic and Volume Maintenance Tasks privilege ticked](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_server_configuration_2026_04_18a913c42e.png) Make two changes: 1. Set **SQL Server Agent** startup type to **Automatic**. 2. Tick **Grant Perform Volume Maintenance Tasks privilege to SQL Server Database Engine Service**. SQL Server Agent should be automatic if you will use scheduled jobs, maintenance plans, alerts, database backups, or recurring tasks. The Perform Volume Maintenance Tasks privilege enables instant file initialization for data files. This can make data file creation and growth much faster. Leave service accounts at the defaults unless your environment requires domain service accounts. Leave SQL Server Browser disabled for a default instance. On the Collation tab, keep the default unless your app vendor requires a specific collation. Changing collation later can be painful. ### Database Engine Configuration — authentication ![SQL Server 2025 Database Engine Configuration with Mixed Mode authentication selected and Administrator added as SQL Server admin](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_dbengine_auth_mixed_mode_2026_04_fc140b5592.png) For a standalone, non-domain-joined Windows VPS, Mixed Mode is often the practical choice. ```text Mixed Mode = SQL Server authentication + Windows authentication ``` Mixed Mode is common when: - the server is not joined to Active Directory; - applications need SQL logins; - connection strings use SQL username and password; - users or apps connect from outside a Windows domain. If you use Mixed Mode: - set a long, strong `sa` password; - store it in a password manager immediately; - click **Add Current User** so the current Windows Administrator becomes a SQL Server admin; - create dedicated app logins later; - do not use `sa` as the normal application login. For domain-joined environments, Windows Authentication may be enough. ### Data Directories tab ![SQL Server 2025 Data Directories tab with user databases, logs, and backups separated into clean C:\SQL folder structure](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_dbengine_data_directories_2026_04_ba8c6fbd7e.png) Use the folder structure created earlier. | Field | Change to | |---|---| | User database directory | `C:\SQL\Data` | | User database log directory | `C:\SQL\Logs` | | Backup directory | `C:\SQL\Backups` | Leave system database paths at the default unless you have a specific design reason to move them. On a single-volume VPS, this structure does not create separate physical storage. The benefit is operational clarity: data files, log files, and backups are no longer mixed into the SQL Server program directory. ### TempDB tab — the most important performance screen ![SQL Server 2025 TempDB tab configured with 4 data files at 512 MB each, 64 MB autogrowth, and C:\SQL\TempDB path](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_dbengine_tempdb_4files_2026_04_a069f32e34.png) TempDB matters for sorts, temp tables, version store activity, reports, and many application workloads. A practical starting point: | VM size | TempDB data files | Initial size per file | Growth | |---|---:|---:|---:| | 2 vCPU / 4 GB RAM | 2 | 256 MB | 64 MB | | 4 vCPU / 8 GB RAM | 4 | 512 MB | 64 MB | | 8 vCPU / 16 GB RAM | 8 | 1024 MB | 128 MB | | 16 vCPU / 32 GB RAM | 8 | 2048 MB | 256 MB | Use this rule for most small and mid-sized VPS installs: ```text TempDB data files = number of vCPUs, capped at 8. ``` Keep all TempDB data files equal size and use fixed MB growth instead of percentage growth. Recommended path: ```text C:\SQL\TempDB ``` Do not leave TempDB ignored. Poor TempDB defaults can become painful when multiple users, reports, temp tables, or scheduled jobs run at the same time. ### MaxDOP tab — use the installer recommendation as the starting point ![SQL Server 2025 MaxDOP tab showing auto-detected 4 logical CPU cores and MaxDOP set to 4 for the Raff Production plan](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_dbengine_maxdop_4_2026_04_18cc193292.png) The SQL Server setup wizard usually proposes a good starting MaxDOP based on logical CPU count. Practical starting values: | vCPU | MaxDOP starting point | |---:|---:| | 2 | 2 | | 4 | 4 | | 8 | 8 | | 16+ | 8 | Avoid setting MaxDOP to 0 on small VMs unless you have tested the workload. A MaxDOP of 0 allows a query to use all available schedulers, which can hurt concurrency on smaller VPS plans. ### Memory and FILESTREAM tabs Leave the Memory tab at setup defaults for now. After installation, set max server memory with T-SQL so you can choose a value based on the VM size and what else runs on the server. Leave FILESTREAM disabled unless your application specifically requires FILESTREAM. ### Ready to Install ![SQL Server 2025 Ready to Install summary showing Standard Developer edition with Database Engine, Replication, Full-Text Search and default instance](https://raff-images.s3.raffusercloud.com/large_raff_mssql2025_ready_to_install_summary_2026_04_5d17286cb2.png) Before clicking Install, review: - edition; - selected features; - default instance; - SQL Server Agent startup type; - data directory; - log directory; - backup directory; - TempDB file count; - TempDB file size; - TempDB growth; - MaxDOP; - SQL admins; - authentication mode. SQL Setup also writes a configuration file. Save the path if you want to reproduce the same installation later. Do not publish the configuration file publicly if it contains sensitive paths, usernames, or product-key-related information. Click **Install**. Expect setup to take 15–30 minutes depending on VM size and selected features. ### Complete When setup finishes, every selected feature should show **Succeeded**. If a feature fails: 1. Open the setup log folder shown on the Complete screen. 2. Review the summary log. 3. Fix the root cause. 4. Reboot if required. 5. Re-run setup only after the failure is understood. Do not ignore partial installation failures. ## Step 4 — Cap SQL Server memory SQL Server will try to use available memory aggressively. That is normal, but a Windows Server VPS also needs RAM for: - Windows Server; - RDP sessions; - antivirus or EDR; - backup software; - monitoring agents; - application services; - file cache; - SSMS if installed locally. Set max server memory after installation. Example for an 8 GB RAM VPS: ```sql EXEC sys.sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sys.sp_configure 'max server memory (MB)', 6144; RECONFIGURE; EXEC sys.sp_configure 'max server memory (MB)'; ``` Example starting points: | VPS RAM | Suggested SQL max server memory | |---:|---:| | 4 GB | 2048–2560 MB | | 8 GB | 5120–6144 MB | | 16 GB | 12288–13312 MB | | 32 GB | 24576–28672 MB | | 64 GB | 53248–57344 MB | These are starting points. Tune based on actual workload, monitoring, and what else runs on the server. Do not leave max server memory at the effective unlimited default on production-style installs. ## Step 5 — Apply the latest SQL Server cumulative update After the base install, apply the latest SQL Server 2025 cumulative update available from Microsoft. Use this rule: ```text Install the latest available SQL Server 2025 cumulative update before production use. ``` Do not hardcode only one CU number in the article unless you will keep it updated every time Microsoft ships a newer CU. After installing the update, reboot if prompted. Verify the build: ```sql SELECT @@VERSION; ``` Also check edition and product level: ```sql SELECT SERVERPROPERTY('ProductVersion') AS ProductVersion, SERVERPROPERTY('ProductLevel') AS ProductLevel, SERVERPROPERTY('ProductUpdateLevel') AS ProductUpdateLevel, SERVERPROPERTY('Edition') AS Edition; ``` Record the version in your change log. ## Step 6 — Install SQL Server Management Studio SQL Server Management Studio is the management GUI. Best practice: - install SSMS on your workstation if you will manage the server remotely; - install SSMS on the server only if local GUI administration is useful; - keep SSMS updated separately from the SQL Server engine. After installing SSMS, connect to: ```text localhost ``` when working on the server, or: ```text SERVER_PUBLIC_IP_OR_PRIVATE_IP ``` from a trusted remote machine. For Mixed Mode testing, use a SQL login. Do not use the `sa` login as the normal application login. ## Step 7 — Configure TCP/IP only if remote SQL access is needed If applications connect only from the same VPS, you may not need to expose SQL Server over the network. If remote applications or admin workstations need SQL access, enable TCP/IP carefully. Open SQL Server Configuration Manager: ```text SQL Server Network Configuration → Protocols for MSSQLSERVER → TCP/IP → Enabled ``` Set a static TCP port, usually: ```text 1433 ``` Restart the SQL Server service after changing network protocol settings. For a named instance, choose a deliberate port and document it. Avoid relying on dynamic ports for production application connections unless your environment is designed around that. ## Step 8 — Open the Windows Firewall only to trusted sources By default, SQL Server may listen on TCP 1433, but Windows Firewall can still block inbound remote access. Do not open SQL Server to the entire internet. If remote SQL access is required, restrict it by source IP or private network. Example PowerShell rule allowing one trusted office IP: ```powershell New-NetFirewallRule ` -DisplayName "SQL Server 2025 TCP 1433 - Office IP" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 1433 ` -RemoteAddress "203.0.113.10" ` -Action Allow ``` Replace `203.0.113.10` with your real office IP, VPN gateway IP, private network range, or trusted admin IP. Avoid this rule: ```powershell New-NetFirewallRule -DisplayName "SQL Server" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 1433 ` -Action Allow ``` That opens SQL Server to any source. Better access patterns: - same-server connections; - private networking between app and database VMs; - VPN; - IP allowlist; - RD Gateway or admin jump host; - no public SQL port when avoidable. Never leave TCP 1433 open to `0.0.0.0/0`. ## Step 9 — Create a test database After installation and update, create a small test database. ```sql CREATE DATABASE RaffSqlTest; GO USE RaffSqlTest; GO CREATE TABLE dbo.HealthCheck ( Id int IDENTITY(1,1) PRIMARY KEY, CreatedAt datetime2 NOT NULL DEFAULT sysdatetime(), Message nvarchar(200) NOT NULL ); GO INSERT INTO dbo.HealthCheck (Message) VALUES (N'SQL Server 2025 is working.'); GO SELECT * FROM dbo.HealthCheck; GO ``` Verify the database files were created in the expected path. ```sql SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('RaffSqlTest'); ``` You should see data and log files under the configured SQL folders. ## Step 10 — Create a safer application login Do not give applications the `sa` password. Create a dedicated login and database user. Example: ```sql CREATE LOGIN app_user WITH PASSWORD = 'Use-A-Strong-Unique-Password-Here!'; GO USE RaffSqlTest; GO CREATE USER app_user FOR LOGIN app_user; GO ALTER ROLE db_datareader ADD MEMBER app_user; ALTER ROLE db_datawriter ADD MEMBER app_user; GO ``` For real production applications, grant only the permissions the app needs. Do not make application logins `sysadmin`. ## Step 11 — Set a first backup Before production use, take a test backup. ```sql BACKUP DATABASE RaffSqlTest TO DISK = 'C:\SQL\Backups\RaffSqlTest_full.bak' WITH INIT, COMPRESSION, CHECKSUM, STATS = 10; GO ``` Verify the backup: ```sql RESTORE VERIFYONLY FROM DISK = 'C:\SQL\Backups\RaffSqlTest_full.bak' WITH CHECKSUM; GO ``` For production, plan: - full backups; - differential backups when useful; - transaction log backups if using full recovery model; - backup retention; - off-server storage; - restore testing; - monitoring failed jobs. A backup strategy is not complete until restore is tested. ## Step 12 — Verify the final install Run these checks before calling the installation complete. ### Quick smoke test From the Windows Server VPS: ```powershell Get-Service -Name MSSQLSERVER, SQLSERVERAGENT | Format-Table Name, Status, StartType ``` Then run: ```sql SELECT @@VERSION AS Version, SERVERPROPERTY('Edition') AS Edition, SERVERPROPERTY('ProductLevel') AS ProductLevel, SERVERPROPERTY('ProductUpdateLevel') AS ProductUpdateLevel; ``` Expected: - `MSSQLSERVER` running; - `SQLSERVERAGENT` running if you set it to Automatic; - edition matches what you installed; - product update level reflects your installed CU. ### Comprehensive post-install verification This PowerShell script checks the settings configured during installation. ```powershell Write-Host "`n=== 1. Services ===" -ForegroundColor Cyan Get-Service -Name MSSQLSERVER, SQLSERVERAGENT | Format-Table Name, Status, StartType -AutoSize Write-Host "=== 2. TCP 1433 Listening ===" -ForegroundColor Cyan $tcpTest = Test-NetConnection -ComputerName localhost -Port 1433 -InformationLevel Quiet Write-Host "TCP 1433 open on localhost: $tcpTest" Write-Host "`n=== 3. Firewall Rule ===" -ForegroundColor Cyan Get-NetFirewallRule -DisplayName "SQL Server*" -ErrorAction SilentlyContinue | Format-Table DisplayName, Enabled, Action, Direction -AutoSize Write-Host "=== 4. Version, Edition, Auth Mode ===" -ForegroundColor Cyan Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT SERVERPROPERTY('ProductVersion') AS Version, SERVERPROPERTY('Edition') AS Edition, SERVERPROPERTY('ProductLevel') AS PatchLevel, SERVERPROPERTY('ProductUpdateLevel') AS CULevel, CASE SERVERPROPERTY('IsIntegratedSecurityOnly') WHEN 0 THEN 'Mixed Mode' WHEN 1 THEN 'Windows Only' END AS AuthMode, SERVERPROPERTY('InstanceDefaultDataPath') AS DataPath, SERVERPROPERTY('InstanceDefaultLogPath') AS LogPath, SERVERPROPERTY('InstanceDefaultBackupPath') AS BackupPath "@ | Format-List Write-Host "=== 5. Instance Configuration ===" -ForegroundColor Cyan Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT name, value_in_use FROM sys.configurations WHERE name IN ( 'max server memory (MB)', 'min server memory (MB)', 'max degree of parallelism', 'cost threshold for parallelism' ) ORDER BY name "@ | Format-Table -AutoSize Write-Host "=== 6. TempDB Files ===" -ForegroundColor Cyan Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT name, physical_name, size * 8 / 1024 AS SizeMB, CASE is_percent_growth WHEN 0 THEN CAST(growth * 8 / 1024 AS VARCHAR) + ' MB' WHEN 1 THEN CAST(growth AS VARCHAR) + ' %' END AS Growth FROM tempdb.sys.database_files ORDER BY type, name "@ | Format-Table -AutoSize Write-Host "=== 7. Recent SQL Server error log entries ===" -ForegroundColor Cyan Invoke-Sqlcmd -ServerInstance "localhost" -Query @" EXEC sp_readerrorlog 0, 1 "@ -QueryTimeout 5 2>$null | Select-Object -Last 10 | Format-Table -AutoSize ``` ### What to check | Check | Expected value | |---|---| | Services | `MSSQLSERVER` and `SQLSERVERAGENT` running if Agent was set to Automatic | | TCP 1433 | Listening only if TCP/IP is enabled | | Firewall rule | Present only if remote SQL access is needed | | Edition | Matches Standard Developer, Standard, Enterprise, Express, or Evaluation | | AuthMode | Mixed Mode if selected | | DataPath | `C:\SQL\Data\` | | LogPath | `C:\SQL\Logs\` | | BackupPath | `C:\SQL\Backups\` | | max server memory | The value you configured | | MaxDOP | Installer recommendation or your tuned value | | TempDB files | Equal-sized data files with fixed MB growth | | Error log | No recent serious errors | If any value does not match, return to the section that controls that setting. Most settings can be corrected post-install, but it is better to detect mismatches before production data is added. ## Common mistakes ### 1. Pending Windows restart blocks setup The installer's Global Rules check can fail when Windows has a pending restart. Fix: reboot before starting SQL Server setup. ### 2. Accepting a Basic install as production-ready Basic install is fast, but it skips important decisions. Use Custom setup for serious installs so you can configure: - edition; - features; - authentication; - data paths; - TempDB; - MaxDOP; - SQL Server Agent; - firewall planning. ### 3. Running setup from an ISO mounted through the RDP client SQL Server setup should run from media on the server itself or from a proper network share. Do not drag the ISO over an RDP redirected drive and run setup from there. ### 4. Leaving TempDB at weak defaults TempDB should use multiple equal-sized data files and fixed MB growth. A good starting point is one TempDB data file per vCPU, capped at eight files for most small and mid-sized VPS installs. ### 5. Leaving max server memory effectively unlimited SQL Server can consume most available RAM. Cap max server memory so Windows and other services do not starve. ### 6. Setting MaxDOP to 0 on a small VM MaxDOP 0 allows a query to use all available schedulers. On small VMs, this can hurt concurrency under load. Use the installer recommendation as a starting point. ### 7. Losing the `sa` password If you choose Mixed Mode, store the `sa` password in a password manager immediately. Do not use `sa` as the application login. ### 8. Installing SQL Server on a domain controller Avoid installing SQL Server on a domain controller. Use a dedicated Windows Server VPS for SQL Server whenever possible. ### 9. Forgetting the firewall The install can succeed and local connections can work while remote access still times out. Only open SQL Server access if remote clients need it. ### 10. Opening TCP 1433 to the internet Restrict by IP, VPN, private network, or trusted admin access. Do not expose SQL Server publicly to the entire internet. ### 11. Installing unnecessary SQL features Every extra feature adds complexity. Install what the workload needs, then add optional features later if the requirement becomes real. ## When to step up to paid Standard or Enterprise Standard Developer is licensed for development, testing, and demonstration only. For production, choose the edition that matches the workload. Use **Express** when: - the database is small; - workload is light; - SQL Server Agent is not required; - 50 GB per database is enough; - resource limits are acceptable. Use **Standard** for most production workloads: - SMB applications; - ERP databases; - internal tools; - IIS / ASP.NET application databases; - moderate reporting; - line-of-business applications. Use **Enterprise** when you need: - larger scale; - Enterprise-only features; - more advanced availability; - larger memory or compute requirements; - licensing that justifies the cost. Use **Evaluation** only for temporary testing. Raff does not resell SQL Server licenses. Bring your own license through your Microsoft licensing partner, CSP, EA, Software Assurance, or MSP. ## Recommended setup by workload | Workload | Recommended edition | Notes | |---|---|---| | Learning SQL Server 2025 | Standard Developer | Free for dev/test | | Staging for a Standard production app | Standard Developer | Matches Standard feature set | | Very small production app | Express | Only if limits are acceptable | | SMB production database | Standard | Best practical default | | ERP database | Standard | Size RAM and backup strategy carefully | | Heavy reporting | Standard or Enterprise | Depends on workload and features | | HA / advanced enterprise workloads | Enterprise | Review licensing and architecture | | Temporary Enterprise feature test | Evaluation | 180-day evaluation only | ## How Raff fits SQL Server hosting Raff Windows VM is a practical foundation for SQL Server workloads that need a self-managed Windows Server environment. A Raff SQL Server deployment can support: - SQL Server 2025 development and staging; - paid SQL Server Standard production installs; - ERP databases; - internal business apps; - IIS / ASP.NET applications; - reporting workloads; - RDP-based admin access; - backups and snapshots; - private networking between app and database VMs. A simple starting architecture: ```text Windows VM ├── SQL Server 2025 ├── SQL Server Agent ├── Backups └── Monitoring ``` A stronger production architecture: ```text App VM ↓ Private network ↓ SQL Server VM ↓ Backups / snapshots / monitoring ``` Start simple when the workload is small. Split the database from the application server when performance, security, or operational needs justify it. ## Tested on Raff > **Tested on:** SQL Server 2025 Standard Developer Edition installed on a Raff Windows Server 2025 VPS — 4 vCPU / 8 GB RAM / 120 GB NVMe, Windows Server 2025 Standard build 26100, us-east datacenter — on April 24, 2026, by Serdar Tekin. > > The original test verified: media acquisition, Custom setup wizard, Azure Extension unticked, Mixed Mode authentication, TempDB configured as 4 files × 512 MB at `C:\SQL\TempDB`, MaxDOP set to 4, `C:\SQL\Data` / `C:\SQL\Logs` / `C:\SQL\Backups` directory structure, SQL Server Agent set to Automatic, Perform Volume Maintenance Tasks privilege granted, firewall rule for TCP 1433, local and remote connectivity, and `SELECT @@VERSION`. ## What's next - [Connect to your Raff Windows Server via RDP](/windows-server/connect-to-windows-vps-rdp) - [Windows Server 2019 vs 2022 vs 2025: Which Version to Choose](/windows-server/windows-server-version-comparison) - [ERP on Windows VPS: Hosting, Sizing, and Migration](/windows-server/erp-on-vps) - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - SQL Server backup strategy on Windows VPS - MSSQL memory tuning for production workloads ## Sources - Microsoft Learn — [SQL Server 2025 release notes](https://learn.microsoft.com/en-us/sql/sql-server/sql-server-2025-release-notes?view=sql-server-ver17) - Microsoft Learn — [Editions and supported features of SQL Server 2025](https://learn.microsoft.com/en-us/sql/sql-server/editions-and-components-of-sql-server-2025?view=sql-server-ver17) - Microsoft Learn — [Install SQL Server from the Installation Wizard](https://learn.microsoft.com/en-us/sql/database-engine/install-windows/install-sql-server-from-the-installation-wizard-setup?view=sql-server-ver17) - Microsoft Learn — [Configure Windows Firewall for SQL Server access](https://learn.microsoft.com/en-us/sql/sql-server/install/configure-the-windows-firewall-to-allow-sql-server-access?view=sql-server-ver17) - Microsoft Learn — [tempdb database](https://learn.microsoft.com/en-us/sql/relational-databases/databases/tempdb-database?view=sql-server-ver17) - Microsoft Learn — [Server memory configuration options](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/server-memory-server-configuration-options?view=sql-server-ver17) - Microsoft Learn — [Configure the max degree of parallelism option](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option?view=sql-server-ver17) - Microsoft Learn — [Install SQL Server Management Studio](https://learn.microsoft.com/en-us/ssms/install/install) - Microsoft — [SQL Server Downloads](https://www.microsoft.com/en-us/sql-server/sql-server-downloads) - Date last verified: 2026-07-06 --- *Microsoft, Windows Server, SQL Server, and SQL Server Management Studio are trademarks of Microsoft Corporation. Raff Technologies is an independent infrastructure provider and is not affiliated with, sponsored by, or endorsed by Microsoft Corporation.* --- ### Active Directory Replication Topology for 2-DC Setups URL: https://rafftechnologies.com/windows-server/ad-replication-topology Description: Design a clean 2-DC Active Directory topology for Windows Server VPS deployments, including single-site defaults, multi-site replication, FSMO placement, and health checks. For most small business and MSP Active Directory deployments, two domain controllers are enough: one primary DC and one secondary DC in the same AD site, connected over private networking. In a single-site setup, Active Directory replication is automatic. Multi-site setups need proper Sites, Subnets, and Site Links so clients find the right DC and replication follows the right network path. ## Quick verdict by setup | Scenario | Recommended topology | Why | |---|---|---| | One cloud environment, 2 DCs | Single AD site, 2 DCs | Simple, automatic replication, easiest to manage | | One office + one cloud DC | Two sites, one site link | Keeps clients mapped to the right DC | | Two cloud regions | Two sites, subnet mapping, site link | Controls replication and logon locality | | MSP with many clients | Separate AD forests or domains per client | Avoids tenant/security mixing | | Branch office with low trust | Consider RODC | Reduces credential exposure in branch locations | | Only one DC today | Add a second DC | Single-DC AD is a business continuity risk | Simple rule: ```text Single location = one AD site. Multiple network locations = multiple AD sites with subnets and site links. Production AD = at least two domain controllers. ```` ## Why AD replication topology matters Active Directory Domain Services is a replicated system. Each writable domain controller stores a copy of the directory database. Changes such as password updates, group membership changes, computer joins, DNS records, Group Policy changes, and user account updates must replicate between domain controllers. If replication is healthy, users usually do not think about it. If replication is unhealthy, you can see problems like: * users can log in from one location but not another; * password changes work on one DC but not another; * Group Policy changes apply inconsistently; * DNS records are missing or stale; * new computers cannot find the right domain controller; * RDP users authenticate slowly; * one DC shows old group membership; * SYSVOL or GPO changes do not appear everywhere; * a failed DC causes more disruption than expected. Replication topology decides how domain controllers find replication partners and how changes move through the environment. For a small deployment, the best topology is usually simple. For a larger or multi-location deployment, the topology must be intentional. ## The important AD topology terms Before changing anything in Active Directory Sites and Services, know the core terms. ## Domain controller A domain controller is a Windows Server running the Active Directory Domain Services role. It provides: * authentication; * authorization; * directory storage; * Group Policy access; * AD-integrated DNS if installed; * Kerberos services; * LDAP services; * domain join support. A production domain should not rely on only one domain controller. If the only DC fails, the domain can become difficult or impossible to operate normally until recovery. ## Site An AD site represents a network location with reliable, fast connectivity. A site is not the same as an office name or cloud region by itself. In Active Directory, a site is tied to IP subnets. Examples: ```text Site: raff-us-east Subnet: 10.10.0.0/24 Site: office-new-york Subnet: 10.20.0.0/24 ``` Sites help Active Directory decide: * which DC a client should use; * how replication should be routed; * which network path should be preferred; * which domain controllers are considered local. ## Subnet A subnet object maps an IP range to an AD site. This is one of the most commonly missed steps. If you create sites but do not assign subnets, clients may still use the wrong domain controller. Example: ```text 10.10.0.0/24 → raff-us-east 10.20.0.0/24 → office-new-york ``` If a client’s IP is inside `10.20.0.0/24`, AD can associate it with the `office-new-york` site. ## Site link A site link tells AD that two or more sites can replicate with each other. A site link has: * member sites; * cost; * replication interval; * schedule. For two sites, the site link is straightforward. For three or more sites, cost becomes more important because it influences the replication route. ## KCC The Knowledge Consistency Checker, or KCC, is the built-in process that automatically creates replication connections between domain controllers. In normal conditions, you do not manually create connection objects. You define sites, subnets, and site links. Then KCC builds the replication topology. Manual connection objects should be rare and carefully documented. ## Bridgehead server A bridgehead server is the domain controller selected to handle replication between sites. In small two-site setups, you usually do not need to manually choose bridgehead servers. Let KCC select them unless you have a clear reason. ## Global Catalog A Global Catalog server stores a partial replica of objects from all domains in the forest and a full replica of its own domain. In a single-domain SMB setup, it is usually practical for both domain controllers to be Global Catalog servers. This improves logon and lookup availability. ## Topology pattern 1 — Single site with two domain controllers This is the default recommendation for most small business Windows VPS deployments. Use this when: * both DCs are in the same cloud region; * both DCs are on the same private network; * the business has one logical AD location; * latency between DCs is low; * there is no need to control intersite replication; * the deployment is small and simple. Architecture: ```text AD Site: Default-First-Site-Name or raff-primary Private subnet: 10.10.0.0/24 Domain controllers: DC01 DC02 ``` Recommended role split: ```text DC01 - PDC Emulator - RID Master - Infrastructure Master - DNS - Global Catalog DC02 - Secondary writable DC - DNS - Global Catalog - Backup authentication path ``` For a small single-domain environment, you can also leave all FSMO roles on DC01 and use DC02 as the healthy standby. That is usually simpler. ## Why this works In a same-site setup, Active Directory handles replication automatically. KCC creates the replication connections. You do not need to create site links. You do not need to tune replication intervals. You do not need to manually build a full mesh. For most 2-DC SMB setups, this is the correct answer: ```text Promote the second DC. Make sure DNS is correct. Verify replication. Monitor regularly. Do not over-engineer. ``` ## Single-site setup checklist Use this checklist after adding the second domain controller. ## Confirm both DCs exist ```powershell Get-ADDomainController -Filter * | Select-Object HostName, Site, IsGlobalCatalog, IPv4Address ``` Expected: * DC01 and DC02 appear; * both are in the same site; * both have correct IP addresses; * both are reachable. ## Confirm DNS server settings Each DC should usually point DNS to another DC first, then itself. Example: ```text DC01 preferred DNS: DC02 private IP DC01 alternate DNS: DC01 private IP DC02 preferred DNS: DC01 private IP DC02 alternate DNS: DC02 private IP ``` Avoid pointing domain controllers only to public DNS resolvers. AD-integrated DNS is required for normal domain discovery. ## Confirm SYSVOL and NETLOGON shares Run on each DC: ```powershell net share ``` Expected shares: ```text SYSVOL NETLOGON ``` If these shares are missing on a new DC, do not assume replication is healthy. Investigate before using the DC in production. ## Confirm replication summary ```powershell repadmin /replsummary ``` Expected: ```text 0 fails No growing replication backlog Recent successful replication ``` A small delta is normal after a recent change. Growing failures are not normal. ## Confirm detailed replication status ```powershell repadmin /showrepl ``` Look for: * recent last successful attempt; * no repeated failures; * correct source DCs; * no RPC, DNS, or access denied errors. ## Topology pattern 2 — Two cloud regions or office plus cloud Use a multi-site topology when domain controllers live in meaningfully different network locations. ![Active Directory multi-site topology diagram showing two AD sites, subnet mappings, a site link, and replication between cloud and office domain controllers.](https://raff-images.s3.raffusercloud.com/active_directory_sites_subnets_site_link_diagram_png_1bbf343fca.png) Examples: * one DC in Raff cloud and one DC in an office; * one DC in a primary cloud region and one DC in another region; * one DC for headquarters and one DC for a branch; * one DC for a production site and another for disaster recovery; * hybrid AD where on-prem clients should prefer the on-prem DC. Architecture: ```text Site: raff-us Subnet: 10.10.0.0/24 DC01 Site: office-ny Subnet: 10.20.0.0/24 DC02 Site Link: raff-us__office-ny ``` This tells AD: * which clients belong to which site; * which DC is local to each subnet; * how replication should occur between the two sites; * how often replication should be attempted. ## When multi-site is worth it Use multiple sites when: * IP subnets are meaningfully separated; * clients should prefer local DCs; * replication traffic should follow a controlled path; * WAN or VPN links are slower than local networking; * office and cloud authentication paths need separation; * you need a DR location; * you need different replication intervals by location. Do not create multiple sites just to make the diagram look sophisticated. If all DCs are in the same private network with low latency, one site is usually better. ## Step 1 — Create the AD sites Open Active Directory Sites and Services: ```text dssite.msc ``` Then: 1. Right-click **Sites**. 2. Select **New Site**. 3. Name the first site, for example `raff-us`. 4. Select the default site link for now. 5. Repeat for the second site, for example `office-ny`. Use names that match actual network locations. Good names: ```text raff-us office-ny branch-dallas dr-site ``` Bad names: ```text site1 newsite test main2 ``` The names should be understandable six months later. ## Step 2 — Create and assign subnets In Active Directory Sites and Services: 1. Expand **Sites**. 2. Right-click **Subnets**. 3. Select **New Subnet**. 4. Enter the subnet prefix. 5. Assign the subnet to the correct site. Example: ```text 10.10.0.0/24 → raff-us 10.20.0.0/24 → office-ny ``` This step is critical. Sites without subnets are incomplete. If subnets are missing, clients can authenticate against a remote DC even when a local DC exists. ## Step 3 — Move domain controllers to the correct sites In `dssite.msc`: 1. Expand the old site, usually `Default-First-Site-Name`. 2. Expand **Servers**. 3. Right-click or drag each domain controller into the correct site. 4. Confirm the DC appears under the right site. Example: ```text DC01 → raff-us DC02 → office-ny ``` After moving DCs, allow time for replication. Then verify: ```powershell Get-ADDomainController -Filter * | Select-Object HostName, Site, IPv4Address ``` ## Step 4 — Create or configure the site link In Active Directory Sites and Services: 1. Expand **Inter-Site Transports**. 2. Expand **IP**. 3. Right-click and create a new site link, or edit the existing one. 4. Add both sites. 5. Set a clear name. 6. Set cost and replication interval. Example: ```text Site link: raff-us__office-ny Sites: raff-us, office-ny Cost: 100 Replication interval: 15 minutes ``` For a simple two-site environment, cost is not very important. For three or more sites, cost helps AD choose preferred replication routes. ## Replication interval guidance Site link replication should match business need and network quality. | Setup | Suggested interval | Why | | ---------------------------------------------- | ----------------------------: | ------------------------------------- | | Same site | Automatic change notification | Let AD manage it | | Two cloud regions with good private networking | 15 minutes | Practical for SMB production | | Office plus cloud over stable VPN | 15–30 minutes | Balance freshness and WAN traffic | | Slow branch link | 60–180 minutes | Reduce bandwidth pressure | | DR-only site | 60–180 minutes | Usually less urgent | | High-change identity environment | 15 minutes | Faster password and group propagation | Do not set everything to the fastest possible interval without understanding traffic. For most SMB and MSP deployments, 15 minutes is a good starting point for important intersite replication. ## Step 5 — Verify client site mapping From a domain-joined client or server, run: ```cmd nltest /dsgetsite ``` Expected: ```text raff-us ``` or: ```text office-ny ``` depending on the client subnet. Then check which DC the client discovers: ```cmd nltest /dsgetdc:yourdomain.local ``` If a client in the office is discovering the cloud DC when it should use the office DC, check subnet assignment first. ## FSMO roles and placement Active Directory has five Operation Master roles, often still called FSMO roles. They are: | Role | Scope | Practical meaning | | --------------------- | ------ | ------------------------------------------------ | | Schema Master | Forest | Controls schema updates | | Domain Naming Master | Forest | Controls adding/removing domains | | PDC Emulator | Domain | Password changes, time sync, legacy PDC behavior | | RID Master | Domain | Allocates RID pools for new security principals | | Infrastructure Master | Domain | Updates cross-domain object references | In a new forest, the first domain controller usually holds all five roles. For a small 2-DC domain, that is usually acceptable. ## Recommended FSMO placement for a 2-DC setup For most SMB deployments: ```text DC01: - All FSMO roles - DNS - Global Catalog DC02: - DNS - Global Catalog - Healthy replication partner - Standby DC ``` Why keep all FSMO roles on DC01? Because it is simple. For a two-DC environment, spreading roles across DCs can create more confusion than benefit. The important part is not role spreading. The important part is knowing where the roles are and knowing how to transfer or seize them if DC01 permanently fails. ## Check FSMO role placement Run: ```cmd netdom query fsmo ``` Or use PowerShell: ```powershell Get-ADForest | Select-Object SchemaMaster, DomainNamingMaster Get-ADDomain | Select-Object PDCEmulator, RIDMaster, InfrastructureMaster ``` Document the output. During an outage, you do not want to discover role placement for the first time. ## Transfer FSMO roles for planned maintenance If DC01 is healthy and you plan to take it offline for a long maintenance window, transfer roles gracefully. Example: ```powershell Move-ADDirectoryServerOperationMasterRole ` -Identity "DC02" ` -OperationMasterRole PDCEmulator, RIDMaster, InfrastructureMaster ``` For all roles: ```powershell Move-ADDirectoryServerOperationMasterRole ` -Identity "DC02" ` -OperationMasterRole SchemaMaster, DomainNamingMaster, PDCEmulator, RIDMaster, InfrastructureMaster ``` Only do this when you understand the impact. For normal patching and short reboots, transferring roles is usually unnecessary. ## Seize roles only after permanent failure Seizing roles is different from transferring roles. Transfer = the current owner is alive and cooperates. Seize = the current owner is dead or cannot return. Do not seize FSMO roles casually. Seize roles only when: * the old role holder is permanently unavailable; * it cannot be cleanly brought back; * you understand cleanup requirements; * you are prepared to remove metadata for the failed DC. If a failed DC might come back online, be careful. Bringing back a failed role holder after role seizure can create dangerous conflicts. ## Global Catalog placement For most single-domain 2-DC setups, make both domain controllers Global Catalog servers. That improves: * logon resilience; * directory search availability; * group membership evaluation; * lookup reliability. Check Global Catalog status: ```powershell Get-ADDomainController -Filter * | Select-Object HostName, IsGlobalCatalog ``` For single-domain environments, both should usually show: ```text True ``` For multi-domain forests, Global Catalog placement needs more planning. ## DNS design for two domain controllers AD depends heavily on DNS. Bad DNS design causes many “replication” problems that are really name-resolution problems. For two DCs: ```text DC01 DNS: Preferred: DC02 private IP Alternate: DC01 private IP DC02 DNS: Preferred: DC01 private IP Alternate: DC02 private IP ``` For clients: ```text Client DNS: Preferred: nearest/local DC Alternate: secondary DC ``` Do not point AD clients directly to public DNS resolvers such as `8.8.8.8` or `1.1.1.1`. Use AD DNS first. Forwarders can handle internet DNS resolution from the DCs. ## Network ports and private connectivity Domain controllers need more than RDP open to each other. AD replication and domain services use several protocols, including: * DNS; * Kerberos; * LDAP; * LDAPS if configured; * SMB; * RPC Endpoint Mapper; * dynamic RPC ports; * Global Catalog ports. For modern Windows Server environments, dynamic RPC commonly uses the high port range: ```text 49152–65535 ``` This matters if you place DCs behind strict firewalls, private networks, security groups, VPNs, or segmented networks. A practical rule: ```text Keep domain controllers on a trusted private network when possible. Do not expose AD replication paths to the public internet. ``` If you must segment domain controllers, plan firewall rules carefully. Do not randomly open ports until replication works. ## Replication health checks Run replication checks regularly. For production, weekly is a reasonable baseline. For critical environments, run them daily or automate monitoring. ## Quick summary ```cmd repadmin /replsummary ``` Look for: * largest delta; * failures; * failure percentage; * source DSA; * destination DSA. Healthy result: ```text 0 fails low or expected delta recent replication ``` ## Detailed replication view ```cmd repadmin /showrepl ``` Use this when `/replsummary` shows failures. Look for: * last success time; * last error; * source DC; * naming context; * repeated failure patterns. Common errors often point to: * DNS failure; * RPC blocked; * access denied; * time skew; * offline DC; * broken secure channel; * routing/firewall issue. ## Force replication when needed Use this after planned changes or when testing. ```cmd repadmin /syncall /AeD ``` Common options: | Option | Meaning | | ------ | ---------------------------------------- | | `/A` | All naming contexts | | `/e` | Cross site boundaries | | `/D` | Identify servers by distinguished name | | `/P` | Push changes outward from the current DC | For many admin checks, this is useful: ```cmd repadmin /syncall /AeD ``` Do not use forced replication as a substitute for fixing a broken topology. ## Check domain controller discovery ```cmd nltest /dclist:yourdomain.local ``` Check secure channel: ```powershell Test-ComputerSecureChannel ``` From a domain-joined client: ```cmd nltest /dsgetdc:yourdomain.local ``` These commands help confirm whether clients can discover and use domain controllers correctly. ## Check SYSVOL replication SYSVOL contains Group Policy and logon scripts. Check shares: ```cmd net view \\DC01 net view \\DC02 ``` Expected: ```text SYSVOL NETLOGON ``` Check Group Policy consistency: ```cmd gpupdate /force ``` On a client: ```cmd gpresult /r ``` If Group Policy behaves differently depending on which DC is used, investigate SYSVOL and AD replication. ## Monitoring schedule Use this simple schedule. | Frequency | Check | | ---------------------------- | -------------------------------------------- | | Daily for critical AD | `repadmin /replsummary` | | Weekly for normal SMB AD | `repadmin /replsummary`, DNS check | | Monthly | Review FSMO owners, GC status, backup status | | After adding a DC | `repadmin /showrepl`, SYSVOL check | | After site/subnet changes | `nltest /dsgetsite`, `nltest /dsgetdc` | | After firewall changes | RPC, LDAP, DNS, SMB connectivity | | After disaster recovery test | FSMO, DNS, SYSVOL, login tests | AD replication should not be checked only when users complain. ## Backup and recovery for domain controllers Do not rely on replication as a backup. Replication copies changes. That includes bad changes. If an admin deletes an OU, breaks DNS, damages Group Policy, or removes users, that change can replicate to other DCs. You still need backups. For AD, plan: * system state backups; * VM-level backups or snapshots; * restore testing; * documented recovery steps; * Active Directory Recycle Bin if appropriate; * clear rules for FSMO seizure; * metadata cleanup process for failed DCs. Snapshots are useful before risky changes. Backups are required for recovery. ## Common mistakes ## Mistake 1 — Running only one domain controller A single DC is a single point of failure. If it fails, users may lose authentication, DNS, Group Policy, and domain services. Use at least two domain controllers for production. ## Mistake 2 — Putting both DCs on the same failure boundary Two DCs on the same host, same storage dependency, or same fragile network path may not provide real redundancy. For stronger resilience, separate them where practical. ## Mistake 3 — Creating sites but not assigning subnets Sites without subnets do not properly guide client location. If clients authenticate against the wrong DC, check subnet mapping first. ## Mistake 4 — Manually creating replication connections without a reason KCC normally handles connection objects. Manual connections can make troubleshooting harder. Only create manual connections when there is a documented reason. ## Mistake 5 — Leaving old failed DC metadata behind If a DC is permanently gone, clean it up properly. Stale DC objects can cause replication, DNS, and authentication confusion. ## Mistake 6 — Opening AD ports over the public internet Domain controllers should communicate over private networks, VPNs, or trusted paths. Do not expose domain controller replication broadly to the public internet. ## Mistake 7 — Treating replication as backup Replication is not backup. Replication copies both good and bad changes. Use system state backups and recovery planning. ## Mistake 8 — Ignoring DNS Many AD replication problems are DNS problems. Always check DNS before assuming AD itself is broken. ## Mistake 9 — Not documenting FSMO placement During an outage, FSMO role placement matters. Document current role holders and recovery steps. ## Mistake 10 — Mixing too many roles on domain controllers Domain controllers should be dedicated when possible. Avoid running SQL Server, ERP apps, IIS workloads, or random business software on DCs. A mixed-role DC is harder to secure, patch, and recover. ## Raff recommendation for 2-DC Windows VPS deployments For most Raff Windows VPS Active Directory deployments, use this model: ```text DC01: Primary domain controller DNS Global Catalog FSMO roles Private IP only where possible DC02: Secondary domain controller DNS Global Catalog Replication partner Private IP only where possible ``` If both DCs live in the same Raff private network and region, keep them in one AD site. If one DC is in Raff and another is in an office or another region, create proper AD sites and subnet mappings. Recommended baseline: ```text Small deployment: 2 DCs, one AD site, both DNS + GC Hybrid office/cloud: 2 sites, 2 subnets, 1 site link, 15–30 minute replication MSP client environment: separate client domains or forests, not one shared AD for unrelated clients ``` Do not overcomplicate the topology before the business needs it. But do not run production AD with one DC. ## What to test before production Before relying on the topology, test: * both DCs can authenticate users; * both DCs resolve AD DNS records; * `repadmin /replsummary` shows no failures; * SYSVOL and NETLOGON exist on both DCs; * clients discover the correct site; * clients find the expected domain controller; * Group Policy applies correctly; * a password change replicates; * DNS records replicate; * backup and restore procedure is documented; * FSMO owners are known. A clean test saves painful troubleshooting later. ## Compatible with Raff Windows VM This guide is compatible with Raff Windows VM deployments running Windows Server domain controllers. Use a “Tested on Raff” claim only after retesting the exact environment and recording: * Windows Server version and build; * number of DCs; * topology type; * private network design; * test date; * tester name; * screenshots; * `repadmin /replsummary` output. Suggested test note after validation: ```text Tested on two Raff Windows VMs running Windows Server 2022 or 2025, two writable domain controllers, AD-integrated DNS, same-site replication, Global Catalog enabled on both DCs, and private networking between DCs. Replication verified with repadmin /replsummary and repadmin /showrepl. ``` Do not publish that claim until the test is actually complete. ## What's next * Promote a Windows VPS to a domain controller. * Set up Active Directory Group Policy from scratch. * Review Windows Server hardening before exposing production workloads. * Configure Windows Firewall for production. * Plan Windows Server backups before relying on AD in production. * Review RDP access and RDS licensing before giving users server access. ## Sources * Microsoft Learn — Active Directory Replication Concepts * Microsoft Learn — Transfer or seize Operation Master roles in Active Directory Domain Services * Microsoft Learn — Service overview and network port requirements for Windows * Microsoft Learn — Active Directory Domain Services overview * Raff — Windows VM product page --- ### MetaTrader VPS Setup for 24/7 EA Trading (Windows) URL: https://rafftechnologies.com/windows-server/metatrader-vps-setup Description: Learn how to set up MetaTrader 4 or MetaTrader 5 on a Windows Server VPS, keep EAs running, avoid RDP sign-out mistakes, secure access, test logs, and choose the right VPS size. A MetaTrader VPS setup means running MetaTrader 4 or MetaTrader 5 on a remote Windows Server so the trading terminal, Expert Advisors, indicators, and signal tools can stay online even when your personal computer is turned off. The clean setup is: ```text Deploy Windows VPS Connect over RDP Install MT4 or MT5 from your broker or MetaQuotes Log in to your trading account Install Expert Advisors / indicators Enable automated trading only after testing Configure startup behavior Keep the RDP session disconnected, not signed out Monitor Journal and Experts logs Back up the MetaTrader data folder ``` The most important operational rule: ```text Disconnect from RDP. Do not sign out. ``` If you sign out of Windows, MetaTrader usually closes because it is a desktop application running inside that user session. A Windows VPS is useful for MetaTrader because it gives you a remote Windows environment with persistent internet access, full administrator control, and RDP access. It does not guarantee profits, execution quality, broker acceptance, or a specific latency result. ## Important trading risk note This article is technical infrastructure documentation. It does not provide trading advice, financial advice, investment recommendations, broker recommendations, or strategy recommendations. A VPS can help keep MetaTrader online. It cannot make an Expert Advisor profitable, remove market risk, prevent slippage, guarantee order execution, or protect against broker-side outages. Before running any Expert Advisor or signal subscription on a live account: - test it on a demo account; - understand the strategy; - review logs; - confirm lot sizing; - check max drawdown behavior; - verify broker rules; - understand spread and slippage risk; - keep your own backups; - accept that automated trading can lose money. Infrastructure improves availability. It does not remove trading risk. ## Quick verdict | Situation | Recommendation | |---|---| | You run one MT4 or MT5 terminal with one EA | Small Windows VPS is usually enough | | You run multiple terminals or multiple brokers | Use more RAM and CPU headroom | | You need lowest possible broker latency | Choose a location close to your broker's trade server and test ping | | You only need MetaTrader's built-in VPS sync | Consider MetaTrader Virtual Hosting | | You want full Windows control, RDP, files, scripts, and multiple terminals | Use a Windows VPS | | You backtest or optimize heavily | Use a stronger VM; optimization is CPU-heavy | | You run production EAs | Disable random reboots, monitor logs, and keep backups | | You cannot monitor the account | Do not run live automation unattended | Simple rule: ```text MetaTrader built-in VPS = simple EA/signal migration. Windows VPS = full control over the Windows trading environment. ``` ## MetaTrader built-in VPS vs Windows VPS MetaTrader 5 includes built-in Virtual Hosting, which is designed to run trading robots and signal subscriptions 24/7, close to broker infrastructure, with migration from inside the trading platform. That is different from renting a full Windows VPS. ## MetaTrader built-in VPS MetaTrader Virtual Hosting is useful when you want: - EA or signal subscription migration from inside MetaTrader; - minimal server management; - a setup that is tightly integrated with the MetaTrader platform; - no Windows desktop administration; - simple 24/7 operation for one MetaTrader environment. Trade-off: - less Windows-level control; - not designed for general server use; - less flexibility for custom tools; - not ideal if you need several terminals, custom file workflows, or full Windows administration. ## Windows VPS A Windows VPS is useful when you want: - full Windows desktop access; - RDP control; - multiple MT4/MT5 terminals; - custom indicators and EAs; - broker-specific installers; - scripts and file automation; - custom backup process; - control over Windows updates and startup behavior; - ability to run other supporting tools. Trade-off: - you manage Windows; - you manage security; - you manage backups; - you must keep MetaTrader running correctly; - latency depends on VPS location, broker server location, routing, and broker execution. For many traders, the Windows VPS model is easier to understand because it behaves like a remote Windows computer. ## MT4 vs MT5 on a VPS Both MetaTrader 4 and MetaTrader 5 are commonly used on Windows VPS environments. | Platform | Better fit | |---|---| | MT4 | Existing forex EAs, older broker setups, legacy MQL4 tools | | MT5 | Newer accounts, multi-asset brokers, MQL5 tools, signals, built-in VPS workflow | | Both | Multi-broker users, migration testing, strategy comparison | Use the platform your broker supports and your EA requires. Do not assume an MT4 EA works on MT5. Do not assume an MT5 EA works on MT4. The scripting languages, platform behavior, broker symbols, account types, and execution details can differ. ## Choosing VPS location Latency matters for some automated strategies, but it is often misunderstood. A VPS close to your broker's trading server can reduce network delay between the terminal and broker. But execution quality also depends on: - broker server location; - broker routing; - liquidity provider; - account type; - spread; - slippage; - market volatility; - EA logic; - order type; - trade size; - broker execution model. Choose a VPS region based on the broker server you actually use, not your home location. If your broker has servers in New York or nearby US infrastructure, a US-based VPS can make sense. If your broker server is in London, Frankfurt, Singapore, or Tokyo, test latency carefully before committing. Inside MetaTrader, check the connection status and ping to the broker server. Document the number, but do not treat it as a permanent guarantee. Routing can change. ## VPS sizing for MetaTrader MetaTrader itself is not usually heavy, but multiple terminals, charts, indicators, logs, and strategy testing can use meaningful resources. Practical sizing: | Workload | Suggested starting point | |---|---| | 1 MT4/MT5 terminal, light EA | 2 vCPU / 4 GB RAM | | 1-3 terminals, several charts | 2-4 vCPU / 4-8 GB RAM | | 3-6 terminals, multiple EAs | 4 vCPU / 8 GB RAM | | Many terminals or heavy indicators | 4-8 vCPU / 8-16 GB RAM | | Strategy testing / optimization | CPU-optimized VM with more RAM | | Always-on production automation | Add headroom instead of running at 90% usage | Storage needs are usually modest, but leave room for: - platform files; - logs; - historical data; - tester cache; - screenshots; - EA files; - backups. If you run many terminals, logs and history data can grow over time. ## What you will build Target setup: ```text Your laptop ↓ RDP Raff Windows VPS ├── MetaTrader 4 or MetaTrader 5 ├── Broker login ├── Expert Advisors / indicators ├── AutoTrading enabled after testing ├── Startup shortcut or scheduled launch ├── Journal and Experts logs └── Backups of the MetaTrader data folder ``` The VPS stays online even when your laptop is off. You connect only when you need to check, update, or manage the terminal. ## What you'll need Prepare: - Raff Windows VPS or similar Windows Server VPS; - RDP access; - broker-supported MT4 or MT5 installer; - broker account login details; - read-only investor password if someone only needs monitoring access; - Expert Advisor files if used; - indicator files if used; - license keys for purchased EAs if required; - basic backup plan; - 30-60 minutes for first setup. Do not store broker passwords in plaintext files. Use a password manager. ## Step 1 — Deploy a Windows VPS Deploy a Windows VPS with enough CPU and RAM for the number of terminals you plan to run. For most users: ```text 2 vCPU / 4 GB RAM ``` is a reasonable starting point for one terminal. Use more headroom if: - multiple terminals run at once; - several EAs run at once; - the account uses many charts; - historical data downloads are large; - the VPS also runs monitoring tools; - you backtest or optimize on the VPS. Choose Windows Server 2022 or Windows Server 2025 based on your broker's MetaTrader installer compatibility. MetaTrader is a Windows desktop application, so both usually work, but test the broker-specific installer before production use. ## Step 2 — Connect over RDP Open Remote Desktop from your local machine and connect to the VPS. Use: ```text Computer: VPS public IP Username: Administrator Password: your Windows VPS password ``` After login: 1. Run Windows Update. 2. Reboot if required. 3. Reconnect. 4. Confirm time zone. 5. Confirm internet access. 6. Confirm browser download works. Do not install trading software before the server is patched and stable. ## Step 3 — Download MetaTrader Download MetaTrader from one of these sources: - your broker's client portal; - your broker's official MT4/MT5 download page; - the official MetaTrader 5 download page; - MetaQuotes or MQL5 resources where appropriate. Prefer the broker-provided installer when using a live broker account. Why? Because broker installers often include the correct server list, branding, and connection configuration. Avoid random third-party MetaTrader downloads. They can include outdated builds, wrong broker configuration, or unwanted software. ## Step 4 — Install MetaTrader Run the MT4 or MT5 installer as Administrator. Use the default install path unless you have a reason to change it. After installation: 1. Open MetaTrader. 2. Log in to your broker account. 3. Select the correct broker server. 4. Confirm the connection status. 5. Open the relevant symbols in Market Watch. 6. Check the Journal tab for login or connection errors. If login fails, confirm: - account number; - password; - server name; - account type; - broker restrictions; - MFA or security requirements; - whether the account is MT4 or MT5. MT4 credentials do not necessarily work in MT5, and MT5 credentials do not necessarily work in MT4. ## Step 5 — Open the MetaTrader data folder MetaTrader keeps EAs, indicators, profiles, logs, templates, and configuration in the data folder. In MetaTrader: ```text File → Open Data Folder ``` Important folders: | Folder | Purpose | |---|---| | MQL4 or MQL5 | Expert Advisors, indicators, scripts | | Experts | EA files | | Indicators | Custom indicators | | Presets | EA parameter files | | Profiles | Chart layouts | | Templates | Chart templates | | Logs | Platform logs | | Tester | Strategy tester files | This folder is the one you should back up before major changes. ## Step 6 — Install Expert Advisors or indicators For MT4: ```text MQL4 → Experts ``` For MT5: ```text MQL5 → Experts ``` Copy your `.ex4`, `.mq4`, `.ex5`, or `.mq5` files into the correct folder. Then restart MetaTrader or refresh the Navigator panel. To attach an EA: 1. Open the chart and timeframe required by the strategy. 2. Drag the EA from Navigator to the chart. 3. Confirm EA inputs. 4. Check the EA smiley/icon/status. 5. Enable automated trading only when you are ready. 6. Watch the Experts and Journal tabs. Only run one EA per chart unless the strategy is specifically designed otherwise. ## Step 7 — Enable automated trading safely In MetaTrader, automated trading usually requires two things: 1. Global automated trading enabled in platform options. 2. EA-level permission enabled on the chart. For MT5: ```text Tools → Options → Expert Advisors ``` Review: - Allow algorithmic trading; - allow DLL imports only if the EA requires it and you trust it; - allow WebRequest only for trusted URLs if required. For MT4: ```text Tools → Options → Expert Advisors ``` Then check the AutoTrading or Algo Trading button on the toolbar. Do not enable DLL imports for unknown EAs. Do not enable WebRequest to unknown domains. Purchased or downloaded EAs can execute trading logic and sometimes interact with external services. Treat them like production software. ## Step 8 — Test on demo before live Before running a live EA: 1. Use a demo account. 2. Confirm the EA loads without errors. 3. Confirm symbols match your broker naming. 4. Confirm lot size. 5. Confirm spread behavior. 6. Confirm stop-loss and take-profit rules. 7. Confirm max trades. 8. Confirm trading hours. 9. Confirm news filters if used. 10. Review the Experts tab. If the EA has a Strategy Tester path, test it there first. MetaTrader 5 Strategy Tester supports testing and optimization of Expert Advisors using historical data and can run many optimization passes with different parameters. Backtesting does not guarantee future performance, but it can catch configuration mistakes before live trading. ## Step 9 — Keep MetaTrader running after RDP disconnect This is the most common VPS mistake. When you are finished checking MetaTrader, close the RDP window or disconnect. Do not click: ```text Start → Sign out ``` Do not run: ```cmd logoff ``` If you sign out, the desktop session closes and MetaTrader closes. Correct behavior: ```text Disconnect RDP session ``` MetaTrader should continue running in the disconnected user session. You can also lock the session: ```text Win + L ``` Then disconnect. After reconnecting later, confirm: - terminal is still open; - connection is active; - EA is still attached; - AutoTrading/Algo Trading is still enabled; - Journal logs are normal. ## Step 10 — Start MetaTrader automatically after login For simple setups, add MetaTrader to the Startup folder. Press: ```text Win + R shell:startup ``` Create a shortcut to MetaTrader there. This starts MetaTrader when that Windows user logs in. A more controlled method is Task Scheduler: 1. Open **Task Scheduler**. 2. Create Basic Task. 3. Trigger: **When I log on**. 4. Action: **Start a program**. 5. Program: path to `terminal.exe` or `terminal64.exe`. Important: MetaTrader is a GUI desktop application. Starting it at system boot without an interactive user session can be unreliable. A scheduled task at user logon is safer than pretending MetaTrader is a Windows service. For serious unattended setups, plan maintenance windows and reboot recovery manually. ## Step 11 — Control Windows updates Windows updates are important, but random reboots can interrupt MetaTrader. Use a planned update process: - choose a maintenance window outside your trading strategy's active hours; - check open positions before reboot; - stop EAs if required; - install updates; - reboot; - reconnect; - verify MetaTrader starts; - verify account connection; - verify EAs are active; - check Journal and Experts logs. Do not disable updates forever. A trading VPS exposed to the internet still needs security patches. The goal is controlled updates, not no updates. ## Step 12 — Back up MetaTrader configuration Back up the data folder before: - changing EA versions; - changing input parameters; - changing broker account; - moving to another VPS; - installing many indicators; - cleaning logs; - updating platform builds; - changing templates or profiles. In MetaTrader: ```text File → Open Data Folder ``` Back up: - `MQL4` or `MQL5`; - `Profiles`; - `Templates`; - `Presets`; - key log folders; - screenshots or reports if used. Do not rely only on screenshots of settings. Save `.set` files for EA inputs. Store backups off the VPS if the trading setup matters. ## Step 13 — Monitor logs Check these tabs inside MetaTrader: | Tab | What to check | |---|---| | Journal | login, connection, platform, broker, sync messages | | Experts | EA loading, trading permissions, order errors, strategy messages | | Trade | open positions and account state | | Mailbox | broker messages | | Alerts | configured alerts | Common messages to investigate: - invalid stops; - trade disabled; - market closed; - not enough money; - invalid volume; - off quotes; - requote; - no connection; - authorization failed; - DLL imports disabled; - WebRequest not allowed. Do not ignore repeated errors. An EA can be "running" but failing every trade request. ## Step 14 — Secure the VPS A MetaTrader VPS often contains broker credentials and trading software. Secure it. Minimum checklist: - strong Administrator password; - no shared admin account for a team; - RDP restricted by IP if possible; - Windows Firewall enabled; - Windows Update enabled; - only trusted EA files installed; - no random cracked EAs or indicators; - broker password stored in a password manager; - investor password used for read-only access; - backups protected; - clipboard and drive redirection limited if needed; - no public file shares; - no unnecessary ports exposed. If you use purchased EAs, keep license keys secure. Do not upload broker passwords, `.set` files, logs, or screenshots publicly without review. ## Common errors and fixes ## Error 1 — MetaTrader closes when I disconnect You probably signed out instead of disconnecting. Fix: - log back in; - open MetaTrader; - check EA and account status; - disconnect by closing the RDP window instead of signing out. ## Error 2 — EA is attached but not trading Check: - AutoTrading/Algo Trading button; - EA settings; - symbol name; - chart timeframe; - lot size; - broker trading permissions; - account type; - market hours; - minimum stop level; - margin; - Experts tab errors; - Journal tab errors. Do not assume it is a VPS problem. Most EA failures are configuration, broker, or strategy rules. ## Error 3 — "No connection" or login failed Check: - broker server selected correctly; - account number; - password; - broker server status; - VPS internet access; - firewall or proxy; - broker account restrictions; - MT4 vs MT5 mismatch. If the broker changed server names, reinstall the broker-provided terminal or rescan servers. ## Error 4 — EA needs WebRequest Some EAs call external URLs. Enable only trusted URLs: ```text Tools → Options → Expert Advisors → Allow WebRequest for listed URL ``` Add only the exact domains required by the EA vendor. Do not allow unknown URLs. ## Error 5 — DLL imports disabled Some EAs require DLL imports. Only enable DLL imports if: - you trust the EA vendor; - the DLL is from a known source; - you understand the security risk; - the EA documentation requires it. DLLs are executable code. Treat them carefully. ## Error 6 — VPS rebooted and MetaTrader did not restart MetaTrader usually starts when a user logs in, not before. Fix: - add MetaTrader to Startup folder; - create a Task Scheduler trigger at user logon; - after planned reboot, log in and confirm; - avoid unscheduled reboots during trading hours. Do not assume a GUI trading terminal behaves like a background service. ## Error 7 — High CPU usage Possible causes: - too many charts; - too many indicators; - too many terminals; - aggressive tick processing; - strategy testing running; - EA loop bug; - logging too much; - Windows updates; - antivirus scanning terminal folders. Fix: - reduce charts; - close unused symbols; - reduce indicators; - split terminals across larger VM; - review EA behavior; - avoid running Strategy Tester during live trading. ## Error 8 — RDP is slow but MetaTrader still works RDP performance and broker execution are not the same. If the desktop feels slow: - reduce RDP resolution; - reduce color depth; - disable visual effects; - close extra apps; - check CPU/RAM; - use a closer RDP client network; - read RDP performance tuning. If MetaTrader logs show normal broker ping and no connection errors, the trading terminal may still be functioning even if the remote desktop feels sluggish. ## Security mistakes to avoid Avoid: - running cracked EAs; - storing broker credentials in plain text; - exposing RDP to everyone without a strong password; - disabling Windows Firewall; - disabling updates forever; - running unknown scripts as Administrator; - sharing screenshots with account numbers visible; - copying terminal folders to third parties without cleaning logs; - testing new EAs on live accounts first; - using the same password for VPS and broker account. Treat the VPS as a production financial system. ## How Raff fits MetaTrader VPS setups Raff Windows VPS gives you a Windows Server environment with RDP access and full administrator control. That fits MetaTrader users who want: - MT4 or MT5 on a remote Windows desktop; - 24/7 terminal availability; - full control over files and indicators; - multiple terminals or brokers; - stable Windows infrastructure; - unmetered bandwidth; - support for Windows VPS access and infrastructure issues. Raff does not provide: - trading advice; - broker services; - EA validation; - profitability guarantees; - account management; - financial recommendations; - MetaQuotes or broker account support. A practical Raff MetaTrader setup: ```text Raff Windows VPS ↓ RDP access ↓ MetaTrader terminal ↓ Broker connection ↓ EA / indicator / signal tools ↓ Monitoring + backups ``` Use Raff for infrastructure. Use your broker and MetaTrader vendor resources for trading platform, account, and EA-specific support. ## What Raff recommends For MetaTrader on a Windows VPS: 1. Choose a VPS region based on broker server latency, not your home location. 2. Start with enough RAM headroom. 3. Install MetaTrader from your broker or official source. 4. Test on demo before live. 5. Enable AutoTrading only after reviewing EA settings. 6. Disconnect from RDP instead of signing out. 7. Use Startup folder or Task Scheduler for user-logon startup. 8. Plan Windows updates instead of disabling them forever. 9. Back up the MetaTrader data folder and `.set` files. 10. Monitor Journal and Experts logs. The goal is not just to keep a terminal open. The goal is to run a controlled, monitored, recoverable MetaTrader environment. ## Tested on > Compatible with Raff Windows VPS deployments running MetaTrader 4 or MetaTrader 5 over RDP. Do not publish that exact claim until the environment has been tested. ## What's next - [Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) - [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) - [Windows Server 2019 vs 2022 vs 2025: Which Version to Choose](/windows-server/windows-server-version-comparison) - [Windows Firewall for Production Servers](/windows-server/windows-firewall-production) - [Cloud Server Backup Strategies](/learn/guides/cloud-server-backup-strategies) - [Raff Windows VPS](/products/windows-vm) ## Sources - MetaTrader 5 — Virtual Hosting for Forex and Stocks Trading - MetaTrader 5 — Download MetaTrader 5 - MetaTrader 5 Help — Expert Advisors and Custom Indicators - MetaTrader 5 Help — Strategy Optimization - Microsoft Learn — Remote Desktop Services overview - Date last verified: 2026-07-07 --- MetaTrader, MetaTrader 4, MetaTrader 5, MQL4, MQL5, and MetaQuotes are trademarks or products of MetaQuotes Ltd. Raff Technologies is not affiliated with or endorsed by MetaQuotes, any broker, or any trading platform vendor. This article is technical infrastructure documentation only and is not financial advice. --- ### Azure VM Alternative: Raff Windows VPS for Cost, Simplicity, and Fit URL: https://rafftechnologies.com/windows-server/azure-comparison Description: Compare Azure Windows VMs and Raff Windows VPS for SMB workloads, including cost structure, egress, licensing, support, migration, and practical fit. Choose Azure when your workload depends on the Azure ecosystem: Azure SQL, Entra ID, Azure Functions, Logic Apps, Service Bus, Azure Monitor, global regions, or specific compliance programs. Choose Raff Windows VPS when you mainly need a reliable Windows Server you can RDP into, with predictable monthly pricing, full admin access, unmetered bandwidth, and Windows-focused support. The honest test is simple: ```text If you need Azure services, choose Azure. If you need a Windows Server VM, Raff is usually simpler and more cost-predictable. ```` ![Azure vs Raff Windows VPS decision framework showing Azure as the better fit for Azure-native services, global regions, and enterprise governance, while Raff fits Windows VPS, RDP, business apps, SQL Server, ERP, predictable cost, and unmetered bandwidth.](https://raff-images.s3.raffusercloud.com/azure_vs_raff_windows_vps_decision_framework_png_1be12d61d2.png) ## Quick verdict by use case | If you are running... | Better fit | Why | | --------------------------------------------------------------------------- | ---------------- | -------------------------------------------------------------- | | QuickBooks, Sage, tax software, or ERP over RDP | Raff Windows VPS | Straight Windows Server workload with predictable monthly cost | | A simple IIS / ASP.NET app on a Windows VM | Raff Windows VPS | Full admin access without Azure complexity | | SQL Server on a self-managed Windows VM | Raff Windows VPS | Similar self-managed responsibility, simpler cost model | | Azure SQL, Azure Functions, Service Bus, or Logic Apps | Azure | The app depends on Azure-native services | | Enterprise environment using Entra ID, Defender, Sentinel, and Azure Policy | Azure | Native governance and security integration | | Multi-region global architecture | Azure | Broad region coverage and platform services | | Small business replacing an office Windows server | Raff Windows VPS | Easier mental model and Windows-focused support | | Regulated workload requiring a specific Azure region or sovereign cloud | Azure | Data residency and compliance requirement | | RDP server for remote staff or contractors | Raff Windows VPS | Predictable Windows VPS setup with RDP access | | Experimental dev/staging Windows servers | Raff Windows VPS | Easier fixed monthly planning | Simple rule: ```text Azure = cloud platform ecosystem. Raff = focused Windows VPS infrastructure. ``` ## What this comparison is really about Azure and Raff are not the same type of platform. Azure is a hyperscale cloud platform with hundreds of services. It is designed for enterprises, global systems, managed databases, serverless applications, identity governance, compliance programs, and large-scale architecture patterns. Raff Windows VPS is focused on a narrower problem: ```text Give teams a reliable Windows Server they can deploy, access, manage, and run business software on without unnecessary cloud complexity. ``` That difference matters. If your workload needs Azure-native services, comparing only VM price misses the point. If your workload is just a Windows Server running RDP, IIS, SQL Server, Active Directory, accounting software, ERP, or a legacy business app, Azure may be more platform than you need. ## Side-by-side comparison | Factor | Azure Windows VM | Raff Windows VPS | | ---------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------- | | Best for | Azure-connected workloads, enterprise governance, global regions | SMB Windows workloads, RDP, business apps, IIS, SQL Server, ERP | | Pricing style | Metered cloud pricing | Predictable VPS pricing | | Windows access | RDP / Bastion / network rules | RDP-ready Windows VPS | | Admin control | Full admin control on VM | Full admin control on VM | | OS management | Customer manages OS and applications | Customer manages OS and applications | | Managed services | Very broad Azure ecosystem | Focused VPS platform | | Bandwidth | Internet egress is metered after free tier | Unmetered bandwidth on Raff plans | | Disk model | Managed disks billed separately | Storage included in VM plan | | Public IP | Azure resource and billing object | Included as part of VPS setup | | Licensing path | Windows VM license included in Azure price, or Azure Hybrid Benefit if eligible | Evaluation license start, then BYOL or Raff licensing path | | Support model | Azure support plans and Microsoft ecosystem | Windows-focused Raff support | | Complexity | More components: resource group, VNet, NSG, disk, NIC, public IP, monitoring | Simpler VM-first model | | Best buyer | Enterprise cloud team | SMB, MSP, developer, founder, IT lead | The strongest difference is not “can both run Windows?” Both can. The difference is how much platform complexity and billing variability you want around that Windows Server. ## Cost model: what you actually pay for A fair Azure vs Raff comparison should not compare only the VM label. ![Azure VM vs Raff Windows VPS cost model comparison showing Azure compute, Windows license, disk, public IP, egress, backup, monitoring, and support compared with Raff VM-first pricing, included storage, public IP, and unmetered bandwidth.](https://raff-images.s3.raffusercloud.com/azure_vm_vs_raff_windows_vps_cost_model_png_6f349564c1.png) For a Windows VM on Azure, the real monthly cost can include: * compute; * Windows Server operating system cost unless Azure Hybrid Benefit applies; * managed disk; * public IP; * outbound internet data transfer; * backup storage; * monitoring/logging; * snapshots; * support plan; * additional security or management services. For Raff Windows VPS, the cost model is simpler: * VM plan; * included compute, RAM, and storage allocation; * included public IP; * unmetered bandwidth; * Windows licensing path; * optional backup/snapshot storage; * optional migration/support services depending on the case. That does not mean Raff replaces every Azure feature. It means the VM bill is easier to understand when the workload is mostly a Windows Server. ## Why we should avoid one stale Azure price Azure prices change by: * region; * VM family; * operating system; * reservation term; * savings plan; * Azure Hybrid Benefit eligibility; * disk type and size; * public IP type; * backup retention; * outbound data transfer; * support plan. That makes a single hardcoded “Azure costs X” number risky. A better article structure is: ```text Use a cost model. Show the cost components. Tell readers how to verify current rates. Explain when Azure optimization changes the answer. ``` The article can still be commercially strong without pretending one Azure price is universal. ## Azure cost components explained ## Compute Azure bills virtual machine compute based on VM size, operating system, region, and purchase model. Pay-as-you-go is the simplest but usually the most expensive. Azure can become more competitive when you use: * reservations; * savings plans; * Azure Hybrid Benefit; * right-sizing; * auto-shutdown for dev/test; * spot VMs for interruptible workloads. For always-on SMB Windows workloads, many buyers use pay-as-you-go because it is easiest to understand. That is usually where Azure looks expensive compared with a fixed-price VPS. ## Windows Server licensing Azure Windows VMs include Windows Server licensing in the Windows VM price unless you apply Azure Hybrid Benefit. Azure Hybrid Benefit can reduce Windows VM cost, but it is not automatic “free savings.” To use Azure Hybrid Benefit for Windows Server, you need qualifying Windows Server licenses with active Software Assurance or qualifying subscription licenses. Microsoft also requires enough eligible core licenses, with a minimum of 8 core licenses per VM. That means the right question is: ```text Do we already own eligible Windows Server licenses with active Software Assurance or subscription coverage? ``` If yes, Azure may become more cost-competitive. If no, Azure pay-as-you-go Windows pricing is the realistic comparison. ## Disk Azure VM disks are separate managed resources. The OS disk and data disks can affect cost depending on: * disk type; * disk size; * performance tier; * redundancy option; * snapshots; * backup strategy. For simple Windows VPS buyers, this is often surprising. They think they are buying “a VM,” but the bill also includes managed disk resources. With Raff, storage is included in the VM plan, and backup/snapshot storage can be planned separately. ## Bandwidth and egress Bandwidth is one of the biggest differences. Azure inbound data transfer is generally free, but outbound internet data transfer is metered after the monthly free allowance. Azure’s bandwidth pricing table includes the first 100 GB per month free, then per-GB pricing by source continent and tier. This matters for workloads like: * backup downloads; * large file transfers; * RDP-heavy usage; * web apps serving files; * SQL exports; * offsite replication; * media or document downloads; * migration out of Azure. Raff’s model is simpler for buyers who want predictable bandwidth cost: plans include unmetered bandwidth. ## Public IP and network resources Azure VM networking is powerful but more complex. A typical Azure VM may involve: * virtual network; * subnet; * network security group; * network interface; * public IP; * route table; * Bastion or VPN if used. This flexibility is useful for enterprise architecture. For a small business that wants “a Windows Server I can RDP into,” it can be more setup than necessary. Raff keeps the first-server experience simpler. ## Backups and snapshots Azure has strong backup and recovery services, but they are separate services with their own configuration and cost model. Raff also supports snapshots and backups, but the VPS buyer usually thinks in a simpler model: ```text VM plan + backup/snapshot retention. ``` For either provider, the important rule is the same: ```text Snapshots are not a full backup strategy. Backups must be scheduled, monitored, and restore-tested. ``` ## Where Azure wins Azure is the better choice when the VM is only one piece of a larger Azure architecture. ## Azure-native services Choose Azure if your workload depends on: * Azure SQL Database; * Azure Functions; * Azure Logic Apps; * Azure Service Bus; * Azure App Service; * Azure Storage; * Azure Monitor; * Azure Backup; * Microsoft Defender for Cloud; * Microsoft Sentinel; * Azure Policy; * Azure Arc; * Entra ID integrations. If these services are central to the workload, moving to a normal VPS would require replacing platform capabilities with self-managed alternatives. That may not be worth it. ## Enterprise identity and governance Azure is strong when the organization already uses: * Entra ID; * Conditional Access; * Microsoft Defender; * Azure Policy; * Azure Monitor; * centralized RBAC; * enterprise compliance workflows; * centralized billing and cost management. For enterprise IT teams, Azure’s governance model can be more important than VM price. ## Global regions and data residency Azure has broad global infrastructure and region options. If the workload needs a specific geography, data residency requirement, sovereign cloud, or global deployment pattern, Azure may be the correct platform. A focused Windows VPS provider cannot replicate Azure’s global footprint. ## Managed alternatives to VMs Sometimes the best Azure answer is not an Azure VM. For example: * use Azure SQL instead of self-managing SQL Server; * use App Service instead of IIS on a VM; * use Azure Files instead of a Windows file server; * use Azure Virtual Desktop for enterprise desktop virtualization; * use Functions for event-driven automation. If you are willing to redesign around managed services, Azure can reduce operational work. If you only lift-and-shift a Windows VM, you still manage the OS and app. ## Where Raff wins Raff wins when the workload is a straightforward Windows Server workload. ## Predictable monthly planning Raff is easier to explain to SMB buyers: ```text Choose a Windows VPS plan. Deploy the server. Connect over RDP. Run the software. Know the monthly baseline. ``` Azure can be optimized, but the buyer has to understand the optimization levers. For many SMBs, predictable is better than theoretically flexible. ## Unmetered bandwidth For workloads with file movement, backups, RDP usage, exports, or client downloads, unmetered bandwidth matters. Azure outbound bandwidth can become a hidden cost if the workload moves more data than expected. Raff’s unmetered bandwidth model makes the bill easier to forecast. ## Simpler Windows Server experience Many SMB workloads do not need a full hyperscale cloud architecture. They need: * Windows Server; * RDP; * full admin access; * stable compute; * enough RAM; * NVMe storage; * backups; * firewall rules; * support when Windows breaks. Raff is designed around that simpler model. ## Windows-focused support Azure support covers a massive platform. Raff support is narrower and more focused on Windows VPS workloads such as: * RDP access; * IIS; * SQL Server; * Active Directory; * business apps; * Windows Server version choice; * migration planning; * firewall configuration; * performance troubleshooting. For small teams without a dedicated cloud architect, that can be more valuable than a bigger platform catalog. ## Easier migration for pure VM workloads If the Azure environment is just: ```text Windows VM Managed disk Public IP NSG rule RDP Installed business software ``` then migration to Raff is usually practical. If the environment also uses Azure SQL, Functions, Service Bus, Private Endpoints, Azure Monitor dashboards, Sentinel, and Entra-integrated governance, migration becomes a redesign project. ## Where they tie For a self-managed Windows Server VM, many responsibilities are similar. Both Azure VM and Raff Windows VPS can run: * RDP; * IIS; * ASP.NET; * SQL Server; * Active Directory Domain Services; * DNS; * file shares; * scheduled tasks; * PowerShell; * Windows Firewall; * business applications. In both cases, you are responsible for: * Windows updates; * application updates; * user access; * firewall rules; * backup strategy; * restore testing; * installed software; * database maintenance; * monitoring; * security hardening. This is an important point. Azure VM is IaaS. A Raff Windows VPS is also IaaS. The provider manages the physical infrastructure. You still manage the guest OS and what you install on it. ## The biggest mistake: comparing Azure platform to a VPS The wrong comparison is: ```text Azure as a full cloud platform vs Raff as one VM ``` Azure will always win that comparison because Azure is much broader. The right comparison is: ```text Azure Windows VM for a pure VM workload vs Raff Windows VPS for the same Windows Server workload ``` For pure VM workloads, Raff is usually the cleaner choice. For platform-integrated workloads, Azure often wins. ## Example workload: small business Windows app Scenario: ```text A 12-person company runs a Windows-only business app. Users connect over RDP. The app uses SQL Server Express or Standard. The server needs backups. No Azure-native services are used. ``` Better fit: ```text Raff Windows VPS ``` Why: * simple RDP access; * predictable cost; * Windows-focused support; * no Azure egress surprise; * no need for Azure-native architecture; * easier for SMB operators to understand. ## Example workload: Azure-native SaaS backend Scenario: ```text A SaaS app runs on Azure App Service. Database is Azure SQL. Authentication uses Entra ID. Background jobs use Azure Functions. Monitoring uses Azure Monitor. ``` Better fit: ```text Azure ``` Why: * workload depends on Azure-native services; * migration would require redesign; * managed services reduce operations; * enterprise governance may already exist. ## Example workload: SQL Server on Windows VM Scenario: ```text A team runs SQL Server on a Windows VM. The app server connects to it. Backups are self-managed. No Azure SQL features are used. ``` Better fit depends on architecture. Choose Raff if: * you want lower VM complexity; * you can self-manage SQL Server; * traffic is mostly in one region; * bandwidth predictability matters; * you do not need Azure-native governance. Choose Azure if: * you need Azure Backup / Monitor / Defender / Policy; * you already use Azure networking; * the team has Azure operations experience; * the database will later move to Azure SQL. ## Example workload: RDS / multi-user desktop Scenario: ```text A business wants several users to access the same Windows desktop environment over Remote Desktop. ``` Better fit: ```text Usually Raff for SMB RDS-style workloads. Azure for enterprise AVD-style workloads. ``` Raff is better when the business wants a simpler Windows Server/RDS setup. Azure is better when the organization wants Azure Virtual Desktop, Entra integration, enterprise identity controls, and large-scale desktop management. ## Migration path: Azure VM to Raff Windows VPS If the Azure workload is a pure Windows VM, the migration path is usually straightforward. ## Step 1 — Inventory Azure resources Document: * VM size; * Windows Server version; * attached disks; * public IP; * private IP; * NSG rules; * installed software; * local users; * domain membership; * scheduled tasks; * SQL Server instances; * IIS sites; * Windows services; * backup jobs; * data paths; * external integrations. Do not migrate blindly. ## Step 2 — Identify Azure dependencies Before leaving Azure, confirm whether the server depends on: * Azure SQL; * Azure Storage; * Azure Files; * Entra ID; * Azure Backup; * Azure Monitor; * Private Endpoints; * Azure Key Vault; * Service Bus; * Functions; * Logic Apps; * Azure Arc; * Defender for Cloud. If the VM is tightly integrated with Azure services, migration needs a redesign plan. ## Step 3 — Build the Raff destination Create a Raff Windows VPS with: * matching or better CPU/RAM; * enough storage; * same Windows Server version or planned upgrade target; * firewall rules; * RDP access; * backup/snapshot strategy; * private networking if multiple servers are involved. ## Step 4 — Migrate application and data Depending on workload, use: * file copy; * backup and restore; * SQL Server backup/restore; * application vendor migration tool; * VHD-based method; * third-party migration tool; * side-by-side install. For business applications, vendor-supported migration is usually safer than disk cloning. ## Step 5 — Test before cutover Test: * RDP login; * application launch; * user access; * database connectivity; * printing; * scheduled tasks; * firewall rules; * DNS; * backups; * restore process; * external integrations. Do not cut over because the server boots. Cut over when the business workflow works. ## Step 6 — Cut over with rollback During cutover: * stop writes on the Azure VM; * take final backup; * migrate final data; * update DNS or shortcuts; * test users; * monitor logs; * keep Azure VM available temporarily as rollback. A clean migration keeps the old environment accessible until the new one is proven. ## Common misconceptions ## “Azure VM means Microsoft manages my Windows Server” Not fully. Azure manages the underlying physical cloud infrastructure. For IaaS virtual machines, you still manage the operating system, applications, configuration, users, and much of the security posture. An Azure VM is not the same as Azure SQL, App Service, or Microsoft 365. ## “Azure Hybrid Benefit is automatic” No. Azure Hybrid Benefit requires eligible Windows Server licenses with active Software Assurance or qualifying subscription coverage. You also need enough eligible core licenses and must maintain compliance. If you do not already have the right licenses, do not assume the discounted Azure price applies. ## “Egress does not matter” It often does. Many Windows workloads move data through: * backups; * RDP file copy; * reports; * SQL exports; * file shares; * document downloads; * offsite replication; * migration. Azure outbound internet transfer can affect the bill. Raff’s unmetered bandwidth makes this easier to plan. ## “Azure is always more reliable because it is hyperscale” Azure has massive infrastructure, but single-VM reliability still depends on architecture. A single Azure VM is still a single VM. High availability usually requires designing across zones, sets, replication, backups, load balancing, and application-level resilience. The same principle applies anywhere: reliability is architecture, not just provider size. ## “Raff replaces Azure” Not for every workload. Raff is a better fit for focused Windows VPS workloads. Azure is a better fit for platform-heavy cloud architecture. The goal is not to claim Raff replaces Azure entirely. The goal is to help buyers stop overpaying for Azure when all they need is a Windows Server. ## Decision checklist Choose Raff Windows VPS if most of these are true: * the workload is a Windows VM; * users connect over RDP; * the app is self-managed; * no Azure-native services are required; * predictable monthly cost matters; * outbound bandwidth matters; * the buyer is an SMB or MSP; * the team wants Windows-focused support; * the server runs business software, IIS, SQL Server, ERP, accounting, or RDS-style access. Choose Azure if most of these are true: * the workload depends on Azure SQL or other Azure managed services; * the organization uses Entra ID and Azure governance deeply; * global regions or specific data residency are required; * the workload needs Azure-native monitoring/security/compliance workflows; * the team already has Azure operations expertise; * reservations, savings plans, and Hybrid Benefit are already part of the cost strategy; * the VM is part of a broader Azure architecture. ## Our recommendation For most SMB Windows Server workloads, choose Raff. That includes: * accounting software; * ERP; * SQL Server on a VM; * IIS / ASP.NET; * RDP access; * file-based business apps; * Active Directory labs or small deployments; * legacy Windows software; * remote desktop for small teams. For enterprise cloud architecture, choose Azure. That includes: * Azure SQL; * Azure Functions; * Azure Virtual Desktop; * Entra-heavy identity models; * Microsoft Sentinel; * Azure Policy; * Azure Government / sovereign requirements; * global multi-region design; * large enterprise governance. The most practical test: ```text List the Azure services your workload actually uses. If the list is mostly “Virtual Machine, disk, public IP, RDP,” Raff is probably the better fit. If the list includes Azure SQL, Functions, Service Bus, Entra, Monitor, Sentinel, Policy, or regional compliance requirements, Azure may be the right platform. ``` ## Verify pricing before you decide Cloud prices change. Verify the comparison on the same day you make the decision, using: * Azure Pricing Calculator; * Azure Windows Virtual Machines pricing page; * Azure Bandwidth pricing page; * Azure Hybrid Benefit eligibility rules; * current Raff pricing page. Suggested comparison scenario: ```text Region: East US VM: 4 vCPU / 8 GB Windows Server Runtime: 730 hours/month Disk: 120–128 GB SSD equivalent Bandwidth: 500 GB outbound/month Public IP: static Backup: enabled Support: note separately Purchase model: pay-as-you-go first, then reservation + Hybrid Benefit as optimized Azure case ``` Do not publish one Azure number without the date, region, VM family, disk type, bandwidth assumption, and licensing assumption. ## What's next * Connect to a Raff Windows VPS via RDP. * Compare Windows Server 2019, 2022, and 2025 before choosing your OS. * Review RDS CAL licensing before giving multiple users Remote Desktop access. * Install SQL Server 2025 on a Windows Server VPS. * Read the ERP on Windows VPS guide if you are migrating business software. * Review Active Directory topology if you are moving domain controllers. ## Sources * Microsoft Azure — Windows Virtual Machines pricing * Microsoft Azure — Bandwidth pricing * Microsoft Learn — Azure Hybrid Benefit for Windows Server * Microsoft Learn — Shared responsibility in the cloud * Microsoft Azure — Azure geographies * Raff — Windows VPS product page * Raff — Pricing page * Date last verified: 2026-07-06 --- ### Azure Virtual Desktop Alternative: Raff Windows VPS/RDP for Small Businesses URL: https://rafftechnologies.com/windows-server/azure-virtual-desktop-alternative Description: Learn when Raff Windows VPS/RDP is a simpler Azure Virtual Desktop alternative for small businesses that need remote users, Windows apps, shared files, backups, and office server migration. Raff Windows VPS/RDP is a simpler Azure Virtual Desktop alternative for small businesses that do not need full virtual desktop infrastructure. If your team mainly needs secure remote access to Windows apps, shared files, accounting software, legal files, tax software, ERP tools, Microsoft Access, or an old office server replacement, a Raff Windows VM can be the more direct path. Azure Virtual Desktop is powerful when you need full VDI, Windows 10/11 multi-session desktops, host pools, RemoteApp publishing, and Azure-native desktop management. This article is not a general Azure VM comparison. Raff already has a separate Azure VM alternative article for that. This guide answers a more specific Windows Hub question: **Can a small business use Raff Windows VPS/RDP instead of Azure Virtual Desktop when it only needs remote access to Windows apps and files?** For many SMBs, the answer is yes. :::cta Explore Windows VM Use Raff Windows VM when your business needs a cloud-hosted Windows Server for remote access, apps, files, and shared workloads. ::: ## The real problem: most SMBs do not need full VDI Many small businesses search for Azure Virtual Desktop because they need remote work. But the actual need is often much simpler: | What the buyer says | What they usually mean | |---|---| | We need Azure Virtual Desktop | Staff need remote access to Windows apps | | We need cloud desktop | Users need the same apps and files from home | | We need VDI | We are tired of remoting into office PCs | | We need RemoteApp | Users need one or two business apps | | We need Azure remote desktop | Our old office server is hard to access | | We need secure remote access | RDP/VPN/workstation access is messy | Azure Virtual Desktop may solve those problems, but it may also introduce more platform than the business needs. If the business does not need host pools, Windows 10/11 multi-session desktops, image management, FSLogix profile strategy, RemoteApp publishing, and Azure-native governance, a Windows VPS/RDP model can be simpler. ## What Raff Windows VPS/RDP gives small businesses Raff Windows VM gives small businesses a cloud-hosted Windows Server environment that users can access with Remote Desktop. That means your team can run Windows-based workloads in one central place instead of depending on individual office PCs or local servers. | Raff Windows VPS/RDP feature | Why it matters for SMBs | |---|---| | Windows Server 2019, 2022, and 2025 options | Choose the Windows Server version your apps support. | | Full administrator access | Install supported apps, configure roles, manage users, and control the server. | | RDP-ready access | Users and admins can connect to the Windows environment remotely. | | Fast deployment | Start testing without waiting for physical hardware. | | AMD EPYC processors and NVMe SSD storage | Gives business apps a strong infrastructure foundation. | | Unmetered bandwidth | Helps avoid surprise bandwidth bills for normal SMB usage. | | 99.9% uptime SLA | Useful for teams relying on the server for daily access. | | 24/7 support | Important when RDP, Windows, or app access affects business work. | | Backups and snapshots | Helps protect the server before changes, migration, and production use. | | Private networking and DDoS protection | Useful when designing safer business infrastructure. | | API and Terraform support | Helpful for MSPs and technical teams managing repeatable environments. | The point is not that Raff Windows VPS has every AVD feature. It does not. The point is that many small businesses do not need every AVD feature. They need a reliable Windows Server they can connect to, manage, back up, and use for business workloads. ## Azure Virtual Desktop is powerful, but it is a different product Azure Virtual Desktop is Microsoft’s desktop and app virtualization service on Azure. It can deliver full desktops and remote applications, including Windows 10/11 multi-session experiences. That is useful when the business needs a true VDI platform. AVD can involve: | AVD component | What it means | |---|---| | Host pools | Groups of session hosts that deliver desktops or apps | | Session hosts | Virtual machines that run user sessions | | Application groups | Published desktops or RemoteApps | | Workspaces | User-facing organization of resources | | User profiles | Often requires profile-container planning | | Azure identity and networking | Entra ID, AD DS, Azure networking, and access design | | Scaling plans | Capacity management for changing user demand | | Image management | Standardized desktop/app images | | Azure monitoring and governance | Operational management inside Azure | That is valuable for the right organization. But it can be too much platform for a small business that only needs a Windows Server environment for apps, files, and RDP access. ## When Raff Windows VPS/RDP is the smarter path Raff Windows VPS/RDP is usually the better starting point when the business needs a practical cloud Windows Server. ![Comparison visual showing a complex cloud server setup versus a simpler Windows VPS RDP path for small business remote access, Windows apps, shared files, backups, and storage](https://raff-images.s3.raffusercloud.com/simpler_windows_server_path_windows_vps_rdp_9eda30b9ec.png) | Business need | Why Raff Windows VPS/RDP fits | |---|---| | Remote employees need Windows apps | Users connect to one hosted Windows environment. | | Business apps run on Windows Server | The VM becomes the app environment. | | Shared folders and mapped drives matter | Use Windows Server file shares and permissions. | | Old office server needs replacement | Move to a cloud Windows Server model. | | Accounting or legal teams need central files | Keep apps, files, reports, and backups in one environment. | | MSP needs repeatable client setup | Standardize client Windows environments. | | Small team needs predictable infrastructure | VM pricing is easier to understand than full AVD design. | | Migration needs to be simple | Build, test, sync, cut over, and keep rollback ready. | The practical rule: **If you need a cloud Windows Server, use Windows VPS. If you need full desktop virtualization, evaluate AVD.** ## When Azure Virtual Desktop is still the better fit Be honest about the boundary. Azure Virtual Desktop is better when the business actually needs VDI. Choose AVD when you need: | Requirement | Why AVD fits | |---|---| | Windows 10/11 multi-session desktop | AVD is built for this scenario. | | Full virtual desktop infrastructure | Host pools, session hosts, workspaces, and app groups are native. | | RemoteApp publishing at scale | AVD is designed for app/desktop delivery. | | Enterprise desktop governance | Azure-native management can be valuable. | | Large desktop fleet | AVD scales for broader desktop strategies. | | Standardized desktop images | Image management is part of the VDI model. | | Mature Azure operations team | More moving parts are easier to operate. | | Existing AVD architecture | Staying with AVD may be better than rebuilding. | Raff Windows VPS is not a full AVD replacement for enterprise desktop virtualization. It is a simpler alternative for SMBs that never needed full VDI. ## Raff Windows VPS/RDP use cases ### Remote employees Remote employees often need access to Windows apps, shared files, and reports. They do not always need a full virtual desktop platform. A Raff Windows VM can give remote staff a central environment for: | Need | Example | |---|---| | Windows apps | Accounting, ERP, Access, legal, tax, or legacy apps | | Shared files | Department folders, client files, project folders | | Reports | PDFs, Excel exports, app reports | | Remote access | RDP/RDS-style access planning | | Backups | VM, file, app, and snapshot protection | | MSP support | Central server instead of many office PCs | Read next: [Windows VPS for Remote Employees](https://rafftechnologies.com/windows-server/windows-vps-remote-employees). ### Accounting firms Accounting firms often compare VDI tools because staff need access to QuickBooks, Sage, tax software, client folders, PDFs, and reports. For many accounting firms, Raff Windows VPS/RDP is a cleaner starting point: | Accounting need | Raff Windows VPS/RDP fit | |---|---| | QuickBooks Desktop | Central Windows environment after licensing/vendor checks | | Sage 50/100/300 | Sized Windows Server environment | | Tax software | Seasonal remote users and client files | | Client folders | Centralized file structure and permissions | | Backups | Protect app data, files, and server state | | Remote staff | Access from home or branch office | Read next: [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms). ### Law firms Law firms need controlled access to case files, legal apps, scanned documents, templates, billing exports, and PDFs. A Raff Windows VM can help when: | Law firm need | Raff Windows VPS/RDP fit | |---|---| | Case files | Central shared folders with permissions | | Legal apps | Hosted Windows Server environment where supported | | Remote attorneys/paralegals | Access through a planned remote model | | Confidential files | Named users and access groups | | Backups | Restore planning for case files and app data | | Office server replacement | Move away from local hardware dependency | Read next: [Windows VPS for Law Firms](https://rafftechnologies.com/windows-server/windows-vps-law-firms). ### File server replacement Some buyers think they need AVD, but the real requirement is a cloud file server. A Raff Windows VM can work as a cloud file server when users access files through Remote Desktop, RD Gateway, VPN/private access, or another controlled model. | File server need | Raff Windows VPS/RDP fit | |---|---| | Shared folders | Central location for business files | | NTFS permissions | Users and groups | | Mapped drives | Familiar Windows workflow | | Remote access | Access inside the hosted session | | Backups | File-level and VM-level protection | | Migration | Move from old local server to cloud Windows Server | Do not expose SMB directly to the public internet. Read next: [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server). ### MSP client environments MSPs often need repeatable Windows environments for different clients. Raff Windows VPS/RDP can help MSPs standardize: | MSP need | Raff fit | |---|---| | One server per client | Cleaner isolation and documentation | | Remote users | Planned RDP/RDS/RD Gateway model | | Client apps | Install supported Windows apps | | Backups | Standard backup/snapshot process | | Migration | Build, test, cut over, rollback | | Support | Central environment instead of many PCs | Read next: [Windows VPS for MSP Client Environments](https://rafftechnologies.com/windows-server/windows-vps-for-msp-client-environments). :::cta Talk to Windows Engineer Review remote users, apps, files, RDS licensing, backups, migration scope, and whether your business needs Windows VPS or full VDI. ::: ## Simple Raff Windows VPS/RDP architecture For many SMBs, the architecture can be simple. ```text Remote users ↓ Secure access model RDP / RDS / RD Gateway / VPN ↓ Raff Windows VM ↓ Windows apps + shared files + reports ↓ Backups + snapshots + restore planning ``` The important part is not only the VM. It is the whole operating model. Plan: | Layer | What to decide | |---|---| | Users | Who connects and from where? | | Access | Admin RDP, RDS Session Host, RD Gateway, VPN, or RemoteApp-style use? | | Apps | Which Windows apps will run? Are they supported? | | Files | Which folders move? What permissions apply? | | Licensing | Windows, RDS CALs, SQL Server, app licenses, Microsoft 365 Apps | | Security | Firewall, user accounts, offboarding, logs, passwords | | Backups | VM backup, file backup, app/database backup, snapshots | | Migration | Test copy, user testing, cutover, rollback | | Support | Who owns Windows, app, user, and backup issues? | This is the difference between “just opening RDP” and running a real remote business environment. ## RDP, RDS, and licensing still matter A Windows VPS with RDP access does not automatically mean unlimited staff desktop sessions. There are different access models: | Access model | Best fit | |---|---| | Admin RDP | One or two administrators managing the server | | RDS Session Host | Multiple staff users need desktop/app sessions | | RD Gateway | Controlled access to RDS resources over the internet | | VPN/private access | Users connect privately before accessing internal services | | RemoteApp-style workflow | Users need specific apps rather than a full desktop | Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs a Remote Desktop Services Client Access License. Microsoft also explains that Azure Virtual Desktop licensing has eligible license requirements for users, depending on the scenario. Practical takeaway: **Raff provides the Windows VM infrastructure. The customer or MSP still needs to plan RDS CALs, app licenses, Microsoft licenses, and vendor support.** ## Why Raff Windows VPS/RDP can be easier to price Azure Virtual Desktop cost estimation can include Azure compute, session hosts, storage, user profiles, networking, monitoring, scaling choices, and eligible user licensing. Raff Windows VPS is usually easier for SMBs to budget because the core model starts with a Windows VM plan, then adds the workload decisions: users, storage, backups, application licenses, RDS CALs, and migration. | Pricing area | Raff Windows VPS/RDP approach | |---|---| | Base server | Choose a Windows VM plan | | Users | Size by active users and workload | | Storage | Plan files, profiles, apps, databases, and growth | | Bandwidth | Raff pricing page lists unmetered bandwidth on Cloud Server plans | | Backups/snapshots | Plan data protection before production | | Licensing | Review Windows, RDS, SQL, Microsoft 365 Apps, and app licenses | | Support | Include Windows/app/user support ownership | | Migration | Plan test migration, cutover, and rollback | Raff’s public Windows VM page lists Windows VPS hosting from $10.99/month, full admin access with RDP, Windows Server 2019/2022/2025 options, a 6-month Windows Server evaluation license to get started, 24/7 expert support, and a 99.9% uptime SLA. Check the live pricing page for current plan details before you commit. :::cta View Pricing Compare Raff Windows VM plans when weighing CPU, memory, storage, backups, and monthly cost against Azure Virtual Desktop complexity. ::: ## Feature checklist: why SMBs choose Raff Windows VPS/RDP Use this buyer checklist when comparing Raff Windows VPS/RDP with a bigger VDI platform. | Feature | Why it supports SMB remote access | |---|---| | Full admin access | Install and manage supported Windows apps | | RDP-ready server | Access the Windows environment remotely | | Windows Server version choice | Match app compatibility requirements | | AMD EPYC + NVMe SSD | Strong base for business apps and files | | Unmetered bandwidth | Reduces bandwidth surprise for normal use | | Private networking | Useful for multi-server or MSP designs | | DDoS protection | Helps protect public-facing infrastructure | | Backups and snapshots | Supports safer changes and recovery planning | | 24/7 support | Useful when Windows access affects business work | | 99.9% uptime SLA | Helps with daily operational confidence | | Fast deployment | Start testing without physical hardware | | API/Terraform support | Helpful for technical teams and MSPs | The best feature is not one checkbox. It is the combination of simple Windows access, practical pricing, business-app fit, and a supportable migration path. ## Sizing Raff Windows VPS/RDP for remote users Do not size by employee count only. Size by concurrent users and workload. | Workload | Starting point | When to move up | |---|---:|---| | 1-2 admins or light users | 2 vCPU / 4 GB RAM | If users run apps or reports | | 3 light remote users | 4 vCPU / 8 GB RAM | If users open Office apps, PDFs, or browsers | | 3-5 active business app users | 4 vCPU / 16 GB RAM | Better for accounting, legal, tax, ERP, Access, or legacy apps | | 5-10 active users | 8 vCPU / 32 GB RAM | If the VPS becomes a daily shared workspace | | App plus SQL/database workload | 8-16 vCPU / 32-64 GB RAM | Consider separating app and database roles | | File-heavy team | Size storage first | Files, profiles, exports, scans, and growth matter | Read next: [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users). ## Security planning before using Raff as an AVD alternative A simpler platform does not mean careless setup. Minimum security plan: | Security area | Recommendation | |---|---| | Named users | Avoid shared accounts | | Admin separation | Separate admin and daily user accounts | | RDP exposure | Avoid broad direct exposure | | RD Gateway/VPN | Use controlled access where appropriate | | Firewall rules | Restrict allowed sources and ports | | Permissions | Use groups and least privilege | | Local redirection | Control drive, clipboard, and printer redirection where needed | | Backups | Protect backups from deletion or ransomware | | Updates | Patch Windows and apps deliberately | | Logs | Review failed sign-ins and unusual activity | | Offboarding | Remove access quickly when users leave | Read next: - [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) - [Windows Server Hardening Checklist](https://rafftechnologies.com/windows-server/windows-server-hardening-checklist) ## Migration path from office server or office PCs Many SMBs considering Azure Virtual Desktop are really trying to escape old office infrastructure. A simpler Raff Windows VPS migration path: 1. Inventory users, apps, files, databases, printers, scanners, and integrations. 2. Confirm app vendor support for Windows Server/RDS or hosted use. 3. Choose the Windows VM size. 4. Build the Raff Windows VM. 5. Configure users, firewall, access model, and backups. 6. Install Windows apps and dependencies. 7. Copy test data first. 8. Test real user workflows. 9. Test printing, PDFs, reports, file paths, and database access. 10. Run a restore test. 11. Schedule cutover outside critical work hours. 12. Move final data. 13. Keep the old environment available for rollback. 14. Monitor performance and support tickets after cutover. Read next: - [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) - [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) - [File Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps) ## When Raff Windows VPS is not the right AVD alternative Raff Windows VPS/RDP is strong for SMB Windows Server workloads, but it is not right for every AVD search. Do not use Raff Windows VPS as an AVD alternative when: | Requirement | Better fit | |---|---| | Windows 10/11 multi-session desktop is mandatory | Azure Virtual Desktop | | Enterprise VDI is the actual project | Azure Virtual Desktop | | Host pools, app groups, and image management are required | Azure Virtual Desktop | | RemoteApp publishing at scale is central | Azure Virtual Desktop | | Azure-native governance is mandatory | Azure Virtual Desktop | | Large desktop fleet management is required | Azure Virtual Desktop | | Internal IT already has a mature AVD environment | Azure Virtual Desktop may be better | This honesty helps the right buyer trust the recommendation. ## How Raff fits Raff fits small businesses that need remote Windows access without building a full Azure Virtual Desktop environment. Use Raff Windows VPS/RDP when your business wants: - Windows Server in the cloud; - full admin access; - RDP-ready access; - remote employees; - accounting, legal, tax, ERP, Access, and legacy apps; - shared files and folders; - office server replacement; - simpler pricing; - backup and snapshot planning; - a realistic migration path. Raff does not replace Azure Virtual Desktop for enterprise VDI. Raff is the simpler Windows VPS/RDP path when your SMB needs a reliable cloud Windows Server for apps, files, users, and backups. :::cta Deploy Windows Now Create a Raff Windows VM when your business is ready to run remote users, Windows apps, shared files, and SMB workloads in the cloud. ::: ## Recommended path by situation | Situation | Read next | |---|---| | You need the SMB buyer guide | [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) | | You need remote staff access | [Windows VPS for Remote Employees](https://rafftechnologies.com/windows-server/windows-vps-remote-employees) | | You need a Remote Desktop business guide | [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) | | You need secure RDP planning | [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) | | You need pricing clarity | [Windows VPS Pricing Explained](https://rafftechnologies.com/windows-server/windows-vps-pricing-explained) | | You need shared files | [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) | | You are replacing office hardware | [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) | | You are migrating from local server | [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) | | You are comparing Azure VM cost | [Azure VM Alternative: Raff Windows VPS](https://rafftechnologies.com/windows-server/azure-comparison) | | You are comparing dedicated hardware | [Windows VPS vs Dedicated Server](https://rafftechnologies.com/windows-server/windows-vps-vs-dedicated-server) | ## Final checklist: should you use Raff Windows VPS/RDP instead of AVD? Before deciding, answer: | Question | Answer | |---|---| | Do users need Windows 10/11 virtual desktops? | ☐ | | Do users need full VDI with host pools and app groups? | ☐ | | Do users mainly need Windows Server apps and files? | ☐ | | Are you replacing an old office server or office PC access model? | ☐ | | Which business apps will run? | ☐ | | Does the app vendor support Windows Server/RDS or hosted use? | ☐ | | How many active users will connect? | ☐ | | Are RDS CALs required? | ☐ | | Are app licenses separate? | ☐ | | How much storage and growth are expected? | ☐ | | Are backups and snapshots planned? | ☐ | | Has restore testing been planned? | ☐ | | Is secure access planned? | ☐ | | Who supports the Windows server and apps? | ☐ | | What is the migration and rollback plan? | ☐ | If the answer is mostly “we need apps, files, remote access, and an office server replacement,” Raff Windows VPS/RDP is probably the simpler path. ## What's next - Explore [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) when you are ready to compare Windows VM options. - Review [Raff pricing](https://rafftechnologies.com/pricing) before choosing CPU, RAM, storage, and monthly cost. - Read [Windows VPS for Remote Employees](https://rafftechnologies.com/windows-server/windows-vps-remote-employees) if remote work is the main driver. - Read [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) before rolling out staff access. - Read [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) for the broader SMB decision guide. - Read [Azure VM Alternative: Raff Windows VPS](https://rafftechnologies.com/windows-server/azure-comparison) if you are comparing Azure Windows VM pricing and infrastructure. ## Sources - Microsoft Learn — [Azure Virtual Desktop documentation](https://learn.microsoft.com/en-us/azure/virtual-desktop/) - Microsoft Learn — [What is Azure Virtual Desktop?](https://learn.microsoft.com/en-us/azure/virtual-desktop/overview) - Microsoft Learn — [Licensing Azure Virtual Desktop](https://learn.microsoft.com/en-us/azure/virtual-desktop/licensing) - Microsoft Learn — [Understand and estimate costs for Azure Virtual Desktop](https://learn.microsoft.com/en-us/azure/virtual-desktop/understand-estimate-costs) - Microsoft Azure — [Azure Virtual Desktop pricing](https://azure.microsoft.com/en-us/pricing/details/virtual-desktop/) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) - Raff — [Windows Server Hub](https://rafftechnologies.com/windows-server) - Raff — [Azure VM Alternative: Raff Windows VPS](https://rafftechnologies.com/windows-server/azure-comparison) --- ### Windows VPS vs Dedicated Server: Which Is Better for Small Businesses? URL: https://rafftechnologies.com/windows-server/windows-vps-vs-dedicated-server Description: Compare Windows VPS and dedicated servers for small businesses. Learn which option fits Remote Desktop, business apps, file servers, backups, migration, pricing, support, and growth. A Windows VPS is usually the better first choice for small businesses that need Remote Desktop access, Windows apps, shared files, backups, office server replacement, or a cloud Windows Server environment without managing physical hardware. A dedicated server can make sense for very large, predictable, hardware-sensitive, or isolation-heavy workloads, but it usually adds more operational responsibility. Raff Technologies provides Windows VMs for teams that want a practical Windows Server foundation for remote users, business apps, files, and migration projects. The important question is not “which is more powerful?” The real question is: **Which option gives your business the right mix of performance, control, cost, flexibility, recovery, and support?** For many small businesses, the answer is Windows VPS first. It is faster to start, easier to resize, simpler to migrate into, and more aligned with common SMB workloads like Remote Desktop, QuickBooks, Sage, tax software, file shares, law firm case files, accounting firm apps, and remote employee access. A dedicated server is not wrong. It is just usually not the first infrastructure step a small business needs. :::cta Explore Windows VM Use Raff Windows VM when your business needs a cloud-hosted Windows Server for remote access, apps, files, and shared workloads. ::: ## Quick verdict: Windows VPS or dedicated server? Use this table as the short answer. | Situation | Better fit | Why | |---|---|---| | Small business needs Remote Desktop access | Windows VPS | Easier to launch, manage, and resize for users. | | Business apps need a Windows environment | Windows VPS | Practical for accounting, tax, ERP, Access, and legacy apps. | | Company is replacing an old office server | Windows VPS | Cloud server model removes physical office hardware dependency. | | Team needs shared files and backups | Windows VPS | Centralized file server and backup planning are easier to start. | | MSP needs repeatable client environments | Windows VPS | Easier to standardize per client. | | Workload needs full physical isolation | Dedicated server | Physical server control may matter. | | Workload uses sustained high CPU/storage I/O all day | Depends | Dedicated can fit, but high-spec VPS may also work. | | Business needs custom hardware or unusual network/storage setup | Dedicated server | Dedicated hardware offers more physical customization. | | Company wants lowest operational complexity | Windows VPS | Less hardware-level responsibility. | | Company has in-house server engineering | Dedicated server may fit | More responsibility is manageable with the right team. | For most SMB Windows workloads, start with a Windows VPS unless there is a clear reason to own or rent the full physical server. ## What is a Windows VPS? A Windows VPS is a virtual server running Windows Server. It gives you a cloud-hosted Windows environment with administrator access, Remote Desktop access, storage, networking, and the ability to install supported Windows applications. Businesses use a Windows VPS for: | Use case | Example | |---|---| | Remote Desktop | Staff connect to a shared Windows environment | | Business apps | QuickBooks, Sage, tax software, ERP, Access, legacy apps | | File server | Shared folders, mapped drives, client folders, reports | | Office server replacement | Move from old local hardware to cloud Windows Server | | SQL-backed apps | Application databases and reports | | MSP clients | Standardized environments for different customers | | Remote employees | Secure access to apps and shared files | | Migration staging | Test apps and files before cutover | A Windows VPS is not only a developer tool. For small businesses, it often becomes the central Windows environment for daily operations. ## What is a dedicated server? A dedicated server is a physical server assigned to one customer. The customer does not share the underlying physical machine with other tenants. Dedicated servers are commonly used when a workload needs: | Need | Why dedicated may fit | |---|---| | Full physical isolation | Entire server belongs to one customer | | Custom hardware | Specific CPU, disk, RAID, or network requirements | | Sustained heavy workloads | Predictable high load all day | | Large storage footprint | Many disks or large local storage pools | | Custom virtualization | Customer wants to run their own hypervisor | | Specific compliance architecture | Physical isolation may be required | | In-house server team | Business can manage more infrastructure responsibility | Dedicated servers can be powerful. But more control usually comes with more planning, management, and responsibility. ## Windows VPS vs dedicated server: core differences ![Comparison visual showing Windows VPS versus dedicated server for small business apps, remote users, files, backups, and hardware control](https://raff-images.s3.raffusercloud.com/windows_vps_vs_dedicated_server_comparison_webp_340b53eb09.png) | Area | Windows VPS | Dedicated server | |---|---|---| | Hardware | Virtualized server on cloud infrastructure | Entire physical server | | Setup speed | Usually faster | Usually slower | | Scaling | Resize or move plan more easily | Often requires hardware change or migration | | Cost model | Smaller starting point | Higher commitment | | Management | Less hardware responsibility | More hardware-level responsibility | | Isolation | Virtual isolation | Physical isolation | | Best for SMBs | Remote users, apps, files, migration | Heavy/custom/high-isolation workloads | | Migration | Easier to test and cut over | Often more involved | | Backup planning | VM/file/app backups | Full server + hardware-aware planning | | Support model | Cloud VM support | Server/hardware/network support | | Flexibility | Strong for changing needs | Strong for fixed known workloads | The dedicated server is not automatically “better.” It is better only when the workload actually benefits from physical hardware control. ## Which is better for Remote Desktop users? For most small businesses, a Windows VPS is the better starting point for Remote Desktop users. Why? | Remote Desktop need | Windows VPS advantage | |---|---| | Start with a few users | Smaller plan can be enough | | Add users over time | Resize before replacing hardware | | Remote employees | Hosted environment is not tied to office power/internet | | MSP support | Standardized VM environment is easier to document | | Backups | VM and file backup planning can be built in | | Migration testing | Build and test before moving users | | Cost control | Avoid overbuying dedicated hardware too early | A dedicated server can make sense when many users need sustained performance, the environment is large, or the business has a clear physical-isolation requirement. But for 3, 5, 10, or even many small-team Remote Desktop deployments, a Windows VPS is usually more practical to start. For deeper planning, read: - [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) - [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) - [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) - [RDS CAL Licensing on Windows Server](https://rafftechnologies.com/windows-server/rds-cal-licensing-guide) :::cta Talk to Windows Engineer Review user count, Remote Desktop access, RDS licensing, apps, files, backups, and migration scope before choosing between Windows VPS and dedicated server. ::: ## Which is better for business apps? Many small businesses compare Windows VPS and dedicated servers because they need to host business applications. Common workloads include: | Workload | Typical better starting point | |---|---| | QuickBooks Desktop | Windows VPS | | Sage 50/100/300 | Windows VPS, sized carefully | | Tax software | Windows VPS | | ERP/inventory software | Windows VPS or larger architecture | | Microsoft Access | Windows VPS | | Legacy Windows apps | Windows VPS after testing | | SQL-backed app | Depends on database size and load | | Heavy custom database | Depends; dedicated may fit | | Large multi-branch environment | Depends on architecture | A Windows VPS is usually enough when the app needs a reliable hosted Windows environment but does not require physical hardware control. A dedicated server may become relevant when: - the app has very high sustained CPU or disk I/O; - database size and usage are large; - the vendor recommends dedicated hardware; - the business needs full physical isolation; - the architecture requires custom storage or network design. For vertical use cases, read: - [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms) - [Windows VPS for Law Firms](https://rafftechnologies.com/windows-server/windows-vps-law-firms) - [Windows VPS for Tax Software](https://rafftechnologies.com/windows-server/windows-vps-tax-software) - [Windows VPS for ERP and Inventory Software](https://rafftechnologies.com/windows-server/windows-vps-erp-inventory-software) - [Windows VPS for Microsoft Access and Legacy Apps](https://rafftechnologies.com/windows-server/windows-vps-microsoft-access-legacy-apps) ## Which is better for file servers? For small-business file servers, Windows VPS is usually the better starting point. A Windows VPS can support: | File server need | Why Windows VPS fits | |---|---| | Shared folders | Central place for business files | | NTFS permissions | Use Windows groups and access rules | | Remote users | Users access files inside the Windows environment | | Client/case folders | Useful for accounting, legal, MSP, and service businesses | | Backups | File-level and VM-level backup planning | | Migration from office server | Test before cutover | | Multi-location access | Branches work from one environment | A dedicated server can make sense when the file workload is extremely large, local disk layout matters, or the business needs custom storage hardware. But most small-business file server needs start with structure, permissions, access model, and backups — not physical server ownership. Use: - [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) - [File Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps) ## Which is better for backups and recovery? Both Windows VPS and dedicated servers need backups. Cloud hosting does not remove backup responsibility. The practical difference is how much infrastructure the business must think about. | Recovery area | Windows VPS | Dedicated server | |---|---|---| | VM backup | Natural fit | Possible, but depends on setup | | Snapshot before change | Often easier in VM model | Depends on stack | | File-level restore | Required | Required | | Database backup | Required | Required | | Hardware failure planning | Provider abstracts more of it | Business/provider must plan server hardware risk | | Migration testing | Easier to clone/test in VM-style workflow | More involved | | Scaling recovery plan | Easier to adapt | More hardware-dependent | For small businesses, the winning model is the one that makes backups understandable, affordable, and tested. Use: [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business). :::cta Explore Data Protection Protect your Windows workload with backup, snapshot, and restore planning before choosing production infrastructure. ::: ## Pricing comparison: Windows VPS vs dedicated server Dedicated servers usually look attractive when comparing raw hardware. But small businesses should compare total operating cost, not only CPU and RAM. | Cost area | Windows VPS | Dedicated server | |---|---|---| | Starting cost | Usually lower | Usually higher | | Overbuying risk | Lower | Higher | | Scaling cost | More flexible | May require migration or hardware change | | Hardware responsibility | Lower | Higher | | Backup planning | Still required | Still required | | Support complexity | Lower for common SMB workloads | Higher if hardware/storage/network issues matter | | Migration effort | Usually easier | Usually more involved | | Idle capacity | Less waste if sized correctly | More likely if over-provisioned | | Long-term fixed heavy load | Can become expensive at high scale | Dedicated may become attractive | The dedicated server may win on raw power per dollar at larger, predictable workloads. The Windows VPS often wins for flexibility, speed, and lower operational burden. Use: [Windows VPS Pricing Explained](https://rafftechnologies.com/windows-server/windows-vps-pricing-explained). :::cta View Pricing Compare Raff Windows VM plans when weighing CPU, memory, storage, backups, and monthly cost against a dedicated server. ::: ## Security comparison Security depends more on design than on whether the server is VPS or dedicated. | Security area | Windows VPS | Dedicated server | |---|---|---| | User access | Must be managed | Must be managed | | RDP exposure | Must be restricted | Must be restricted | | Firewall rules | Required | Required | | Patching | Required | Required | | Backups | Required | Required | | Physical isolation | Virtual isolation | Physical isolation | | Operational simplicity | Usually easier for SMBs | More moving parts | | Compliance fit | Depends on requirements | Can fit physical isolation requirements | A dedicated server gives physical isolation, but that does not automatically make the workload secure. Weak passwords, exposed RDP, missing backups, poor patching, and shared accounts are still risks. Use: - [Windows Server Hardening Checklist](https://rafftechnologies.com/windows-server/windows-server-hardening-checklist) - [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) ## Migration comparison A Windows VPS is usually easier for small businesses moving from an office server. | Migration area | Windows VPS | Dedicated server | |---|---|---| | Test environment | Easy to build | More involved | | Start small | Easier | Less practical | | App testing | Straightforward | Straightforward, but more infrastructure commitment | | File migration | Good fit | Good fit | | SQL/app migration | Good fit if sized correctly | Good fit for heavy workloads | | Rollback planning | Easier with snapshots/backups | Depends on architecture | | Cutover | Flexible | More planning if hardware-specific | | Post-migration resizing | Easier | Harder | The safest migration pattern is usually side-by-side: 1. Build the new Windows environment. 2. Test apps, files, users, and backups. 3. Move data in stages. 4. Cut over after validation. 5. Keep rollback ready. Use: - [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) - [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) - [File Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps) ## Decision matrix Use this matrix when the choice is still unclear. ![Decision matrix visual showing when small businesses should choose Windows VPS or dedicated server](https://raff-images.s3.raffusercloud.com/smb_windows_infrastructure_decision_matrix_webp_2f12b5ce0e.png) | Question | If yes, lean Windows VPS | If yes, lean dedicated server | |---|---|---| | Do you need to start quickly? | Yes | Not the main factor | | Do you have under 10-20 active users? | Often yes | Rarely required | | Do you expect needs to change? | Yes | Not ideal | | Do you need physical isolation? | Not enough | Yes | | Do you need custom hardware? | No | Yes | | Is the workload business-app/RDP/file-server focused? | Yes | Only if very heavy | | Do you have in-house server engineering? | Not required | Helpful | | Is cost predictability important? | Yes | Depends | | Is raw sustained performance the main goal? | Depends | Often yes | | Are you replacing an old office server? | Usually yes | Only for large workloads | ## When to choose Windows VPS Choose Windows VPS when your small business needs: | Need | Why Windows VPS fits | |---|---| | Remote Desktop access | Easier to start and manage | | Business app hosting | Good fit for many Windows apps | | Cloud file server | Central folders, permissions, backups | | Office server replacement | Avoids physical office hardware dependency | | Remote employees | Centralized access model | | Accounting, legal, tax, ERP workflows | Practical Windows environment | | MSP client environments | Repeatable and standardized | | Migration testing | Build before cutover | | Predictable monthly infrastructure | Easier starting point | | Flexibility | Resize as needs change | Most small businesses should start here unless there is a clear reason not to. ## When to choose dedicated server Choose a dedicated server when the business has a specific reason, such as: | Need | Why dedicated may fit | |---|---| | Full physical isolation | Entire machine belongs to one customer | | Very large predictable workload | Hardware commitment may make sense | | Custom storage or RAID design | Dedicated hardware gives more control | | Custom virtualization layer | Business wants its own hypervisor | | High sustained database load | Dedicated hardware may be more cost-effective | | Compliance architecture requires physical separation | Dedicated can support that model | | In-house team can manage it | More responsibility is acceptable | A dedicated server should be a deliberate decision, not just the default because it sounds stronger. ## How Raff fits this comparison Raff fits small businesses that need a practical Windows VPS for Remote Desktop, business apps, file servers, accounting firms, law firms, tax software, ERP/inventory systems, remote employees, MSP client environments, and migration away from local office hardware. Raff Windows VM is the right direction when your business wants: - cloud-hosted Windows Server infrastructure; - full administrator access; - Remote Desktop access; - support for Windows-based workloads; - a simpler starting point than dedicated hardware; - clear monthly infrastructure planning; - room to grow before overcommitting to physical servers. Raff is not a dedicated server provider. That is the point: for many SMB Windows workloads, you do not need to start with dedicated hardware. You need the right Windows VM, sized correctly, protected with backups, and configured around your users and applications. :::cta Deploy Windows Now Create a Raff Windows VM when your business is ready to run remote users, Windows apps, shared files, and SMB workloads in the cloud. ::: ## Recommended path by situation | Situation | Read next | |---|---| | You need the SMB buyer guide | [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) | | You need pricing clarity | [Windows VPS Pricing Explained](https://rafftechnologies.com/windows-server/windows-vps-pricing-explained) | | You need remote user access | [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) | | You support remote employees | [Windows VPS for Remote Employees](https://rafftechnologies.com/windows-server/windows-vps-remote-employees) | | You need shared files | [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) | | You are replacing office hardware | [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) | | You are migrating from local server | [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) | | You need backups | [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) | | You are an MSP | [Windows VPS for MSP Client Environments](https://rafftechnologies.com/windows-server/windows-vps-for-msp-client-environments) | | You run accounting workloads | [Windows VPS for Accounting Firms](https://rafftechnologies.com/windows-server/windows-vps-accounting-firms) | | You run legal workloads | [Windows VPS for Law Firms](https://rafftechnologies.com/windows-server/windows-vps-law-firms) | ## Final checklist: Windows VPS or dedicated server? Before choosing, answer: | Question | Answer | |---|---| | How many active users will connect? | ☐ | | What apps will run on the server? | ☐ | | Does the app vendor support Windows Server/RDS? | ☐ | | How much CPU/RAM/storage is needed now? | ☐ | | How much growth is expected in 12-24 months? | ☐ | | Are RDS CALs required? | ☐ | | Is SQL Server involved? | ☐ | | Are backups and snapshots planned? | ☐ | | Is restore testing planned? | ☐ | | Is physical isolation required? | ☐ | | Is custom hardware required? | ☐ | | Is the workload heavy and predictable? | ☐ | | Who manages Windows updates and security? | ☐ | | Who supports applications and users? | ☐ | | What is the rollback plan? | ☐ | If physical isolation, custom hardware, or sustained heavy workload is not a requirement, a Windows VPS is usually the cleaner starting point for small businesses. ## What's next - Explore [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) when you are ready to compare Windows VM options. - Review [Raff pricing](https://rafftechnologies.com/pricing) before choosing CPU, RAM, storage, and monthly cost. - Read [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) for the broader SMB decision guide. - Read [Windows VPS Pricing Explained](https://rafftechnologies.com/windows-server/windows-vps-pricing-explained) before budgeting the full environment. - Read [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) before rolling out staff access. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production data. ## Sources - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) - Raff — [Windows Server Hub](https://rafftechnologies.com/windows-server) - Raff — [Remote Desktop Server for Business](https://rafftechnologies.com/windows-server/remote-desktop-server-for-business) - Raff — [Windows VPS Hosting for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-small-business) - Microsoft Learn — [Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [What is SMB File Sharing for Windows and Windows Server?](https://learn.microsoft.com/en-us/windows-server/storage/file-server/file-server-smb-overview) - Microsoft Learn — [SMB security hardening in Windows Server and Windows Client](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-security-hardening) --- ### Windows VPS Hosting for Small Businesses URL: https://rafftechnologies.com/windows-server/windows-vps-small-business Description: Learn when a Windows VPS makes sense for small businesses that need Remote Desktop access, Windows apps, shared files, backups, migration, and predictable cloud infrastructure. A Windows VPS can help small businesses run Windows workloads in the cloud when they need Remote Desktop access, hosted business apps, shared files, SQL Server tools, backups, migration from old office hardware, or a central Windows Server environment for remote users. It works best when the business plans user count, access model, application support, storage, backups, security, and licensing before production. Raff Technologies provides Windows VMs for small teams that want a practical cloud Windows Server without building a complex hyperscaler setup. Small businesses usually do not wake up thinking, “We need a virtual private server.” They feel a business problem first. The office server is getting old. Remote employees need access. Accounting software only works on one machine. Files are spread across offices. Backups are unclear. A legacy app still needs Windows. A tax team needs seasonal access. An MSP needs a repeatable client environment. A Windows VPS is valuable when it turns those problems into one controlled Windows environment: users connect remotely, business apps run centrally, files are protected, backups are planned, and the server is no longer tied to one physical office. ## Quick verdict: when a Windows VPS fits a small business Use this table before choosing a Windows VPS. | Small business situation | Windows VPS fit | Why | |---|---|---| | Team needs Remote Desktop access | Strong fit | Users can reach a centralized Windows environment from outside the office. | | Business app runs on Windows Server | Strong fit after testing | Apps can run in a cloud-hosted Windows Server environment. | | Office server is aging | Strong fit | A Windows VPS can replace the physical server role. | | Multiple offices need the same apps or files | Strong fit | Centralized access reduces branch-by-branch complexity. | | Files need shared access and backups | Good fit | A cloud file server can centralize shared folders with backup planning. | | ERP, inventory, tax, or accounting software needs remote access | Good fit after vendor checks | App support, licensing, and database behavior must be reviewed. | | Users only need simple document collaboration | Depends | SaaS file tools may be simpler. | | Large local files move all day | Depends | Local storage may still be better for heavy LAN file workflows. | | High availability is mandatory | Not a single VPS decision | Plan redundancy, failover, and recovery architecture. | | App vendor does not support hosted/RDS use | Risky | Check vendor support before migration. | The best fit is a business that needs a central Windows Server environment for remote access, apps, files, or migration from local infrastructure. :::cta Explore Windows VM Use Raff Windows VM when your small business needs a cloud-hosted Windows Server for remote access, apps, files, and Windows workloads. ::: ## Why small businesses choose Windows VPS hosting ![Use case map showing Windows VPS for remote access, business software, server replacement, shared files, databases, and backups](https://raff-images.s3.raffusercloud.com/windows_vps_small_business_use_case_map_webp_619238fc20.png) A small business usually chooses Windows VPS hosting for one of six reasons. | Reason | Example | |---|---| | Remote access | Employees need to reach a Windows desktop or app from home, branches, or client sites. | | Business software | Accounting, ERP, inventory, tax, Access, or legacy apps need a central Windows environment. | | Server replacement | The old office server is aging, unreliable, or difficult to maintain. | | Shared files | Users need central folders, mapped drives, or app file paths. | | Databases | SQL Server or app databases need a Windows Server environment. | | Better recovery planning | Backups, snapshots, restore testing, and off-server copies need to be clearer. | The goal is not “move everything to cloud” by default. The goal is to put the right Windows workloads in an environment that is easier to access, manage, back up, and support. ## Windows VPS vs local office server A local office server can still work when users are on-site, workloads depend on local hardware, and the business has reliable power, cooling, backup, and IT support. ![Comparison visual showing local office server versus Windows VPS for small business users, apps, files, and backups](https://raff-images.s3.raffusercloud.com/small_business_local_server_vs_windows_vps_webp_e4b61e25e7.png) A Windows VPS becomes attractive when the business needs remote access, multi-location access, or a cleaner replacement for old hardware. | Area | Local office server | Windows VPS | |---|---|---| | Server location | One physical office | Cloud-hosted Windows Server VM | | Hardware | Business owns and replaces it | Cloud VM replaces physical server role | | Remote users | VPN, firewall, or local workaround | Remote access can be planned from the start | | Multi-location access | Often complex | Centralized environment for branch users | | Backups | Often inconsistent or local | VM backup, snapshot, and restore planning can be centralized | | Scaling | Buy or replace hardware | Resize VM or split roles | | Support | May require on-site work | MSP/team can manage a known cloud environment | | Risk | Office power/hardware can block access | Not tied to one office server | The decision is not “cloud always wins.” The decision is whether the workload benefits from being centralized in a hosted Windows environment. ## Windows VPS vs SaaS tools A Windows VPS is not always the best answer. Some business problems are better solved with SaaS. | Need | Windows VPS | SaaS | |---|---|---| | Run a Windows-only desktop app | Strong fit | Usually poor fit unless vendor has SaaS version | | Host legacy business software | Strong fit after testing | Depends on replacement availability | | Use mapped drives or NTFS permissions | Strong fit | Different model | | Real-time document co-authoring | Not ideal | Strong fit | | Vendor-managed updates | Business/MSP manages app | Vendor usually manages | | Custom Windows server control | Strong fit | Limited | | Simple file sharing | Can work | Often simpler | | SQL Server-backed app | Strong fit | Depends on app | If a SaaS version of the application fully replaces the workflow, it may be simpler. If the business still depends on Windows Server, Remote Desktop, mapped drives, SQL Server, or legacy apps, a Windows VPS may be the practical path. ## Common Windows VPS use cases for small businesses ### Remote Desktop for employees Many small businesses use a Windows VPS so employees can connect to a central Windows environment instead of relying on one office PC or server. Remote Desktop fits when: | Situation | Why it fits | |---|---| | Users need access from home | The Windows environment is reachable remotely. | | Multiple users need the same app | The app can run centrally where supported. | | Branch users need shared access | Offices connect to one environment. | | MSP manages users | Access can be documented and standardized. | Microsoft describes Remote Desktop Services as a Windows Server platform for securely delivering managed desktops and applications to users in offices, homes, branches, and partner locations. That is the right mental model for many small business Remote Desktop scenarios. For staff desktop sessions, licensing matters. Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs an RDS Client Access License. ### Business software hosting A Windows VPS can host Windows-based business software when the vendor supports the environment. Examples include: | Software type | Planning focus | |---|---| | Accounting software | Data location, printers, RDS support, backups | | Tax software | Seasonal users, client files, vendor support | | ERP/inventory | Database, reports, branches, device workflows | | Microsoft Access | Front-end/back-end split, file paths, RDP access | | Legacy apps | Runtime dependencies, licensing, support | | SQL-backed apps | SQL Server backups, logins, jobs, connection strings | The application should be tested before production. A Windows VPS can provide the server environment, but the vendor support model still matters. ### Cloud file server A Windows VPS can work as a cloud file server when the business needs shared folders, NTFS permissions, mapped drives, and backup planning. It is strongest when: | File pattern | Fit | |---|---| | Users access files through RDP/RDS | Strong fit | | Business apps need shared folders | Good fit after testing | | Multi-location users need one file location | Good fit | | Folder permissions matter | Good fit | | Users want direct SMB from anywhere | Risky without secure access design | Microsoft describes SMB as the protocol Windows uses for file sharing. SMB should be used through a controlled access model, not casually exposed to the public internet. ### SQL Server and database-backed apps A Windows VPS can support SQL Server-backed business apps when the database workload is sized and backed up correctly. Plan: | SQL area | What to check | |---|---| | SQL version and edition | Supported by the application | | Recovery model | Affects backup and restore strategy | | Logins and users | Must migrate correctly | | SQL Agent jobs | Backups, imports, exports, reports | | Connection strings | Apps must point to the new SQL Server | | Firewall rules | Restrict access to required paths | | Restore test | Proves backup recovery | SQL Server migration is not only restoring a database. Logins, jobs, permissions, and app connections matter. ### Office server replacement Many small businesses reach Windows VPS hosting because the old office server becomes a risk. Warning signs: | Sign | Meaning | |---|---| | Hardware is old | Replacement risk is growing | | Backups are unclear | Recovery is not proven | | Remote access is messy | Users depend on workarounds | | Multiple offices copy files manually | Centralization may help | | One person knows the setup | Documentation risk | | Server runs many hidden tasks | Migration checklist is needed | A side-by-side migration is usually safer: build the new Windows VPS, test apps and users, run final sync, cut over, and keep rollback ready. ## How to choose the right Windows VPS size Do not size a Windows VPS only by employee count. Size it by active users, application workload, database load, storage growth, and remote access pattern. ![Workload planning visual for small business Windows VPS sizing with users, apps, SQL, storage, backups, and growth](https://raff-images.s3.raffusercloud.com/windows_vps_small_business_workload_planning_webp_0d86615079.png) Use this starting model: | Workload | Starting size | When to move up | |---|---:|---| | 1 admin or light user | 2 vCPU / 4 GB RAM | If apps or reports run on the server | | 3 light remote users | 4 vCPU / 8 GB RAM | If users keep browsers, PDFs, or Office apps open | | 3 business app users | 4 vCPU / 16 GB RAM | If accounting, Access, tax, or legacy apps run daily | | 5 active users | 4 vCPU / 16 GB RAM | If users stay logged in most of the day | | 10 active users | 8 vCPU / 32 GB RAM | If the VPS becomes a shared workplace | | SQL/ERP/heavy app | 8-16 vCPU / 32-64 GB RAM | If database, reports, and sessions compete | Storage should include production files, app data, database files, user profiles, logs, backups, reports, exports, and 12 to 24 months of expected growth. :::cta View Pricing Compare Raff Windows VM plans when sizing CPU, memory, storage, and monthly cost for your small business workload. ::: ## Remote access: direct RDP, RDS, RD Gateway, or VPN? Remote access should be designed before users start working. | Access model | Best fit | |---|---| | Direct admin RDP | One or two administrators | | RDS Session Host | Multiple staff users need desktop/app sessions | | RD Gateway | Controlled access for remote RDS users | | VPN/private access | Mapped drives or internal tools need private network access | | Web app access | Users only need browser access to an app | Direct RDP may be acceptable for restricted admin access. It should not become the default plan for every business user without a security review. RD Gateway can be useful when multiple users connect from changing locations. Microsoft describes RD Gateway as enabling secure, encrypted connections to RDS resources over the internet without requiring VPN access. ## Backups are part of the Windows VPS decision A Windows VPS should not become production until backup and restore planning are clear. Plan: | Backup layer | Purpose | |---|---| | VM backup | Recover the whole Windows VPS | | Snapshot before changes | Roll back before risky updates or migrations | | File-level backup | Restore individual files or folders | | Database backup | Protect SQL Server or app databases | | Off-server copy | Reduce risk from VM/account/ransomware scenarios | | Restore test | Prove recovery works | Backups should be tied to business expectations: | Term | Meaning | |---|---| | RPO | How much data loss is acceptable | | RTO | How long the business can be down | A 3-user office may accept different recovery targets than a tax firm during filing season or a warehouse during daily shipping. :::cta Explore Data Protection Protect your Windows VPS workload with backup, snapshot, and restore planning before storing production business data. ::: ## Security planning for small business Windows VPS A Windows VPS can hold business-critical data, so security must be planned before users connect. Minimum planning: | Area | Recommendation | |---|---| | Admin access | Use named admin accounts | | User access | Least privilege and role-based groups | | RDP exposure | Avoid broad direct RDP exposure | | Firewall rules | Allow only required ports and sources | | Updates | Patch Windows and business apps deliberately | | Backups | Restrict who can delete or modify backups | | Passwords | Use strong credentials and offboarding process | | Logs | Review failed logins and access events | | App support | Keep vendor-supported versions where possible | | Documentation | Record access, roles, backups, and support owners | Microsoft provides Windows Server security baseline guidance and Security Compliance Toolkit resources for recommended configuration baselines. For small businesses, baselines are a starting point, not a complete compliance program. ## Licensing and support questions to ask Before production, answer these questions: | Question | Why it matters | |---|---| | Does the app vendor support Windows Server? | Unsupported apps create migration risk. | | Does the app support RDS or multi-user sessions? | Staff Remote Desktop use may need a supported model. | | Are RDS CALs required? | Staff desktop sessions differ from admin access. | | Does SQL Server licensing apply? | SQL Server edition and licensing are separate decisions. | | Are Windows users named and documented? | Shared accounts create security and support problems. | | Who patches the server? | Updates need ownership. | | Who supports the app? | Infrastructure and app support are different. | | Who tests restores? | Backups are only useful if recoverable. | A Windows VPS is infrastructure. The business or MSP still owns the software, licensing, access, backups, and support process unless a specific managed service says otherwise. ## Migration path from local server to Windows VPS For many SMBs, the Windows VPS journey starts with migration from local hardware. Use this safe pattern: 1. Inventory the old server. 2. Decide what moves, rebuilds, retires, or stays local. 3. Build the new Windows VPS. 4. Configure access, users, firewall, and backups. 5. Run test migration. 6. Test real workflows. 7. Schedule cutover. 8. Run final sync or final backup/restore. 9. Move users. 10. Keep rollback ready. 11. Monitor after cutover. Do not break the old server first. Keep it available until the Windows VPS is proven. ## Windows VPS for MSP-managed clients MSPs can use Windows VPS environments to standardize client workloads. Good MSP use cases: | MSP client need | Why Windows VPS helps | |---|---| | Replace aging office servers | Removes hardware dependency | | Host client business apps | Centralizes Windows app access | | Support remote users | Gives a known access model | | Standardize backups | Easier to document and monitor | | Separate client environments | Cleaner security and billing | | Build test environments | Safer migrations and upgrades | Each client should usually have its own Windows VPS, access policy, backup plan, documentation set, and offboarding process. ## Windows VPS pricing: what affects cost? Small businesses should compare more than the base monthly VM price. Cost drivers include: | Cost area | What affects it | |---|---| | CPU and RAM | Active users, apps, reports, SQL workload | | Storage | Files, databases, profiles, logs, growth | | Backups | Retention, frequency, restore needs | | Windows licensing | Depends on provider and deployment model | | RDS CALs | Required for staff RDS usage scenarios | | SQL Server | Edition and licensing model | | Migration labor | Apps, files, SQL, AD, cutover | | Support | Infrastructure support vs app support | | Security | Access controls, monitoring, hardening | | Downtime risk | Recovery expectations and redundancy | The cheapest server is not always the cheapest operating model. The right Windows VPS plan should match the workload and recovery expectations. ## How Raff fits Windows VPS hosting for small businesses Raff fits small businesses that need a cloud-hosted Windows Server environment for Remote Desktop access, business apps, shared files, SQL Server tools, office server replacement, migration, multi-location users, MSP client environments, tax software, accounting workflows, ERP/inventory systems, or Microsoft Access and legacy apps. Raff Windows VMs can serve as the infrastructure layer. From there, the business or MSP should configure users, applications, RDS access, backups, security rules, monitoring, and documentation. Raff is not a replacement for application vendor support, SQL Server licensing, RDS CAL planning, or internal business process ownership. The clean model is: use Raff for the Windows VM foundation, then plan the workload correctly. :::cta Deploy Windows Now Create a Raff Windows VM when your team is ready to run Windows workloads, remote users, apps, and shared files in the cloud. ::: ## Recommended path by small business situation ![Decision path visual showing small business Windows VPS use cases including sizing, migration, files, SQL, remote access, and backups](https://raff-images.s3.raffusercloud.com/windows_vps_small_business_decision_path_webp_a022ef6abc.png) | Business situation | Recommended next guide | |---|---| | You are sizing for users | Windows VPS sizing for remote users | | You are replacing office hardware | Cloud Windows Server vs Local Office Server | | You need migration planning | Windows Server Migration Checklist | | You are moving a local server | Local Office Server to Cloud Windows VPS Migration | | You are moving file shares | File Server Migration to Windows VPS | | You are moving SQL Server | SQL Server Migration to Windows VPS | | You need shared folders | Windows VPS as a Cloud File Server | | You need remote access security | RD Gateway vs Direct RDP | | You run ERP or inventory software | Windows VPS for ERP and Inventory Software | | You run tax software | Windows VPS for Tax Software | | You use Access or legacy apps | Windows VPS for Microsoft Access and Legacy Apps | | You manage clients as an MSP | Windows VPS for MSP Client Environments | This page is the starting point. The supporting guides help you make the detailed decision. ## What's next - Explore [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) when you are ready to compare Windows VM plans. - Review [Raff pricing](https://rafftechnologies.com/pricing) when sizing CPU, RAM, storage, and monthly cost. - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing a plan. - Read [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) if you are replacing office hardware. - Read [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) before moving production workloads. - Read [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) if you are moving from local hardware. - Read [File Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps) if shared folders are part of the move. - Read [SQL Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/sql-server-migration-to-windows-vps) if the workload depends on SQL Server. ## Sources - Microsoft Learn — [Remote Desktop Services overview in Windows Server](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/overview) - Microsoft Learn — [Remote Desktop Services roles](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-roles) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [Deploy Remote Desktop Gateway role for Remote Desktop Services](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/remote-desktop-gateway-role) - Microsoft Learn — [What is SMB File Sharing for Windows and Windows Server?](https://learn.microsoft.com/en-us/windows-server/storage/file-server/file-server-smb-overview) - Microsoft Learn — [SMB security hardening in Windows Server and Windows Client](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-security-hardening) - Microsoft Learn — [Back up and restore of SQL Server databases](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/back-up-and-restore-of-sql-server-databases) - Microsoft Learn — [Recovery models in SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/recovery-models-sql-server) - Microsoft Learn — [Security baselines guide](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/windows-security-baselines) - Microsoft Learn — [Microsoft Security Compliance Toolkit](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Windows Server Hub](https://rafftechnologies.com/windows-server) - Raff — [Pricing](https://rafftechnologies.com/pricing) --- ### How to Connect to a Windows VPS via RDP URL: https://rafftechnologies.com/windows-server/connect-to-windows-vps-via-rdp Description: Step-by-step guide to connecting to a Windows VPS with Remote Desktop, including Windows, macOS, Linux, mobile clients, password reset, certificate warnings, and RDP troubleshooting. To connect to a Windows VPS via RDP, copy the server's public IP address from your Raff dashboard, open a Remote Desktop client, enter the IP address, sign in with `Administrator`, enter the password you set during VM creation, and accept the first-time certificate warning. For most users, the connection takes less than a minute. The fastest path is: ```text 1. Open your RDP client. 2. Enter the Windows VPS public IP. 3. Use username: Administrator. 4. Enter the Windows VPS password. 5. Accept the certificate warning. 6. You are connected to Windows Server. ``` If the connection fails, the cause is usually one of four things: - the VM is not running yet; - the password or username is wrong; - your network blocks outbound TCP 3389; - the server firewall or RDP service is not reachable. This guide shows how to connect from Windows, macOS, Linux, iPhone, iPad, and Android, then how to fix the most common RDP errors. ## What RDP is RDP stands for Remote Desktop Protocol. It lets you open a graphical Windows desktop session on a remote Windows Server. Instead of working directly on a physical machine, you control the Windows VPS over the network from your local computer. For Windows VPS users, RDP is used for: - first server login; - installing software; - managing Windows Server; - configuring IIS, SQL Server, ERP, accounting apps, or business software; - running admin tools; - checking logs; - changing firewall rules; - setting up RDS when more users are needed. RDP is not the same as a web dashboard. The dashboard creates and manages the VM. RDP connects you to the Windows desktop inside that VM. ## What you'll need Before starting, prepare: - a Raff Windows VPS with status **Running**; - the VM's **Public IPv4** address; - the Administrator password you set during VM creation; - an RDP client on your local device; - outbound access to TCP port `3389` from your network; - 5 minutes for the first connection. Windows has a built-in RDP client. macOS, iOS, iPadOS, and Android use Microsoft's Windows App or another RDP client. Linux users can use Remmina or FreeRDP. ## RDP connection settings Use these settings for a standard Raff Windows VPS connection: | Field | Value | |---|---| | Computer / PC name / Server | Your VPS public IP address | | Username | `Administrator` | | Password | The password set during VM creation or reset later | | Port | `3389` unless changed manually | | Authentication | Password-based Windows login | | Certificate warning | Expected on first connection | Example: ```text Computer: 203.0.113.42 Username: Administrator Password: your saved Administrator password ``` If `Administrator` does not work in your RDP client, try: ```text .\Administrator ``` or: ```text \Administrator ``` For example: ```text 203.0.113.42\Administrator ``` ## Step 1 — Get your IP address and password ready ![VM details page on app.rafftechnologies.com showing the IP address field, credentials panel, and the Password action in the top toolbar](https://raff-images.s3.raffusercloud.com/large_raff_dashboard_vm_details_windows_server_2026_04_e539f4c973.png) Raff handles Windows credentials differently from providers that email a generated password. You set the Administrator password during VM creation. Raff does not display that password afterward, so save it in a password manager before closing the creation flow. To find your Windows VPS IP address: 1. Log in to the Raff dashboard. 2. Go to **Compute → All Virtual Machines**. 3. Click your Windows VM. 4. Copy the **Public IPv4** address from the VM details page. The default username is: ```text Administrator ``` unless you changed it during setup. ## If you forgot the Administrator password If you forgot the password, reset it from the VM details page. In the Raff dashboard: 1. Open the Windows VM details page. 2. Go to **Actions**. 3. Find **Reset Password**. 4. Confirm the reset. 5. Use the new password after the reset completes. If reset does not work, contact Raff support with the VM name and account email. Do not keep retrying random passwords. Repeated failed login attempts can trigger lockout behavior depending on Windows policy. ## Step 2 — Connect from Windows Windows includes **Remote Desktop Connection** by default. No install is needed. 1. Press `Win + R`. 2. Type: ```text mstsc ``` 3. Press **Enter**. 4. In **Computer**, paste your Windows VPS public IP address. 5. Click **Show Options**. 6. In **User name**, enter: ```text Administrator ``` 7. Click **Connect**. 8. Enter the Administrator password. 9. Accept the certificate warning. You should now see the Windows Server desktop. ## Save the RDP connection on Windows After entering the IP and username: 1. Click **Show Options**. 2. Go to the **General** tab. 3. Click **Save As**. 4. Save the `.rdp` file somewhere safe. Next time, double-click the `.rdp` file. Do not store the password inside an `.rdp` file shared with other people unless your organization has a safe credential process. ## Step 3 — Connect from macOS On macOS, use Microsoft's **Windows App** from the Mac App Store. 1. Install **Windows App** from the Mac App Store. 2. Open Windows App. 3. Click **+**. 4. Choose **Add PC**. 5. In **PC name**, paste your Windows VPS public IP. 6. Add a user account: - Username: `Administrator` - Password: your Administrator password 7. Save the connection. 8. Double-click the saved PC. 9. Accept the certificate warning. Windows App supports common RDP features such as clipboard sharing, display settings, and folder redirection depending on your client settings. For normal Windows VPS administration, it is the recommended path on macOS. ## Step 4 — Connect from Linux The easiest Linux RDP client is usually **Remmina**. Install Remmina: ```bash # Ubuntu / Debian sudo apt update sudo apt install remmina remmina-plugin-rdp ``` For Fedora: ```bash sudo dnf install remmina remmina-plugins-rdp ``` For Arch: ```bash sudo pacman -S remmina freerdp ``` Then connect: 1. Open **Remmina**. 2. Click **+** to create a new profile. 3. Set **Protocol** to `RDP - Remote Desktop Protocol`. 4. Set **Server** to your Windows VPS public IP. 5. Set **Username** to `Administrator`. 6. Enter the password. 7. Click **Save and Connect**. If you prefer the command line, use FreeRDP: ```bash xfreerdp /v:203.0.113.42 /u:Administrator /p:'YourPasswordHere' /cert:tofu /size:1920x1080 ``` Replace the IP and password. `/cert:tofu` means trust on first use. Avoid `/cert:ignore` for normal use because it skips certificate validation entirely. ## Step 5 — Connect from iPhone, iPad, or Android Use Microsoft's mobile **Windows App**. On iPhone or iPad: 1. Install **Windows App** from the App Store. 2. Open the app. 3. Tap **+**. 4. Choose **Add PC**. 5. Enter the Windows VPS IP address. 6. Add the `Administrator` account and password. 7. Save and connect. 8. Accept the certificate warning. On Android: 1. Install **Windows App** from Google Play. 2. Tap **+**. 3. Add the Windows VPS IP address. 4. Add the `Administrator` login. 5. Save and connect. Mobile RDP is useful for quick admin tasks. For serious server work, use a desktop or laptop with a keyboard and larger screen. ## Step 6 — Accept the certificate warning The first RDP connection usually shows a certificate warning. This is normal for a new Windows VPS. Why it happens: - the server uses a self-signed RDP certificate by default; - your local computer has never trusted this server before; - the certificate name may not match the IP address. If the IP address is correct and you are connecting to your own VM, accept the warning. Do not ignore certificate warnings if you are connecting over an unknown network, using a suspicious IP, or if the warning appears unexpectedly after a long period of normal use. For production RDS environments, you can later configure trusted certificates, RD Gateway, and stronger access controls. ## Step 7 — Verify the Windows VPS connection After the desktop opens, run a quick check. Open PowerShell as Administrator and run: ```powershell Get-ComputerInfo | Select-Object CsName, OsName, OsVersion, OsBuildNumber ``` You should see: - server name; - Windows Server edition; - OS version; - build number. Then check the IP configuration: ```powershell ipconfig ``` Also confirm RDP service status: ```powershell Get-Service TermService ``` Expected status: ```text Running ``` If you can open PowerShell and run these checks, your RDP session is working. ## Security tips after first login After you connect for the first time, do not stop at the desktop. Do these basic hardening steps: 1. Run Windows Update. 2. Confirm the Administrator password is strong and unique. 3. Create named admin accounts if more people need access. 4. Do not share one Administrator password across a team. 5. Restrict RDP access by firewall rule if possible. 6. Use a VPN or RD Gateway for stricter environments. 7. Do not expose unnecessary ports. 8. Enable backups or snapshots before installing important software. 9. Review Windows Firewall. 10. Keep a recovery path in the Raff dashboard. For small one-admin environments, direct RDP may be acceptable. For production teams, RDP access should be part of a security plan. ## Common RDP errors and how to fix them Most first-time RDP problems fit into a small number of categories. ## Error 1 — "Your credentials did not work" Most likely causes: - wrong password; - wrong username; - password pasted with hidden characters; - Caps Lock; - password was reset but not updated in your client; - saved RDP credentials are stale. Try these username formats: ```text Administrator .\Administrator \Administrator ``` Example: ```text 203.0.113.42\Administrator ``` Then type the password manually instead of pasting it. If it still fails, reset the password from the Raff dashboard. ## Error 2 — "Remote Desktop can't connect to the remote computer" This usually means the server cannot be reached over RDP. Check in this order: 1. Is the VM status **Running** in the Raff dashboard? 2. Are you using the correct public IP? 3. Are you connected to a corporate VPN or office network that blocks RDP? 4. Can your network reach TCP port `3389`? 5. Was Windows Firewall changed inside the VM? 6. Was RDP disabled manually? From Windows, test the port: ```powershell Test-NetConnection 203.0.113.42 -Port 3389 ``` From macOS or Linux: ```bash nc -zv 203.0.113.42 3389 ``` If the port test fails from your office network, try a personal hotspot. Many corporate networks block outbound RDP. ## Error 3 — Network Level Authentication warning You may see an error similar to: ```text The remote computer requires Network Level Authentication. ``` This usually means your local RDP client is too old or incompatible. Fix it by updating your local RDP client or operating system. Do not disable Network Level Authentication as a normal fix. NLA is a security feature and should stay enabled for internet-facing or production servers. Only disable it temporarily for controlled testing if you have console access or another recovery path. ## Error 4 — CredSSP authentication error You may see: ```text An authentication error has occurred. The function requested is not supported. ``` This is usually related to CredSSP update mismatch. The clean fix is to update the local computer and the Windows Server with current Windows Updates. Avoid old workarounds that weaken encryption oracle remediation settings. They may make the connection work by reducing security, which is not the right fix for a production server. ## Error 5 — The session disconnects after a fixed time If the session disconnects after a fixed period such as 30 minutes or 2 hours, a session limit policy is probably configured. Check Local Group Policy: ```text Computer Configuration → Administrative Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Session Time Limits ``` Review: - **Set time limit for active but idle Remote Desktop Services sessions** - **Set time limit for active Remote Desktop Services sessions** - **End session when time limits are reached** If the server is joined to a domain, a domain Group Policy may override local settings. ## Error 6 — Black screen after login A black screen after login is usually not an RDP credential problem. Try: 1. Wait 30–60 seconds after first login. 2. Reconnect. 3. Restart the VM from the Raff dashboard if safe. 4. Use lower display resolution in the RDP client. 5. Disable advanced graphics features in the RDP client. 6. Check whether Windows updates are still applying. After reconnecting, inspect Event Viewer and Windows Update status. ## Error 7 — Copy and paste does not work Clipboard sharing can be disabled by client settings, server policy, or RDS configuration. Try: 1. Disconnect and reconnect. 2. Check the RDP client clipboard setting. 3. On Windows client, open **Local Resources** and enable Clipboard. 4. Restart `rdpclip.exe` inside the session: ```powershell Stop-Process -Name rdpclip -Force Start-Process rdpclip.exe ``` For production RDS environments, clipboard redirection may be intentionally disabled by policy. ## Error 8 — File transfer does not work RDP file transfer depends on drive or folder redirection. On Windows Remote Desktop Connection: 1. Open `mstsc`. 2. Click **Show Options**. 3. Go to **Local Resources**. 4. Click **More**. 5. Select the local drives you want to redirect. 6. Connect again. On macOS Windows App, configure folder redirection in the saved PC settings. For sensitive servers, avoid redirecting your full local drive. Share only the folder you actually need. ## RDP security best practices RDP is powerful, but it must be protected. Use these rules: | Practice | Why it matters | |---|---| | Use a strong Administrator password | Reduces brute-force risk | | Keep Windows updated | Fixes RDP and authentication vulnerabilities | | Restrict RDP source IPs | Limits who can even reach port 3389 | | Use VPN or RD Gateway for teams | Avoids broad public RDP exposure | | Avoid shared admin accounts | Improves accountability | | Do not run daily work as Administrator | Reduces blast radius | | Enable backups before major changes | Gives rollback and recovery options | | Monitor failed logins | Helps detect attack attempts | | Use RDS CALs for multi-user access | Keeps production access properly licensed | RDP should be convenient, not careless. ## Admin RDP vs RDS Session Host A normal Windows Server VPS includes administrative RDP access. That is different from using the server as a multi-user desktop for employees. Administrative RDP is for: - server setup; - troubleshooting; - patching; - software installation; - admin maintenance. RDS Session Host is for: - multiple users signing in regularly; - shared business app access; - remote desktop workflows; - RemoteApp; - proper RDS licensing. If more than the default administrative sessions are needed, read the multi-user RDP and RDS CAL licensing guides before putting users on the server. Do not build a production multi-user desktop environment around admin RDP sessions. ## What Raff recommends For most Raff Windows VPS users: 1. Use `Administrator` only for first setup and emergency admin tasks. 2. Save credentials in a password manager. 3. Run Windows Update after first login. 4. Keep RDP access restricted where possible. 5. Use a VPN or RD Gateway for teams and sensitive servers. 6. Use RDS Session Host and RDS CALs for real multi-user access. 7. Enable backups or snapshots before installing business-critical apps. 8. Contact support if the VM is running but RDP port `3389` is not reachable. The goal is simple: ```text Connect fast, then secure the server properly. ``` ## Tested on > Tested on Raff Windows VPS running Windows Server 2025, connecting with Remote Desktop Connection on Windows and Windows App on macOS. The original Raff dashboard screenshot and workflow were kept from the previous version of this guide. Retest the article after any future dashboard UI or password reset flow change. ## What's next - [Multi-user RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-admin-sessions-vs-rds) - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) - [Windows Server 2019 vs 2022 vs 2025: Which Version to Choose](/windows-server/windows-server-version-comparison) - [Windows Firewall for Production Servers](/windows-server/windows-firewall-production) - [Raff Windows VPS](/products/windows-vm) ## Sources - Microsoft Learn — Remote Desktop Services overview in Windows Server - Microsoft Learn — Remote Desktop Services roles and components - Microsoft Learn — Troubleshoot unexpected RDS session locks or disconnections - Microsoft Support — CredSSP updates for CVE-2018-0886 - Microsoft Tech Community — Windows App now available on all major platforms - Remmina official documentation - Date last verified: 2026-07-06 --- ### Always On Availability Groups on Two Windows VPSes URL: https://rafftechnologies.com/windows-server/mssql-always-on-setup Description: Learn how to plan and set up SQL Server Always On availability groups on Windows Server VPS infrastructure, including WSFC, SQL editions, replicas, listener, quorum, seeding, failover tests, backups, and common mistakes. SQL Server Always On availability groups provide high availability for SQL Server databases by replicating databases from a primary SQL Server replica to one or more secondary replicas. For a Windows Server VPS setup, the normal high-availability architecture is: ```text App server ↓ Availability Group Listener ↓ Primary SQL Server replica ↔ Secondary SQL Server replica ↓ Windows Server Failover Cluster ↓ Quorum witness ``` The important rule: ```text Always On is high availability. It is not a replacement for backups. ``` A good production setup needs: - at least two Windows Server VMs; - private networking between SQL nodes; - Active Directory or a carefully designed cluster identity model; - Windows Server Failover Clustering; - SQL Server edition that supports the required AG features; - same SQL Server version and patch level on replicas; - comparable CPU, RAM, and disk layout; - database in FULL recovery model; - full and log backups before joining secondary databases; - listener DNS/IP planning; - quorum witness planning; - firewall rules for SQL, cluster, and database mirroring endpoints; - tested manual and automatic failover; - backup and restore process independent of the AG. If you are using SQL Server Standard edition, you are usually talking about a **Basic Availability Group**: two replicas, one database, and limited secondary capabilities. If you need multiple databases failing over together, readable secondaries, backup offload to secondaries, more replicas, or advanced routing, you likely need SQL Server Enterprise. ## Quick verdict | Situation | Recommended path | |---|---| | One critical database on SQL Server Standard | Basic Availability Group | | Multiple databases must fail over together | Enterprise Availability Group | | Need readable secondary replicas | Enterprise Availability Group | | Need backups on secondary replicas | Enterprise Availability Group | | Need lowest-cost DR with manual recovery | Log shipping may be simpler | | Need instance-level failover, jobs, logins, SQL Agent, linked servers | Consider Failover Cluster Instance or another architecture | | Need automatic failover between two local nodes | Synchronous commit + automatic failover + WSFC quorum | | Need DR across distance/regions | Asynchronous commit with manual/forced failover planning | | Small app with light SQL usage | Start with backups first; HA may be overkill | | Business-critical SQL workload | Always On + backups + monitoring + documented failover runbook | Simple rule: ```text Backups protect data. Always On reduces downtime. Monitoring tells you when either one is failing. ``` ## What Always On availability groups do An Always On availability group is a SQL Server high-availability and disaster-recovery feature. It replicates selected user databases from a primary replica to one or more secondary replicas. The primary replica accepts read-write traffic. Secondary replicas receive transaction log records from the primary and apply them to local database copies. Depending on edition and configuration, secondary replicas can be used for: - failover; - read-only workloads; - backup offload; - disaster recovery; - reporting workloads; - maintenance flexibility. A listener gives applications a stable connection name. Instead of connecting to a physical SQL Server VM, applications connect to: ```text sql-prod-listener.yourdomain.local ``` During failover, the listener moves to the new primary replica. The application should reconnect to the listener and continue against the new primary database. ## What Always On does not do Always On does not protect against every database problem. It does not replace: - full backups; - differential backups; - transaction log backups; - restore testing; - corruption detection; - security controls; - application-level retry logic; - monitoring; - patching discipline; - runbooks. If a user deletes rows, that delete can replicate. If a bad deployment changes data, that change can replicate. If an application corrupts data logically, the corruption may replicate. The AG keeps databases available. Backups let you go back in time. You need both. ## SQL Server editions: Standard vs Enterprise Always On capability depends heavily on SQL Server edition. ![SQL Server Standard Basic Availability Group versus SQL Server Enterprise Always On comparison showing replica limits, database limits, readable secondary support, backup offload, and best-fit use cases.](https://raff-images.s3.raffusercloud.com/sql_server_standard_vs_enterprise_always_on_png_4a9890110e.png) ## SQL Server Standard: Basic Availability Groups SQL Server Standard supports Basic Availability Groups. A Basic AG is useful for one important database that needs a failover replica. But it has limits: - two replicas only; - one availability database per basic AG; - no read access on the secondary replica; - no backups on secondary replica; - no DBCC integrity checks on secondary replica; - only Standard edition support; - cannot be upgraded in place to an advanced Enterprise AG. For a small business with one core database, Basic AG can be enough. For a serious multi-database application, it usually becomes limiting. ## SQL Server Enterprise: Advanced Availability Groups SQL Server Enterprise supports full Always On availability groups. Use Enterprise when you need: - multiple databases in one AG; - databases failing over together; - multiple secondary replicas; - readable secondary replicas; - backup offload to secondary replicas; - read-only routing; - larger HA/DR topology; - more flexible failover design; - distributed availability groups; - contained availability groups; - advanced SQL Server HA features. Enterprise costs more, but it avoids many Standard edition limits. Do not design a multi-database production architecture around Standard edition if the application expects all databases to fail over together. ## Always On vs Failover Cluster Instance vs log shipping SQL Server has multiple high-availability and disaster-recovery patterns. ## Availability Group Best for: - database-level failover; - one or more replicated databases; - listener-based application failover; - readable secondaries on Enterprise; - local HA and remote DR patterns. Trade-off: - does not protect instance-level objects automatically; - logins, SQL Agent jobs, linked servers, credentials, and server-level settings must be managed separately; - requires careful database eligibility and synchronization. ## Failover Cluster Instance Best for: - instance-level failover; - shared storage environments; - applications that depend heavily on SQL instance name and server-level objects; - scenarios where the entire SQL instance should move together. Trade-off: - depends on shared storage or storage replication design; - failover is instance-level rather than database-level; - different infrastructure model. ## Log shipping Best for: - low-cost disaster recovery; - delayed copy protection; - simple warm standby; - manual failover tolerance; - environments where HA complexity is not justified. Trade-off: - no automatic failover; - usually more manual; - recovery point depends on log backup frequency; - connection redirection is not automatic unless you build it. For many SMB workloads, log shipping plus good backups can be more realistic than a full Always On architecture. Do not choose Always On just because it sounds enterprise-grade. Choose it when the recovery objective justifies the complexity. ## Recommended architecture on a Windows VPS ![SQL Server Always On architecture on Windows Server VPS showing an app server connecting through an availability group listener to primary and secondary SQL replicas, Windows Server Failover Cluster, private network replication, quorum witness, and backups.](https://raff-images.s3.raffusercloud.com/sql_server_always_on_architecture_windows_vps_png_5e7883a9b7.png) For a two-node SQL Server Always On setup: ```text Private network: 10.20.0.0/24 SQL01: Windows Server SQL Server instance Primary replica initially SQL02: Windows Server SQL Server instance Secondary replica initially AD / DNS: Domain controller and DNS WSFC: SQLCLUSTER Availability Group: AG_APP01 Listener: sql-app01-listener Quorum: File share witness or cloud witness ``` A common Raff-style design: ```text App VM ↓ private network SQL AG listener ↓ SQL01 + SQL02 ↓ Private network replication ↓ Quorum witness ``` Do not place the application and both SQL replicas on the same failure boundary if the goal is high availability. If all components fail together, the AG does not protect the business. ## What you'll need Prepare: - two Windows Server VMs for SQL replicas; - one domain controller or existing Active Directory environment; - SQL Server installed on both SQL nodes; - matching SQL Server version, edition, and patch level; - private network between SQL nodes; - static private IPs; - DNS working correctly; - Windows Server Failover Clustering feature; - domain account for SQL Server service if Kerberos/listener requirements apply; - SQL Server Management Studio; - database in FULL recovery model; - recent full and log backups; - firewall plan; - quorum witness; - listener name and IP address; - maintenance window for setup and failover testing. For production, use dedicated SQL Server VMs. Do not run SQL Server Always On replicas on domain controllers. ## Step 1 — Decide the AG model Before touching Windows clustering, decide the SQL Server AG model. Ask: - Standard or Enterprise? - One database or many? - Automatic failover or manual failover? - Synchronous or asynchronous commit? - Local HA or remote DR? - Listener or direct connection strings? - Readable secondary needed? - Backup offload needed? - How much data loss is acceptable? - How much downtime is acceptable? - Who performs failover? - How will applications reconnect? Do not build the cluster first and decide the business requirements later. ## Step 2 — Prepare Active Directory and DNS For most Windows SQL Server Always On deployments, Active Directory makes the architecture cleaner. Prepare: - domain-joined SQL01 and SQL02; - DNS records working; - time sync healthy; - service accounts documented; - cluster computer object permissions planned; - listener name planned; - SPN planning if Kerberos is required. Check domain join: ```powershell (Get-WmiObject Win32_ComputerSystem).Domain ``` Check DNS: ```powershell Resolve-DnsName SQL01 Resolve-DnsName SQL02 ``` If DNS is unhealthy, stop. SQL Server clustering and listeners depend on reliable name resolution. ## Step 3 — Prepare both SQL Server VMs Both SQL replicas should be comparable. Match: - Windows Server version; - SQL Server version; - SQL Server edition; - cumulative update level; - collation where application requires it; - data drive layout; - log drive layout; - TempDB design; - service account model; - firewall rules; - SQL Server configuration. Recommended folder layout: ```text D:\SQL\Data L:\SQL\Logs T:\SQL\TempDB B:\SQL\Backups ``` If you use a single disk, keep the folder structure consistent on both nodes. Always On setup is easier when file paths match. ## Step 4 — Install Windows Server Failover Clustering Run on both SQL nodes: ```powershell Install-WindowsFeature Failover-Clustering -IncludeManagementTools ``` Verify: ```powershell Get-WindowsFeature Failover-Clustering ``` Then run cluster validation. From one node: ```powershell Test-Cluster -Node SQL01,SQL02 ``` Review the validation report. Do not ignore storage, network, or system warnings without understanding them. For an AG without shared storage, storage warnings may need interpretation, but network and system failures should be fixed. ## Step 5 — Create the Windows Server Failover Cluster Create the cluster: ```powershell New-Cluster -Name SQLCLUSTER -Node SQL01,SQL02 -StaticAddress 10.20.0.50 ``` Check: ```powershell Get-Cluster Get-ClusterNode ``` Expected: ```text SQL01 Up SQL02 Up ``` Use a private IP for cluster communication and listener traffic where possible. Avoid exposing SQL cluster endpoints directly to the public internet. ## Step 6 — Configure quorum witness A two-node cluster needs a witness to avoid split-brain behavior. Common witness options: - file share witness; - cloud witness; - disk witness if shared storage exists. For a two-VM setup, a file share witness is common. Example: ```text \\DC01\SQLClusterWitness ``` Configure: ```powershell Set-ClusterQuorum -FileShareWitness "\\DC01\SQLClusterWitness" ``` Check: ```powershell Get-ClusterQuorum ``` Do not run a two-node production cluster without understanding quorum. If both nodes disagree about who should be online, quorum determines which side can continue. ## Step 7 — Open required firewall paths Plan firewall rules intentionally. Common SQL AG communication includes: | Purpose | Common port | |---|---:| | SQL Server client connections | 1433 or configured SQL port | | Database mirroring endpoint for AG data movement | 5022 by convention | | WSFC / RPC / cluster communication | Windows cluster/RPC ports | | SMB for file share witness | 445 | | DNS | 53 | | Kerberos | 88 | | LDAP / AD | 389 / 636 where applicable | Open only between trusted private IPs. Example database mirroring endpoint rule: ```powershell New-NetFirewallRule ` -DisplayName "SQL Always On Endpoint 5022" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 5022 ` -RemoteAddress "10.20.0.0/24" ` -Action Allow ``` Do not expose port 5022 or SQL Server listener ports publicly unless there is a very specific, protected architecture. ## Step 8 — Enable Always On availability groups in SQL Server On each SQL Server node: 1. Open **SQL Server Configuration Manager**. 2. Go to **SQL Server Services**. 3. Right-click the SQL Server service. 4. Open **Properties**. 5. Go to the **Always On High Availability** tab. 6. Check **Enable Always On Availability Groups**. 7. Restart the SQL Server service. Repeat on both nodes. PowerShell can also be used, but SQL Server Configuration Manager is usually clearer for first setup. Verify in SQL Server: ```sql SELECT SERVERPROPERTY('IsHadrEnabled') AS IsHadrEnabled; ``` Expected: ```text 1 ``` ## Step 9 — Create database mirroring endpoints Always On availability groups use database mirroring endpoints for replica communication. On SQL01: ```sql CREATE ENDPOINT [Hadr_endpoint] STATE = STARTED AS TCP (LISTENER_PORT = 5022) FOR DATABASE_MIRRORING ( ROLE = ALL, AUTHENTICATION = WINDOWS NEGOTIATE, ENCRYPTION = REQUIRED ALGORITHM AES ); GO ``` Run the same on SQL02. Grant connect permission to the SQL Server service account if needed: ```sql GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [DOMAIN\sqlsvc]; GO ``` If each SQL Server uses a different service account, grant endpoint permissions appropriately on each replica. For production, document endpoint port, authentication, encryption, and service account. ## Step 10 — Prepare the database The database must be eligible for AG membership. On the primary SQL Server: ```sql ALTER DATABASE AppDB SET RECOVERY FULL; GO ``` Take a full backup: ```sql BACKUP DATABASE AppDB TO DISK = 'B:\SQL\Backups\AppDB_full.bak' WITH INIT, COMPRESSION, CHECKSUM, STATS = 10; GO ``` Take a log backup: ```sql BACKUP LOG AppDB TO DISK = 'B:\SQL\Backups\AppDB_log.trn' WITH INIT, COMPRESSION, CHECKSUM, STATS = 10; GO ``` Copy backups to SQL02. Restore on SQL02 with NORECOVERY: ```sql RESTORE DATABASE AppDB FROM DISK = 'B:\SQL\Backups\AppDB_full.bak' WITH NORECOVERY, REPLACE; GO RESTORE LOG AppDB FROM DISK = 'B:\SQL\Backups\AppDB_log.trn' WITH NORECOVERY; GO ``` The secondary database should remain in restoring state until joined to the AG. ## Step 11 — Create the availability group You can create the AG with SSMS or T-SQL. For many admins, the SSMS wizard is easier for the first setup. In SSMS: ```text Always On High Availability → Availability Groups → New Availability Group Wizard ``` Choose: - availability group name; - database; - replicas; - synchronization mode; - failover mode; - endpoints; - backup preferences; - listener if desired; - seeding method. For a local HA pair: ```text SQL01: Synchronous commit Automatic failover SQL02: Synchronous commit Automatic failover ``` For remote DR: ```text Primary: Synchronous or asynchronous depending on latency Remote secondary: Asynchronous commit Manual failover ``` Synchronous commit protects data better but can add latency. Asynchronous commit reduces latency but allows possible data loss during failover. ## Step 12 — Add the listener An availability group listener gives applications a stable name. Example: ```text sql-app01-listener.yourdomain.local ``` Listener planning: | Field | Example | |---|---| | Listener DNS name | `sql-app01-listener` | | Listener port | `1433` | | Listener IP | `10.20.0.60` | | Subnet | SQL private subnet | | Application connection string | points to listener, not node name | Applications should connect to the listener, not directly to SQL01 or SQL02. Example connection target: ```text Server=sql-app01-listener;Database=AppDB;Integrated Security=True;TrustServerCertificate=False; ``` For multi-subnet deployments, client driver settings such as `MultiSubnetFailover=True` may matter. For a single private subnet, listener configuration is simpler. ## Step 13 — Join secondary databases If the wizard does not automatically join the secondary database, run on SQL02: ```sql ALTER DATABASE AppDB SET HADR AVAILABILITY GROUP = AG_APP01; GO ``` Then check synchronization. On either replica: ```sql SELECT ag.name AS availability_group, ar.replica_server_name, drs.database_id, db.name AS database_name, drs.synchronization_state_desc, drs.synchronization_health_desc FROM sys.dm_hadr_database_replica_states drs JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id JOIN sys.availability_groups ag ON ar.group_id = ag.group_id JOIN sys.databases db ON drs.database_id = db.database_id; ``` Expected for a healthy synchronous setup: ```text SYNCHRONIZED HEALTHY ``` If it shows `NOT SYNCHRONIZING`, investigate before testing failover. ## Step 14 — Test application connection through the listener Do not test only in SSMS. Test from the application server. From PowerShell: ```powershell Test-NetConnection sql-app01-listener -Port 1433 ``` From SQL tools: ```sql SELECT @@SERVERNAME AS ConnectedInstance; ``` Then test your real app connection string. The application must use the listener name. If the application still connects to SQL01 directly, failover will not help it. ## Step 15 — Test manual failover Before production, test failover intentionally. In SSMS: ```text Always On High Availability → Availability Groups → right-click AG → Failover ``` Or with T-SQL on the target secondary: ```sql ALTER AVAILABILITY GROUP AG_APP01 FAILOVER; GO ``` Only perform planned manual failover when the secondary is synchronized. After failover: - listener should point to the new primary; - application should reconnect; - database should be read-write on new primary; - old primary should become secondary; - synchronization should resume. Check: ```sql SELECT ag.name, ars.role_desc, ar.replica_server_name, ars.synchronization_health_desc FROM sys.dm_hadr_availability_replica_states ars JOIN sys.availability_replicas ar ON ars.replica_id = ar.replica_id JOIN sys.availability_groups ag ON ar.group_id = ag.group_id; ``` Document the observed downtime. If the app does not reconnect cleanly, fix the application connection string and retry. ## Step 16 — Test automatic failover carefully Automatic failover requires: - synchronous commit; - automatic failover mode on both replicas; - synchronized secondary; - WSFC quorum; - healthy cluster; - client connection through listener. Test only in a maintenance window. Common safe test: 1. Confirm AG healthy. 2. Confirm secondary synchronized. 3. Confirm application connects through listener. 4. Pause or stop SQL Server service on current primary. 5. Observe failover. 6. Confirm app reconnects. 7. Restore service. 8. Confirm old primary rejoins as secondary. 9. Review logs. Do not perform destructive failover tests without backups and a rollback plan. ## Step 17 — Configure backup strategy Always On does not replace backups. Use: - full backups; - differential backups where appropriate; - transaction log backups; - copy-only backups where required; - off-server backup storage; - restore testing; - backup monitoring. For Enterprise AGs, you can configure backup preference to offload backups to secondaries. For Basic AGs on Standard edition, backups on secondary replicas are not supported. Even when backups run on a secondary, you must monitor them. A backup job that silently fails on the preferred replica is still a failed backup. ## Step 18 — Monitor Always On Use SSMS Always On Dashboard. Also monitor: - replica role; - synchronization state; - synchronization health; - send queue; - redo queue; - last hardened LSN; - listener status; - cluster node status; - quorum status; - SQL Agent jobs; - backup success; - transaction log growth; - disk space; - endpoint connectivity; - Windows event logs; - SQL Server error logs. Useful query: ```sql SELECT ag.name AS ag_name, ar.replica_server_name, ars.role_desc, ars.connected_state_desc, ars.synchronization_health_desc, ars.operational_state_desc FROM sys.dm_hadr_availability_replica_states ars JOIN sys.availability_replicas ar ON ars.replica_id = ar.replica_id JOIN sys.availability_groups ag ON ar.group_id = ag.group_id; ``` If the AG is critical, monitoring should alert a human. Do not rely on manually opening SSMS once a month. ## Step 19 — Keep server-level objects in sync Availability groups replicate databases. They do not automatically replicate every server-level object. Track and sync: - SQL logins; - SQL Agent jobs; - linked servers; - credentials; - operators; - alerts; - SSIS packages; - maintenance plans; - server-level permissions; - certificates; - endpoints; - custom server configuration. This is one of the biggest Always On mistakes. After failover, the database may be online, but the app can fail because the login, job, or linked server does not exist on the new primary. Create a runbook for server-level object synchronization. ## Step 20 — Document the failover runbook A production AG needs a runbook. Include: - AG name; - listener name; - node names and IPs; - cluster name and IP; - witness path; - SQL service accounts; - endpoint port; - database list; - backup locations; - monitoring links; - manual failover command; - forced failover conditions; - application connection strings; - rollback process; - who can approve failover; - who contacts application owners; - post-failover checks. Do not wait for an outage to decide who is allowed to fail over SQL. ## Common mistakes ## Mistake 1 — Treating Always On as backup Always On replicates changes. Bad changes replicate too. Use backups and restore testing. ## Mistake 2 — Using Standard edition for a multi-database app Standard edition Basic AG supports one database per Basic AG. If your app needs multiple databases to fail over together, use Enterprise or another architecture. ## Mistake 3 — Connecting applications to the node name Apps must connect to the listener. If the app connects to SQL01 directly, the app stays pointed at SQL01 after failover. ## Mistake 4 — No quorum witness in a two-node cluster A two-node cluster needs a witness strategy. Without quorum planning, failover behavior can be unsafe or unavailable. ## Mistake 5 — Different disk paths on replicas If SQL01 uses `D:\SQL\Data` and SQL02 does not have the same path, seeding, restore, and file placement become harder. Keep layouts consistent. ## Mistake 6 — No server-level object sync AGs replicate databases, not all server-level objects. Sync logins, SQL Agent jobs, credentials, linked servers, and certificates. ## Mistake 7 — Exposing SQL ports publicly Keep SQL replication and listener traffic on private networks where possible. Restrict firewall rules by source IP and subnet. ## Mistake 8 — No failover test An untested AG is a theory. Test planned failover before production. ## Mistake 9 — Ignoring application retry behavior The SQL side can fail over successfully while the app still fails because it does not reconnect properly. Test the real app. ## Mistake 10 — No monitoring Always On can be unhealthy while databases still appear online. Monitor synchronization state, queues, cluster health, backup jobs, and disk space. ## Security checklist Review: - SQL ports restricted to trusted sources; - endpoint port restricted to SQL nodes; - listener not exposed publicly without a reason; - Windows Firewall enabled; - SQL service accounts documented; - SPNs registered if Kerberos is required; - least-privilege SQL admin access; - backups encrypted where appropriate; - certificates protected; - RDP access restricted; - patching process planned; - forced failover permissions limited. High availability should not weaken security. ## How Raff fits SQL Server Always On Raff Windows VM can provide the Windows Server infrastructure layer for self-managed SQL Server HA designs. A Raff-based pattern can include: - two Windows VMs for SQL replicas; - private networking between nodes; - separate app VM; - Windows Server Failover Cluster; - SQL Server Always On availability group; - listener on private network; - backups and snapshots; - support for Windows VM infrastructure. Raff does not replace SQL Server licensing, database administration, application architecture, or Microsoft SQL Server support. You still need: - SQL Server licenses; - Windows Server design; - AD/DNS design; - cluster setup; - database backup strategy; - monitoring; - DBA ownership; - failover runbook. Use Raff for the infrastructure foundation. Use SQL Server expertise for the database architecture. ## What Raff recommends For SQL Server Always On on Windows VPS: 1. Start with backup and restore discipline before HA. 2. Use Standard Basic AG only for one-database HA needs. 3. Use Enterprise when the application needs multiple databases or readable secondaries. 4. Put replicas on comparable Windows VMs. 5. Use private networking for SQL replication and listener traffic. 6. Configure WSFC and quorum before creating the AG. 7. Keep disk paths consistent. 8. Use the listener in application connection strings. 9. Test manual failover and application reconnect. 10. Monitor synchronization, backups, logs, and cluster health. The right mindset: ```text Do not build Always On because it sounds advanced. Build it because the recovery objective requires it and the team can operate it. ``` Do not publish that exact claim until the environment has been tested. ## What's next - [Install SQL Server 2025 on a Windows Server VPS](/windows-server/install-sql-server-2025-windows-server-vps) - [MSSQL Backup Strategy on Windows VPS](/windows-server/mssql-backup-strategy-windows-vps) - [MSSQL Memory Tuning on Windows VPS](/windows-server/mssql-memory-tuning) - [Windows Server Version Comparison](/windows-server/windows-server-version-comparison) - [Active Directory Domain Controller on Windows VPS](/windows-server/active-directory-domain-controller) - [Active Directory Replication Topology](/windows-server/ad-replication-topology) - [Raff Windows VPS](/products/windows-vm) ## Sources - Microsoft Learn — What is an Always On availability group? - Microsoft Learn — Prerequisites, restrictions, and recommendations for Always On availability groups - Microsoft Learn — Basic Always On availability groups for a single database - Microsoft Learn — Editions and supported features of SQL Server 2025 - Microsoft Learn — Create or configure an availability group listener - Microsoft Learn — Windows Server Failover Clustering with SQL Server - Date last verified: 2026-07-07 --- ### SQL Server 2025 Security Hardening on a Windows Server VPS (2026 MSP Guide) URL: https://rafftechnologies.com/windows-server/sql-server-2025-security-hardening-vps Description: Step-by-step SQL Server 2025 hardening on a Windows Server VPS: disable sa, least-privilege app logins, SQL Server Audit, TCP/IP enable, firewall scoping, and Let's Encrypt cert replacement. End-to-end MSP guide tested on Raff. ## In short SQL Server 2025 ships with much stronger default security than 2022 — mandatory TLS 1.3 encryption, PBKDF2 password hashing, RC4 disabled, TLS 1.0/1.1 deprecated. But three things still need manual hardening on every Raff Server install: replace the self-signed certificate with a real one (Let's Encrypt works), disable the `sa` account and use least-privilege application logins, and enable SQL Server Audit so you actually know who logged in and what they did. This guide walks through each step with T-SQL examples, verified on a live SQL Server 2025 Standard Developer install on Windows Server 2025. ## Who this guide is for You've installed SQL Server 2025 on a Raff Server (see our [SQL Server 2025 install guide](/windows-server/install-sql-server-2025-windows-server-vps)) and you want to take it to a production-ready security posture before exposing the instance to applications, internal users, or the internet. This guide is written for MSPs and DBAs who deploy SQL Server for clients and need a defensible, documented hardening checklist they can re-use. If you're a solo developer doing local dev work, you can skim Part 2 ("What you still need to do") and skip the Audit and certificate sections — they're for production deployments. ## What you'll need - **A working SQL Server 2025 install** on a Raff Windows Server, with the Database Engine running and reachable from your admin workstation - **Sysadmin access** to the SQL instance — either via `sa` (which we'll disable as part of this guide) or a Windows-authenticated admin (preferred, what we'll use throughout) - **PowerShell admin access** to the Raff Server — we use `Invoke-Sqlcmd` for most steps - **A domain you control** if you plan to follow Part 2's certificate replacement section — Let's Encrypt cannot issue certs for IP addresses or for Raff's rDNS hostnames, you need your own DNS-resolvable name - **Estimated time:** 60-90 minutes for the full hardening pass ## About the examples in this guide Several commands in this guide contain placeholder values you must substitute before running. They are intentionally documentation-friendly (RFC 5737 IPs, example domains, obvious password patterns) so they will not work in production without replacement: | Placeholder | Replace with | |---|---| | `customeracme.com` / `sql.customeracme.com` | A domain you actually own and control | | `203.0.113.10/32`, `198.51.100.42/32` | Your admin/office public IP (find via `ifconfig.me` or `ipinfo.io`) | | `TempStrongPassword2026!ReplaceMe` | A 16+ character password generated by your password manager | | `StrongMasterKeyPassword2026!`, `StrongCertPrivateKeyPassword2026!` | Distinct strong passwords stored in your password manager and a backup off-server | | `PASTE_THUMBPRINT_HERE_LOWERCASE` | The actual SHA-1 thumbprint of your certificate (from `Get-ChildItem Cert:\LocalMachine\My`) | | `` | Your Raff Server's actual public IPv4 address | If a command produces a "login failed" or "address invalid" error after you run it, double-check that you substituted every placeholder. Copy-pasting verbatim will not work. ## Part 1 — What's already secure-by-default in SQL Server 2025 Microsoft made significant security changes in SQL Server 2025 that prior hardening guides assumed you had to enable manually. **You don't.** Skip these, but verify they're actually on. ### TLS 1.3 + TDS 8.0 enforced encryption Per [Microsoft's "Secure by default" announcement](https://techcommunity.microsoft.com/blog/sqlserver/secure-by-default-what%E2%80%99s-new-in-sql-server-2025-security/4424340), SQL Server 2025 uses TDS 8.0 + TLS 1.3 for several internal communication paths by default — SQL Server Agent, replication, linked servers, log shipping, Always On AGs. Encryption is enforced from the very first packet, no negotiation phase. Client connections from modern drivers (ODBC 18, OLE DB 19, .NET SqlClient) default to `Encrypt=True`. This is a fundamental change. Old SQL hardening guides told you to "enable Force Encryption" — in 2025 it's effectively the default for first-party tools. **What you should still verify** (rather than configure): ```powershell # Check what TLS protocols Windows Schannel allows $base = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols' foreach ($p in 'TLS 1.0','TLS 1.1','TLS 1.2','TLS 1.3') { $path = "$base\$p\Server" $val = (Get-ItemProperty -Path $path -Name Enabled -ErrorAction SilentlyContinue).Enabled Write-Host "$p Server Enabled: $val" } ``` On a fresh Windows Server 2025, this returns blank/null for all four. **Don't panic — that's normal.** When SCHANNEL registry keys don't exist, Windows uses its built-in defaults. On Server 2025 those defaults are: TLS 1.0 and 1.1 disabled, TLS 1.2 and 1.3 enabled. The absence of registry entries means "use defaults", not "everything is off." You only need to set these registry keys if you want to **explicitly disable** TLS 1.2 in the future (TLS 1.3 only) or if you're chasing a compliance audit that requires explicit configuration. ### PBKDF2 password hashing Pre-2025, SQL Server hashed SQL login passwords with a single SHA-512 pass and a 32-bit salt. SQL 2025 replaces this with PBKDF2/RFC2898 using SHA-512 and 100,000 iterations. Brute-force attacks against stolen hash dumps are now orders of magnitude slower. This is automatic — if you create a new SQL login on SQL 2025, it gets the new algorithm. There's nothing to configure. If you migrated logins from a 2022 instance, those keep their old hashes until the password is changed. **Practical implication:** force a password rotation on every SQL login during your 2022 → 2025 migration so they pick up the stronger hash. ### Other secure-by-default items - **RC4 Kerberos disabled** by Windows Server 2025's security baseline - **TLS 1.0 / 1.1 disabled** at the OS level - **NTLMv1 removed** in Windows 11 24H2 / Server 2025 - **xp_cmdshell defaults to disabled** (verify, but don't expect to find it on) You can verify `xp_cmdshell` quickly: ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT name, value, value_in_use FROM sys.configurations WHERE name = 'xp_cmdshell'" ``` Expected: both `value` and `value_in_use` are `0`. If anything is `1`, see Part 2's xp_cmdshell section. ## Part 2 — What you still need to harden manually The default install gets you most of the way, but five things remain on every Raff Server SQL 2025 deployment. ### 1. Disable the `sa` account The `sa` (system administrator) login is the SQL Server equivalent of `root` — it has full server-level control, can't be removed, and is the #1 brute-force target on internet-exposed SQL Servers. Even with strong passwords, the existence of an enabled `sa` account is a liability. **Before you disable, make sure you have an alternative sysadmin** — your Windows Authenticated Administrator added during install is the standard fallback: ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT sl.name AS LoginName, sl.is_disabled, CASE WHEN srm.role_principal_id IS NOT NULL THEN 'YES' ELSE 'no' END AS IsSysadmin FROM sys.sql_logins sl LEFT JOIN sys.server_role_members srm ON sl.principal_id = srm.member_principal_id AND srm.role_principal_id = (SELECT principal_id FROM sys.server_principals WHERE name = 'sysadmin') WHERE sl.name = 'sa' UNION ALL SELECT sp.name, sp.is_disabled, CASE WHEN srm.role_principal_id IS NOT NULL THEN 'YES' ELSE 'no' END FROM sys.server_principals sp LEFT JOIN sys.server_role_members srm ON sp.principal_id = srm.member_principal_id AND srm.role_principal_id = (SELECT principal_id FROM sys.server_principals WHERE name = 'sysadmin') WHERE sp.type IN ('U','G') AND sp.is_disabled = 0 "@ ``` You should see at least one Windows login with `IsSysadmin: YES` (typically `HOSTNAME\Administrator`). Confirm you can log in using that account through SSMS or `sqlcmd -E` (Trusted Connection) before disabling sa. **Disable sa:** ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query "ALTER LOGIN sa DISABLE;" # Verify Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT name, type_desc, is_disabled, modify_date FROM sys.server_principals WHERE name = 'sa' "@ ``` Expected: `is_disabled: True`, `modify_date` stamped to right now. #### Optional: also rename the sa account Some MSPs additionally rename `sa` to make brute-force scripts (which usually try the literal name "sa") miss the target entirely. Both rename and disable is the most defensible posture: ```sql -- Rename first, then disable the renamed account ALTER LOGIN sa WITH NAME = sa_disabled_20260430; ALTER LOGIN sa_disabled_20260430 DISABLE; ``` This breaks any application or script that hardcoded `sa` as a connection username — which is exactly the point. Document the renamed login somewhere visible to anyone who'll inherit the server (runbook, secrets manager note, etc.) so emergency recovery doesn't get blocked by name confusion. #### What if you accidentally lock yourself out? If you disable `sa` AND lose access to your Windows admin login, recovery requires single-user-mode tricks — boot SQL with `-m` flag, log in as a Windows admin, re-enable sa or grant another login sysadmin. Microsoft documents the procedure at [Connect to SQL Server when system administrators are locked out](https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/security/connect-to-sql-server-when-locked-out). ### 2. Create least-privilege application logins Every application that talks to SQL Server should have its **own** login, scoped to the **specific database it needs**, with the **minimum permissions** to do its work. Not sysadmin. Not db_owner. Almost never has cross-database permissions. Here's a complete example creating a login for a hypothetical app called `RaffApp01`: ```sql -- Create the application database (skip if it already exists) CREATE DATABASE RaffApp01; -- Create the server-level login with strong policy enforcement CREATE LOGIN app_raffapp01 WITH PASSWORD = 'TempStrongPassword2026!ReplaceMe', DEFAULT_DATABASE = RaffApp01, CHECK_EXPIRATION = ON, CHECK_POLICY = ON; -- Map login to a database user inside RaffApp01 USE RaffApp01; CREATE USER app_raffapp01 FOR LOGIN app_raffapp01; -- Grant only what an app needs: read + write within this DB ALTER ROLE db_datareader ADD MEMBER app_raffapp01; ALTER ROLE db_datawriter ADD MEMBER app_raffapp01; -- Optional: allow EXECUTE on stored procedures (if your app uses procs) -- GRANT EXECUTE TO app_raffapp01; ``` Key points in this script: - **`CHECK_EXPIRATION = ON`** — password is subject to Windows password policy expiration. The app's password rotation becomes a forced operational discipline rather than a forgotten config item. - **`CHECK_POLICY = ON`** — Windows complexity rules apply. SQL refuses passwords below the local security policy minimum (length, character classes). - **`DEFAULT_DATABASE`** — login lands in its app database by default, not `master`. Limits the blast radius of a misconfigured connection string. - **`db_datareader` and `db_datawriter` only** — login can read and write data in this DB but cannot create/drop tables, modify schema, grant permissions to others, or touch any other database. **Verify it worked:** ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT sl.name AS Login, sl.is_disabled, sl.default_database_name, sl.is_policy_checked, sl.is_expiration_checked, CASE WHEN srm.role_principal_id IS NOT NULL THEN 'YES' ELSE 'no' END AS IsSysadmin FROM sys.sql_logins sl LEFT JOIN sys.server_role_members srm ON sl.principal_id = srm.member_principal_id AND srm.role_principal_id = (SELECT principal_id FROM sys.server_principals WHERE name = 'sysadmin') WHERE sl.name = 'app_raffapp01' "@ ``` Expected output: - `is_disabled: False` - `default_database_name: RaffApp01` - `is_policy_checked: True` - `is_expiration_checked: True` - `IsSysadmin: no` ← **the most important line** And inside the database: ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Database "RaffApp01" -Query @" SELECT dp.name AS DBUser, USER_NAME(rm.role_principal_id) AS RoleMembership FROM sys.database_principals dp LEFT JOIN sys.database_role_members rm ON dp.principal_id = rm.member_principal_id WHERE dp.name = 'app_raffapp01' "@ ``` Expected: two rows — one for `db_datareader`, one for `db_datawriter`. No `db_owner`. #### Why this matters: the `db_owner` and sysadmin trap A startlingly large number of production SQL deployments give every app login `db_owner` (or worse, sysadmin). Two reasons: 1. **It's easier.** Devs hit a permission error during local testing, the DBA grants db_owner to make the error go away, and that "temporary" grant ships to production. 2. **Frameworks/ORMs sometimes need it.** Some EF migrations, Hibernate schema updates, etc. *want* DDL rights to auto-create tables. For Reason 1: don't. Diagnose the actual permission needed and grant only that. For Reason 2: have **two** logins per app — a "schema owner" login used only during deployments (db_owner permissions, used by your migration tool), and a "runtime" login used by the live app (db_datareader + db_datawriter). The runtime login can never accidentally drop a table. ### 3. Enable SQL Server Audit SQL Server Audit is the canonical answer to "who logged in and what did they do" in any production SQL deployment. It's a free feature of all editions including Standard Developer and Express. There is no excuse not to use it. We'll create: - A **Server Audit** (the WHERE — file path on disk for log storage) - A **Server Audit Specification** (the WHAT — which events to log) - Then enable both ```powershell # Create the audit folder first New-Item -ItemType Directory -Path "C:\SQL\Audit" -Force ``` ```sql -- 1. Create the audit target (where logs go) CREATE SERVER AUDIT Raff_SecurityAudit TO FILE ( FILEPATH = 'C:\SQL\Audit\', MAXSIZE = 100 MB, MAX_ROLLOVER_FILES = 10, RESERVE_DISK_SPACE = OFF ) WITH ( QUEUE_DELAY = 1000, ON_FAILURE = CONTINUE ); -- 2. Create the audit specification (what events to log) CREATE SERVER AUDIT SPECIFICATION Raff_SecurityAudit_Spec FOR SERVER AUDIT Raff_SecurityAudit ADD (FAILED_LOGIN_GROUP), ADD (SUCCESSFUL_LOGIN_GROUP), ADD (LOGOUT_GROUP), ADD (SERVER_ROLE_MEMBER_CHANGE_GROUP), ADD (DATABASE_ROLE_MEMBER_CHANGE_GROUP), ADD (SERVER_PERMISSION_CHANGE_GROUP), ADD (DATABASE_PERMISSION_CHANGE_GROUP), ADD (SERVER_OBJECT_PERMISSION_CHANGE_GROUP), ADD (DATABASE_OBJECT_PERMISSION_CHANGE_GROUP), ADD (SCHEMA_OBJECT_CHANGE_GROUP), ADD (DATABASE_PRINCIPAL_CHANGE_GROUP), ADD (SERVER_PRINCIPAL_CHANGE_GROUP), ADD (DATABASE_CHANGE_GROUP) WITH (STATE = ON); -- 3. Enable the audit target ALTER SERVER AUDIT Raff_SecurityAudit WITH (STATE = ON); ``` #### What each action group captures | Group | Captures | |---|---| | FAILED_LOGIN_GROUP | Every failed login attempt (your brute-force detector) | | SUCCESSFUL_LOGIN_GROUP | Every successful login (your forensic timeline) | | LOGOUT_GROUP | Session terminations | | SERVER_ROLE_MEMBER_CHANGE_GROUP | "X was added to sysadmin" | | DATABASE_ROLE_MEMBER_CHANGE_GROUP | "X was added to db_owner in DB Y" | | SERVER_PERMISSION_CHANGE_GROUP | GRANT / REVOKE / DENY at server level | | DATABASE_PERMISSION_CHANGE_GROUP | GRANT / REVOKE / DENY at database level | | SERVER_OBJECT_PERMISSION_CHANGE_GROUP | Permission changes on server-level objects | | DATABASE_OBJECT_PERMISSION_CHANGE_GROUP | Permission changes on tables, views, procs | | SCHEMA_OBJECT_CHANGE_GROUP | CREATE / ALTER / DROP table, view, proc | | DATABASE_PRINCIPAL_CHANGE_GROUP | CREATE / ALTER / DROP USER | | SERVER_PRINCIPAL_CHANGE_GROUP | CREATE / ALTER / DROP LOGIN | | DATABASE_CHANGE_GROUP | CREATE / ALTER / DROP DATABASE | Together these capture: every login attempt, every change to who has access to what, every schema modification. That's the foundation for both compliance reporting and incident response. #### Verify the audit is running ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT name, type_desc, is_state_enabled, create_date FROM sys.server_audits" Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT sas.name, sas.is_state_enabled, sasd.audit_action_name FROM sys.server_audit_specifications sas JOIN sys.server_audit_specification_details sasd ON sas.server_specification_id = sasd.server_specification_id ORDER BY sas.name, sasd.audit_action_name "@ ``` Both queries should return rows showing `is_state_enabled: True`. #### Read the audit log To prove it works, trigger a failed login and read it back: ```powershell # Trigger a deliberate failed login try { Invoke-Sqlcmd -ServerInstance "localhost" -Username "sa" -Password "WrongPassword123!" -Query "SELECT 1" -ErrorAction Stop } catch { Write-Host "Failed login triggered (expected)" -ForegroundColor Yellow } # Wait for the audit queue to flush (we set QUEUE_DELAY = 1000ms) Start-Sleep -Seconds 3 # Read the audit log Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT TOP 20 event_time, action_id, succeeded, server_principal_name, client_ip, application_name, statement FROM sys.fn_get_audit_file('C:\SQL\Audit\*.sqlaudit', DEFAULT, DEFAULT) WHERE action_id IN ('LGIF', 'LGIS') ORDER BY event_time DESC "@ ``` You should see the failed login captured with: - `action_id: LGIF` (LGIF = Login Failed; LGIS = Login Successful) - `succeeded: False` - `server_principal_name: sa` - `statement: Login failed for user 'sa'. Reason: An error occurred while evaluating the password.` The "evaluating the password" reason text is specific to disabled accounts — different from "wrong password" for an enabled account. SQL gives you actionable forensic detail in the audit log itself. #### A note on `client_ip` In our test, `client_ip` showed as `local machine` rather than `127.0.0.1`. This happens because connections to `localhost` from a `SqlClient` driver on the same box use **LPC (Local Procedure Call / Shared Memory) protocol**, not TCP/IP. The audit log records the protocol type rather than spoofing a TCP source IP. Remote TCP connections will show actual IP addresses. #### Querying the audit log for incident response This is the kind of query you'd run after suspicious activity: ```sql -- All failed logins in the last 24 hours, grouped by source IP SELECT client_ip, server_principal_name, COUNT(*) AS FailedAttempts, MIN(event_time) AS FirstAttempt, MAX(event_time) AS LastAttempt FROM sys.fn_get_audit_file('C:\SQL\Audit\*.sqlaudit', DEFAULT, DEFAULT) WHERE action_id = 'LGIF' AND event_time > DATEADD(HOUR, -24, GETUTCDATE()) GROUP BY client_ip, server_principal_name ORDER BY FailedAttempts DESC; -- All schema changes in the last 7 days SELECT event_time, server_principal_name, database_name, schema_name, object_name, statement FROM sys.fn_get_audit_file('C:\SQL\Audit\*.sqlaudit', DEFAULT, DEFAULT) WHERE action_id IN ('CR', 'AL', 'DR') AND event_time > DATEADD(DAY, -7, GETUTCDATE()) ORDER BY event_time DESC; ``` #### Audit log retention Our config (`MAXSIZE = 100 MB`, `MAX_ROLLOVER_FILES = 10`) gives ~1 GB of rolling logs. For compliance scenarios that require longer retention: - **Pull logs to centralized storage** — robocopy `C:\SQL\Audit\*.sqlaudit` to a network share or S3 bucket on a daily schedule - **Forward to SIEM** — many SIEM tools (Splunk, Sentinel, Datadog) have SQL Server Audit collectors - **Increase MAXSIZE and MAX_ROLLOVER_FILES** if disk space allows ### 4. Enable TCP/IP and tighten the firewall This is the most surprising finding from our live testing: **SQL Server 2025 with a default-instance Custom install ships with TCP/IP DISABLED at the protocol level.** All your local `Invoke-Sqlcmd` calls work because they use Shared Memory. But no remote client can connect to your instance until you explicitly enable TCP/IP. Old install guides (and even many SQL 2022 walkthroughs) assume TCP is on. Verify yours: ```powershell $tcpKey = 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQLServer\SuperSocketNetLib\Tcp' Get-ItemProperty -Path $tcpKey | Select-Object Enabled, ListenOnAllIPs, DisplayName ``` If `Enabled: 0`, TCP is off and remote clients cannot reach your instance. Enable it: ```powershell # Enable TCP/IP Set-ItemProperty -Path $tcpKey -Name Enabled -Value 1 # Restart SQL Server service for the change to take effect Restart-Service -Name MSSQLSERVER -Force # Verify Get-ItemProperty -Path $tcpKey | Select-Object Enabled, ListenOnAllIPs, DisplayName # Confirm SQL is now listening Test-NetConnection -ComputerName localhost -Port 1433 -InformationLevel Quiet ``` `Test-NetConnection` should now return `True`. #### Add the firewall rule with tight scope Now that TCP is reachable on the server side, restrict who can reach it. **Never** create a TCP 1433 rule with `RemoteAddress = Any` and leave it that way — automated scanners will find it within minutes and start brute-forcing. ```powershell # Create the rule with a placeholder Any scope first New-NetFirewallRule ` -DisplayName "SQL Server (TCP 1433)" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 1433 ` -RemoteAddress Any ` -Action Allow ` -Profile Any # Immediately tighten — replace 203.0.113.10 with YOUR admin/office public IP Set-NetFirewallRule ` -DisplayName "SQL Server (TCP 1433)" ` -RemoteAddress "203.0.113.10/32" # Verify Get-NetFirewallRule -DisplayName "SQL Server (TCP 1433)" | Get-NetFirewallAddressFilter | Select-Object @{n='Rule';e={'SQL Server (TCP 1433)'}}, RemoteAddress, LocalAddress ``` **Find your admin public IP** by visiting `ifconfig.me` or `ipinfo.io` from your admin workstation. Substitute it for `203.0.113.10/32` (which is an RFC 5737 documentation-only IP that doesn't route anywhere — safe to use as a placeholder, useless for real access control). For multiple admin IPs, use a comma-separated list: `-RemoteAddress "203.0.113.10/32, 198.51.100.42/32"`. For a small office with a dynamic IP block, use the CIDR: `-RemoteAddress "203.0.113.0/24"`. #### Better than IP allowlisting: tunneled access For production deployments where your admin IP changes (working from home, traveling, hot-desking), IP allowlisting becomes operational pain. Three better patterns: - **VPN to your Raff Server's network**, then 1433 only allows `LocalSubnet` - **SSH tunnel** through a separate Raff Server acting as a bastion, then 1433 listens on `127.0.0.1` only and is reached via local-port-forward - **Cloudflare Tunnel** or similar zero-trust proxy with per-user identity-based access For most MSP deployments, IP allowlisting is fine and the simplest answer. Use the better patterns when client requirements push you there. ### 5. Replace SQL Server's self-signed certificate Even though encryption is on by default in 2025, the certificate SQL Server ships with is **auto-generated and self-signed**. This is the weakest link in the secure-by-default chain because: - ODBC Driver 18 / OLE DB Driver 19 reject self-signed certs by default (`TrustServerCertificate=False` is the new default) - Linked servers between SQL 2025 instances **break entirely** if one side uses a self-signed cert - Apps connecting with modern .NET drivers see "certificate chain not trusted" errors - Replication, log shipping, Always On all fail You have three workable choices: 1. **Let's Encrypt (recommended for most Raff deployments)** — free, public CA, trusted by every modern OS automatically. Requires a domain name you control. 2. **Internal Certificate Authority** — for AD-joined environments with existing PKI infrastructure. More setup, more enterprise. 3. **Properly-formed self-signed cert with SAN entries** — for fully air-gapped deployments without DNS or internal CA. This guide covers the Let's Encrypt path because it's the most common Raff Server scenario and the simplest to operate. #### Prerequisite: a domain name and DNS record **You need a domain you own** (e.g. `customeracme.com`). Raff's reverse-DNS hostnames (`xxx-xxx-xxx-xxx.raffusercloud.com`) cannot be used for Let's Encrypt — the customer needs to bring their own domain. Create a DNS A record pointing your chosen subdomain at the Raff Server's public IP: ``` sql.customeracme.com. A ``` Wait for DNS propagation (5-15 minutes typically; you can check with `nslookup sql.customeracme.com 8.8.8.8`). #### Install win-acme [win-acme](https://www.win-acme.com/) is the most reliable Windows ACME client for Let's Encrypt. Download the latest release ZIP, extract to `C:\Program Files\win-acme\`, run as admin. #### Issue the certificate For SQL Server, we want a certificate stored in the **Local Machine\Personal** certificate store, with the private key marked exportable so SQL can read it. win-acme handles this: ```powershell # From an admin PowerShell session cd "C:\Program Files\win-acme" .\wacs.exe ` --target manual ` --host sql.customeracme.com ` --validation http-01 ` --validationport 80 ` --store certificatestore ` --certificatestore My ` --installation script ` --script "scripts\ImportSqlServer.ps1" ``` The HTTP-01 validation requires port 80 to be temporarily reachable from the internet — Let's Encrypt's servers will hit `http://sql.customeracme.com/.well-known/acme-challenge/...` to verify domain control. If port 80 is blocked, use DNS-01 validation instead (requires DNS API integration). #### Bind the certificate to SQL Server After win-acme imports the certificate, find its thumbprint: ```powershell Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object Subject -like "*sql.customeracme.com*" | Select-Object Subject, Thumbprint, NotAfter ``` Copy the thumbprint, then write it into SQL Server's registry: ```powershell $thumbprint = "PASTE_THUMBPRINT_HERE_LOWERCASE" $regPath = 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQLServer\SuperSocketNetLib' Set-ItemProperty -Path $regPath -Name Certificate -Value $thumbprint # Grant the SQL service account read access to the private key $cert = Get-ChildItem -Path Cert:\LocalMachine\My\$thumbprint $keyPath = "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$($cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)" $acl = Get-Acl $keyPath $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\MSSQLSERVER", "Read", "Allow") $acl.AddAccessRule($rule) Set-Acl $keyPath $acl # Restart SQL Server to pick up the new cert Restart-Service -Name MSSQLSERVER -Force ``` Verify the new certificate is in use: ```powershell # Check the SQL error log — it'll log which certificate it loaded Get-Content "C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\Log\ERRORLOG" | Select-String -Pattern "certificate" ``` You should see a line like `The certificate [Cert Hash(sha1) "..."] was successfully loaded for encryption.` matching your new thumbprint. #### Auto-renewal Let's Encrypt certs expire every 90 days. win-acme installs a Windows scheduled task at install that runs daily and renews any certs ≤ 30 days from expiry. It also re-runs the `ImportSqlServer.ps1` post-install script automatically — but **the SQL Service won't reload the new cert until restart**. Add a service restart to your renewal script, or accept that you'll restart SQL once every 90 days at renewal time (most production SQL deployments restart for cumulative updates more often than that anyway). ### 6. TDE — Transparent Data Encryption (briefly) TDE encrypts your database files at rest (`.mdf`, `.ndf`, `.ldf`) and backup files. If someone steals your disk image or backup file, they can't restore it without your encryption key. **TDE is available on Standard, Enterprise, and Developer editions.** Express does not support TDE — if you're on Express, your data files are unencrypted at rest. If that's unacceptable, BitLocker on the underlying volume is a partial substitute. We're not going deep on TDE in this article because: - It involves a Database Master Key, a Server Certificate, and a Database Encryption Key — all of which need backup/recovery procedures or you can lose your data permanently - Backup encryption (covered next) is often the bigger compliance win for less complexity - Full TDE setup with proper key management deserves its own article The minimum viable TDE setup: ```sql -- 1. Master key in master DB USE master; CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'StrongMasterKeyPassword2026!'; -- 2. Certificate in master DB CREATE CERTIFICATE Raff_TDE_Cert WITH SUBJECT = 'Raff TDE Certificate'; -- 3. BACKUP THE CERTIFICATE IMMEDIATELY — losing it means losing your data BACKUP CERTIFICATE Raff_TDE_Cert TO FILE = 'C:\SQL\Backups\Raff_TDE_Cert.cer' WITH PRIVATE KEY ( FILE = 'C:\SQL\Backups\Raff_TDE_Cert.pvk', ENCRYPTION BY PASSWORD = 'StrongCertPrivateKeyPassword2026!' ); -- 4. Enable TDE on a specific database USE RaffApp01; CREATE DATABASE ENCRYPTION KEY WITH ALGORITHM = AES_256 ENCRYPTION BY SERVER CERTIFICATE Raff_TDE_Cert; ALTER DATABASE RaffApp01 SET ENCRYPTION ON; ``` **Critically: copy `Raff_TDE_Cert.cer` and `Raff_TDE_Cert.pvk` (and the password) to off-server secure storage.** If the Raff Server fails and you have only the encrypted database files, you cannot restore them without these certificate files. This is the #1 way TDE causes data loss in practice. ### 7. Backup encryption A simpler win than full TDE: encrypt **just the backup files**. This protects against backup theft / leakage without the operational complexity of TDE on the live data files. Available on all editions of SQL Server 2025 — Express included. ```sql -- Use the same Raff_TDE_Cert from the TDE section, OR create a backup-specific one USE master; CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'StrongMasterKeyPassword2026!'; CREATE CERTIFICATE Raff_Backup_Cert WITH SUBJECT = 'Raff Backup Encryption'; -- Backup the certificate to off-server storage immediately BACKUP CERTIFICATE Raff_Backup_Cert TO FILE = 'C:\SQL\Backups\Raff_Backup_Cert.cer' WITH PRIVATE KEY ( FILE = 'C:\SQL\Backups\Raff_Backup_Cert.pvk', ENCRYPTION BY PASSWORD = 'StrongCertPrivateKeyPassword2026!' ); -- Encrypted backup BACKUP DATABASE RaffApp01 TO DISK = 'C:\SQL\Backups\RaffApp01_Encrypted.bak' WITH COMPRESSION, ENCRYPTION ( ALGORITHM = AES_256, SERVER CERTIFICATE = Raff_Backup_Cert ); ``` Restoring an encrypted backup requires the certificate to exist in the destination instance. If you're restoring on a different server, restore the certificate first with `CREATE CERTIFICATE FROM FILE`. Same warning as TDE: **keep the cert + private key + password in off-server storage**. Lose them and you've encrypted your own backups out of reach. ### 8. Patching cadence Microsoft ships SQL Server 2025 cumulative updates roughly every 60-90 days. Each CU contains security fixes, bug fixes, and minor performance improvements. **CU1 alone fixed CVE-2026-32176**, an elevation-of-privilege vulnerability in linked servers. Production patching standard: - **CU within 30 days of release** for security-relevant CUs - **CU within 60 days** for general CUs - **Subscribe to** the [SQL Server release notes RSS feed](https://learn.microsoft.com/en-us/sql/sql-server/sql-server-release-versions) — Microsoft posts every CU here - **Apply CUs to a non-production instance first**, run your test suite, then promote - **Take a database backup before applying any CU** — CUs apply Windows-side and aren't trivially reversible To check your current build vs available CUs: ```powershell Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT @@VERSION, SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('ProductUpdateLevel')" ``` Compare the result to [Microsoft's SQL Server 2025 build list](https://learn.microsoft.com/en-us/troubleshoot/sql/releases/sqlserver-2025/cumulative-update1). ## Part 3 — MSP handoff checklist For MSPs deploying SQL Server 2025 for clients, this is the scannable checklist to copy into your client runbook. Every box should be ticked before handing off. ``` SQL SERVER 2025 HARDENING — RAFF SERVER DEPLOYMENT CHECKLIST INSTANCE BASICS [ ] SQL Server 2025 installed on Windows Server 2025 [ ] Windows pending-restart cleared before install [ ] Latest Cumulative Update applied (target: CU1 or later) [ ] Mixed Mode auth (only if app requires SQL logins; otherwise Windows-only) [ ] Volume Maintenance Tasks privilege granted to SQL service [ ] SQL Server Agent set to Automatic startup ACCOUNT HARDENING [ ] sa account disabled [ ] sa account renamed (optional but recommended for internet-exposed instances) [ ] Windows admin account verified working as backup sysadmin [ ] Per-application logins created with CHECK_POLICY = ON, CHECK_EXPIRATION = ON [ ] Each app login has only db_datareader + db_datawriter (not db_owner, not sysadmin) [ ] No app login has cross-database permissions NETWORK HARDENING [ ] TCP/IP enabled at SuperSocketNetLib registry level [ ] SQL service restarted after enabling TCP/IP [ ] Windows Firewall rule for TCP 1433 created [ ] Firewall rule scoped to specific admin IPs (not Any) [ ] No public exposure of TCP 1433 to 0.0.0.0/0 ENCRYPTION [ ] Self-signed certificate replaced with trusted CA cert (Let's Encrypt or internal CA) [ ] Certificate has FQDN + NetBIOS name in SAN [ ] SQL service granted read access to certificate private key [ ] win-acme renewal task scheduled (if using Let's Encrypt) [ ] TDE configured if compliance requires (with certificate backup off-server) [ ] Backup encryption configured (with certificate backup off-server) AUDITING [ ] Server Audit created with file target on dedicated path (C:\SQL\Audit\) [ ] Server Audit Specification created with login, role, permission, schema, principal action groups [ ] Both audit objects enabled (STATE = ON) [ ] Failed login test event captured in audit log (verified via sys.fn_get_audit_file) [ ] Audit log retention strategy defined (centralized storage / SIEM forwarding) OPERATIONAL [ ] Database backups configured with encryption + off-server storage [ ] Backup encryption certificate backed up to off-server secure storage [ ] Database Master Key backed up off-server [ ] CU patching cadence agreed with client (30/60-day SLA) [ ] SQL Server build documented in client runbook [ ] Emergency contacts and recovery procedures documented [ ] Audit log query templates saved for incident response CLIENT HANDOFF [ ] sa password and admin credentials in client password manager (not yours) [ ] Database master key password in client password manager [ ] Certificate private key password in client password manager [ ] Documentation of all customizations vs Microsoft defaults [ ] First-90-day support window defined ``` ## Part 4 — Verify the hardening worked After completing all sections of Part 2, run this consolidated PowerShell script as an admin on the Raff Server. It checks every hardening item we configured and prints a green/red status. Use it as a smoke test after initial hardening, and re-run it on a schedule (weekly or monthly) to detect drift — someone re-enabling sa, an audit getting accidentally turned off, the firewall rule being widened, etc. ```powershell Write-Host "`n=== SQL Server 2025 Hardening Verification ===" -ForegroundColor Cyan Write-Host "Run as Administrator on the Raff Server`n" -ForegroundColor DarkGray # 1. sa account disabled Write-Host "1. sa account state" -ForegroundColor Cyan $saState = Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT is_disabled FROM sys.server_principals WHERE name = 'sa'" if ($saState.is_disabled) { Write-Host " PASS: sa is disabled" -ForegroundColor Green } else { Write-Host " FAIL: sa is ENABLED — disable with ALTER LOGIN sa DISABLE;" -ForegroundColor Red } # 2. xp_cmdshell off Write-Host "`n2. xp_cmdshell state" -ForegroundColor Cyan $xp = Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT value_in_use FROM sys.configurations WHERE name = 'xp_cmdshell'" if ($xp.value_in_use -eq 0) { Write-Host " PASS: xp_cmdshell is disabled" -ForegroundColor Green } else { Write-Host " FAIL: xp_cmdshell is ENABLED — disable via sp_configure 'xp_cmdshell', 0; RECONFIGURE;" -ForegroundColor Red } # 3. App logins are NOT sysadmin Write-Host "`n3. SQL logins with sysadmin role (excluding sa)" -ForegroundColor Cyan $sysadmins = Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT sl.name FROM sys.sql_logins sl JOIN sys.server_role_members srm ON sl.principal_id = srm.member_principal_id JOIN sys.server_principals sp ON srm.role_principal_id = sp.principal_id WHERE sp.name = 'sysadmin' AND sl.name <> 'sa' "@ if ($sysadmins) { Write-Host " FAIL: SQL logins with sysadmin (review and remove unless intentional):" -ForegroundColor Red $sysadmins | ForEach-Object { Write-Host " - $($_.name)" -ForegroundColor Red } } else { Write-Host " PASS: no non-sa SQL logins are sysadmin" -ForegroundColor Green } # 4. SQL logins missing password policy enforcement Write-Host "`n4. SQL logins without CHECK_POLICY = ON" -ForegroundColor Cyan $weakLogins = Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT name FROM sys.sql_logins WHERE is_policy_checked = 0 AND name NOT LIKE '##%' AND name <> 'sa' "@ if ($weakLogins) { Write-Host " WARN: SQL logins without password policy:" -ForegroundColor Yellow $weakLogins | ForEach-Object { Write-Host " - $($_.name)" -ForegroundColor Yellow } } else { Write-Host " PASS: all non-sa SQL logins enforce password policy" -ForegroundColor Green } # 5. SQL Server Audit enabled Write-Host "`n5. SQL Server Audit state" -ForegroundColor Cyan $audits = Invoke-Sqlcmd -ServerInstance "localhost" -Query "SELECT name, is_state_enabled FROM sys.server_audits" if ($audits -and ($audits | Where-Object is_state_enabled -eq $true)) { Write-Host " PASS: at least one Server Audit is running" -ForegroundColor Green $audits | ForEach-Object { Write-Host " - $($_.name): enabled=$($_.is_state_enabled)" -ForegroundColor DarkGray } } else { Write-Host " FAIL: no Server Audit is enabled" -ForegroundColor Red } # 6. Audit specification covers login events Write-Host "`n6. Audit specification action groups" -ForegroundColor Cyan $auditSpecs = Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT sasd.audit_action_name FROM sys.server_audit_specifications sas JOIN sys.server_audit_specification_details sasd ON sas.server_specification_id = sasd.server_specification_id WHERE sas.is_state_enabled = 1 "@ $expected = @('FAILED_LOGIN_GROUP','SUCCESSFUL_LOGIN_GROUP','SERVER_ROLE_MEMBER_CHANGE_GROUP','SCHEMA_OBJECT_CHANGE_GROUP') $captured = $auditSpecs.audit_action_name $missing = $expected | Where-Object { $_ -notin $captured } if (-not $missing) { Write-Host " PASS: critical action groups captured" -ForegroundColor Green } else { Write-Host " WARN: action groups missing from audit:" -ForegroundColor Yellow $missing | ForEach-Object { Write-Host " - $_" -ForegroundColor Yellow } } # 7. TCP/IP enabled at protocol level Write-Host "`n7. SQL Server TCP/IP protocol" -ForegroundColor Cyan $tcpKey = 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQLServer\SuperSocketNetLib\Tcp' $tcp = Get-ItemProperty -Path $tcpKey -ErrorAction SilentlyContinue if ($tcp.Enabled -eq 1) { Write-Host " PASS: TCP/IP is enabled" -ForegroundColor Green } else { Write-Host " FAIL: TCP/IP is DISABLED — remote clients cannot connect" -ForegroundColor Red } # 8. Firewall rule for 1433 has restricted scope Write-Host "`n8. Firewall rule scope for TCP 1433" -ForegroundColor Cyan $fwRules = Get-NetFirewallPortFilter -Protocol TCP | Where-Object LocalPort -eq 1433 | ForEach-Object { $_ | Get-NetFirewallRule | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' } } if (-not $fwRules) { Write-Host " WARN: no inbound Allow rule for TCP 1433 (remote clients will be blocked)" -ForegroundColor Yellow } else { foreach ($rule in $fwRules) { $scope = ($rule | Get-NetFirewallAddressFilter).RemoteAddress if ($scope -eq 'Any') { Write-Host " FAIL: rule '$($rule.DisplayName)' allows TCP 1433 from ANY remote IP" -ForegroundColor Red } else { Write-Host " PASS: rule '$($rule.DisplayName)' scoped to $scope" -ForegroundColor Green } } } # 9. SQL Server certificate (is it self-signed or CA-issued?) Write-Host "`n9. SQL Server TLS certificate" -ForegroundColor Cyan $certThumb = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQLServer\SuperSocketNetLib' -Name Certificate -ErrorAction SilentlyContinue).Certificate if (-not $certThumb) { Write-Host " WARN: no explicit certificate configured — SQL is using auto-generated self-signed cert" -ForegroundColor Yellow Write-Host " Modern drivers reject self-signed by default. Replace with Let's Encrypt or internal CA." -ForegroundColor DarkGray } else { $cert = Get-ChildItem -Path Cert:\LocalMachine\My\$certThumb -ErrorAction SilentlyContinue if ($cert.Issuer -eq $cert.Subject) { Write-Host " WARN: configured certificate is self-signed (Issuer = Subject)" -ForegroundColor Yellow } else { Write-Host " PASS: certificate issued by external CA" -ForegroundColor Green Write-Host " Issuer: $($cert.Issuer)" -ForegroundColor DarkGray Write-Host " Subject: $($cert.Subject)" -ForegroundColor DarkGray Write-Host " Expires: $($cert.NotAfter)" -ForegroundColor DarkGray } } # 10. Recent failed login attempts (last 24h) — useful for spotting attacks Write-Host "`n10. Failed logins in the last 24 hours" -ForegroundColor Cyan try { $failedLogins = Invoke-Sqlcmd -ServerInstance "localhost" -Query @" SELECT client_ip, server_principal_name, COUNT(*) AS FailedAttempts FROM sys.fn_get_audit_file('C:\SQL\Audit\*.sqlaudit', DEFAULT, DEFAULT) WHERE action_id = 'LGIF' AND event_time > DATEADD(HOUR, -24, GETUTCDATE()) GROUP BY client_ip, server_principal_name ORDER BY FailedAttempts DESC "@ -ErrorAction Stop if (-not $failedLogins) { Write-Host " PASS: no failed login attempts in last 24 hours" -ForegroundColor Green } else { Write-Host " INFO: failed login activity detected:" -ForegroundColor Yellow $failedLogins | Format-Table -AutoSize } } catch { Write-Host " SKIP: audit log not readable (audit may not be enabled or path is wrong)" -ForegroundColor DarkGray } Write-Host "`n=== Verification complete ===" -ForegroundColor Cyan Write-Host "Re-run weekly to detect drift.`n" -ForegroundColor DarkGray ``` ### How to use this script **For initial hardening:** Run it once after completing every section in Part 2. Every check should return `PASS`. Any `FAIL` or `WARN` is a hardening gap to close. **For ongoing monitoring:** Schedule it to run weekly via Task Scheduler, log output to a file, alert on `FAIL` lines: ```powershell # Save the script as C:\SQL\Scripts\Verify-SQLHardening.ps1 # Then schedule it weekly: $action = New-ScheduledTaskAction ` -Execute "PowerShell.exe" ` -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\SQL\Scripts\Verify-SQLHardening.ps1 *> C:\SQL\Audit\hardening-check.log" $trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 6am Register-ScheduledTask ` -TaskName "SQL Hardening Verification" ` -Action $action ` -Trigger $trigger ` -RunLevel Highest ` -User "SYSTEM" ``` **For client handoff:** Run it in front of the client, save the output as a PDF, attach to the runbook. Repeat it 30 days post-deployment to confirm nothing has drifted. ## Tested on Raff > **Tested on:** SQL Server 2025 Standard Developer Edition (build 17.0.1000.7 RTM) on a Raff Windows Server 2025 — Production plan, 4 vCPU / 8 GB RAM / 120 GB NVMe, Windows Server 2025 Standard build 26100, us-east datacenter — on April 30, 2026, by Serdar Tekin. We verified end-to-end: sa login disable with audit-log capture of subsequent failed login attempt as evidence; least-privilege application login `app_raffapp01` created with CHECK_POLICY/CHECK_EXPIRATION enabled, scoped to db_datareader/db_datawriter only, IsSysadmin: no; SQL Server Audit `Raff_SecurityAudit` with 13 action groups including FAILED_LOGIN_GROUP / SUCCESSFUL_LOGIN_GROUP / SCHEMA_OBJECT_CHANGE_GROUP, file target at `C:\SQL\Audit\`, 100 MB max size with 10-file rollover, captured both LGIF and LGIS events with full metadata via `sys.fn_get_audit_file`; TCP/IP enabled at SuperSocketNetLib registry level (default state was DISABLED — significant finding for default-instance Custom installs); Windows Firewall rule for TCP 1433 with RemoteAddress scoped to `203.0.113.10/32` (RFC 5737 documentation IP — readers replace with their admin IP); xp_cmdshell verified at default off state. Certificate replacement (Let's Encrypt via win-acme) and TDE/backup encryption documented from Microsoft Learn references — not live-tested in this session due to test VM scope. ## What's next - [Connect to your Raff Windows Server via RDP](/windows-server/connect-to-windows-vps-rdp) — first-step access guide - [Windows Server 2019 vs 2022 vs 2025 — Which to Choose](/windows-server/windows-server-version-comparison) — OS choice fundamentals - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) — license multi-user RDP for DBAs and analysts - [Install SQL Server 2025 on Windows Server VPS](/windows-server/install-sql-server-2025-windows-server-vps) — the install guide that precedes this hardening guide - [Self-Host QuickBooks Desktop Multi-User on Windows Server](/windows-server/quickbooks-multi-user-windows-server-vps) — QuickBooks runs on top of SQL Server; harden the underlying SQL the same way ## Sources - Microsoft Learn — [Securing SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/security/securing-sql-server) - Microsoft Community Hub — [Secure by default: What's new in SQL Server 2025 security](https://techcommunity.microsoft.com/blog/sqlserver/secure-by-default-what%E2%80%99s-new-in-sql-server-2025-security/4424340) - Microsoft Community Hub — [TLS 1.3 in SQL Server 2025: What It Really Changes for Security](https://techcommunity.microsoft.com/blog/coreinfrastructureandsecurityblog/tls-1-3-in-sql-server-2025-what-it-really-changes-for-security/4491479) - Microsoft Learn — [TLS 1.3 support](https://learn.microsoft.com/en-us/sql/relational-databases/security/networking/tls-1-3) - Microsoft Learn — [Configure TLS 1.3 on SQL Server 2022 and later](https://learn.microsoft.com/en-us/sql/relational-databases/security/networking/connect-with-tls-1-3) - Microsoft Learn — [Encrypt connections by importing a certificate](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-sql-server-encryption) - Microsoft Learn — [Database Engine: Breaking Changes in SQL Server 2025](https://learn.microsoft.com/en-us/sql/database-engine/breaking-changes-to-database-engine-features-in-sql-server-2025) - Microsoft Learn — [SQL Server Audit (Database Engine)](https://learn.microsoft.com/en-us/sql/relational-databases/security/auditing/sql-server-audit-database-engine) - Microsoft Learn — [Server Audit Action Groups](https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-server-audit-specifications-transact-sql) - Microsoft Learn — [CHECK_POLICY and CHECK_EXPIRATION login options](https://learn.microsoft.com/en-us/sql/relational-databases/security/password-policy) - Microsoft Learn — [Transparent Data Encryption (TDE)](https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption) - Microsoft Learn — [Backup Encryption](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/backup-encryption) - Microsoft Learn — [Connect to SQL Server when system administrators are locked out](https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/security/connect-to-sql-server-when-locked-out) - Microsoft Learn — [SQL Server 2025 cumulative updates](https://learn.microsoft.com/en-us/troubleshoot/sql/releases/sqlserver-2025/cumulative-update1) - win-acme project — [win-acme.com](https://www.win-acme.com/) - Date last verified: 2026-04-30 --- *Microsoft, Windows Server, SQL Server, and SQL Server Management Studio are trademarks of Microsoft Corporation. Raff Technologies is an independent infrastructure provider and is not affiliated with, sponsored by, or endorsed by Microsoft Corporation.* --- ### SQL Server Migration to Windows VPS URL: https://rafftechnologies.com/windows-server/sql-server-migration-to-windows-vps Description: Plan a SQL Server migration to Windows VPS, including backup/restore, recovery model, logins, SQL Agent jobs, connection strings, app testing, cutover, and rollback. SQL Server migration to Windows VPS is not just copying database files. A safe migration needs a plan for backup and restore, recovery model, logins, users, SQL Agent jobs, maintenance plans, connection strings, firewall rules, application testing, final cutover, and rollback. Raff Technologies provides Windows VMs for teams that want a cloud-hosted Windows Server destination for SQL-backed business apps, ERP systems, inventory tools, Access applications, IIS/.NET workloads, and MSP client environments. SQL Server is usually invisible until something breaks. Users see the business application, but SQL Server may be holding orders, inventory, invoices, reports, customer records, transactions, and application settings behind the scenes. That is why SQL Server migration should be treated as a business continuity project. The database must restore correctly, applications must connect, logins must work, jobs must run, backups must be valid, and the rollback plan must be clear before production users move. ## Quick verdict: when SQL Server migration to Windows VPS makes sense Use this table before moving SQL Server to a Windows VPS. | Situation | Windows VPS fit | Why | |---|---|---| | Small business app depends on SQL Server | Good fit | SQL Server can move with the Windows app environment. | | ERP or inventory software needs cloud access | Good fit after testing | App, database, users, and reports can be centralized. | | Local office server is aging | Strong fit | SQL Server can move away from old hardware. | | MSP manages client SQL-backed apps | Strong fit | A repeatable Windows VPS environment is easier to document and support. | | IIS/.NET app uses SQL Server | Good fit | Web app and database migration can be planned together. | | Database workload is heavy or latency-sensitive | Depends | You may need separate app/database roles or performance testing. | | SQL Server version is old or unsupported | Review first | Compatibility, upgrade path, and app support must be checked. | | High availability is mandatory | Not a single VPS decision | Design redundancy, failover, and recovery architecture first. | The best fit is a small or mid-size SQL-backed Windows workload where the database, application, users, and backup strategy can be tested before cutover. :::cta Talk to Windows Engineer Review SQL Server databases, logins, jobs, app connections, backups, and cutover timing before migrating production workloads. ::: ## SQL Server migration is not file copy A SQL Server database is more than `.mdf` and `.ldf` files. A real migration may include: | Migration area | Examples | |---|---| | Databases | User databases, system dependencies, compatibility level | | Logins | SQL logins, Windows logins, passwords, SIDs | | Users and roles | Database users, fixed roles, custom roles | | SQL Agent jobs | Backups, reports, imports, exports, maintenance | | Maintenance plans | Index maintenance, cleanup, statistics, backup tasks | | Linked servers | Connections to other SQL instances or external systems | | Credentials and proxies | Job execution context and security | | Connection strings | App configs, web.config, ODBC, DSNs | | Firewall rules | SQL port access and application connectivity | | Backups | Full, differential, log backups, retention, restore testing | Microsoft's SQL Server backup and restore documentation describes backup and restore strategies, security considerations, and core backup terms. That is the safest starting point for most SMB migrations: restore a known backup on the destination and prove the app works before cutover. ![Architecture visual showing SQL Server migration to Windows VPS with databases, logins, jobs, connection strings, apps, and backups](https://raff-images.s3.raffusercloud.com/sql_server_migration_architecture_windows_vps_webp_94e69d8dbb.png) ## Backup/restore vs detach/attach vs copy wizard There are several ways to move SQL Server databases. The right method depends on downtime tolerance, database size, recovery model, version compatibility, and operational risk. | Method | What it means | Best fit | |---|---|---| | Backup and restore | Back up the source database and restore it on the destination | Most SMB migrations, repeatable tests, safer rollback | | Full + differential + log restore | Restore full backup, then later backups/logs for cutover | Larger databases or shorter final downtime | | Detach and attach | Detach database files and attach them to destination | Simple cases, but more disruptive and riskier if mishandled | | Copy Database Wizard | Moves/copies databases and some server objects between instances | Useful in some environments, but still requires testing | | Side-by-side SQL migration | Build destination SQL Server, test restore, then cut over apps | Best for controlled Windows VPS migration | Microsoft documents copying databases with backup and restore, and also describes the Copy Database Wizard as a way to move or copy databases and some server objects between SQL Server instances. For Raff Windows VPS migrations, backup/restore and side-by-side testing are usually the cleaner model. The old SQL Server stays available while the new Windows VPS is built, restored, tested, and prepared for cutover. ## Step 1: inventory SQL instances and databases Start with discovery. Document: | Inventory item | What to capture | |---|---| | SQL Server version | Version, edition, patch level | | Instance names | Default and named instances | | Databases | Names, sizes, owners, compatibility levels | | Recovery models | Simple, full, or bulk-logged | | Backup history | Full, differential, log backups, retention | | Logins | SQL logins, Windows logins, groups | | Users and roles | Database users, roles, schemas | | Jobs | SQL Agent jobs, schedules, enabled/disabled state | | Maintenance plans | Backup, index, cleanup, update statistics | | Linked servers | External connections and credentials | | Applications | Apps that connect to each database | | Connection strings | Server names, ports, instance names, credentials | | Firewall rules | SQL access between app and database | | Storage paths | Data, log, tempdb, backup locations | This inventory should answer: what must exist on the Windows VPS for the application to behave exactly as expected? ## Step 2: check recovery model, backup chain, and restore goals SQL Server recovery model affects your backup and restore plan. Microsoft explains that SQL Server backup and restore operations happen in the context of the database recovery model. The recovery model controls how transactions are logged, whether transaction log backups are required or allowed, and what restore operations are available. For migration planning: | Recovery model | Migration impact | |---|---| | Simple | Usually restore latest full or differential backup; point-in-time restore is limited | | Full | Requires transaction log backup planning if you want lower data loss | | Bulk-logged | Can affect point-in-time recovery depending on operations | Define two goals before cutover: | Goal | Meaning | |---|---| | RPO | How much data loss is acceptable during migration | | RTO | How long the app can be unavailable | For small databases, a final full backup and restore during downtime may be fine. For larger or busier databases, you may need full backup, differential backup, and transaction log backups to reduce the final cutover window. ## Step 3: plan SQL Server version and edition compatibility Do not migrate blindly between SQL Server versions. Check: | Compatibility item | What to verify | |---|---| | Source SQL version | Current version and patch level | | Destination SQL version | Target version supported by the app | | SQL edition | Express, Standard, Enterprise, Developer, or other | | Database compatibility level | Whether the app expects a specific level | | Deprecated features | Old features that may fail or warn | | SQL Server Express limits | Database size, memory, CPU, and Agent limitations | | Application support | Vendor support for target SQL version | | Collation | Instance and database collation behavior | | Drivers | ODBC/OLE DB/.NET drivers used by the app | A Windows VPS provides the Windows environment. SQL Server licensing, installation media, edition selection, and application support still need to be handled correctly. ## Step 4: migrate logins, users, roles, and permissions A database restore does not automatically solve every login problem. SQL Server has server-level logins and database-level users. If a database user is linked to a login that does not exist on the destination, the user can become orphaned. Microsoft documents this issue and provides guidance for finding and remapping orphaned users when a database is moved to another server. ![SQL Server migration dependency map showing logins, orphaned users, SQL Agent jobs, linked servers, maintenance plans, and connection strings](https://raff-images.s3.raffusercloud.com/sql_server_migration_dependencies_risk_map_webp_e2be9b550e.png) Plan: | Security object | What to migrate or verify | |---|---| | SQL logins | Names, SIDs, password handling | | Windows logins | Domain or local Windows accounts | | Server roles | sysadmin, securityadmin, dbcreator, etc. | | Database users | User-to-login mapping | | Database roles | db_owner, db_datareader, custom roles | | Schemas | Ownership and default schemas | | App service accounts | Accounts used by services or apps | | Contained users | Whether the app supports contained database users | Microsoft also has guidance for transferring logins and passwords between SQL Server instances. This matters because login mismatches are one of the most common "database restored but app cannot log in" problems. :::cta Explore Windows VM Use Raff Windows VM as the destination for SQL Server tools, business apps, remote users, and Windows workloads. ::: ## Step 5: migrate SQL Agent jobs, maintenance plans, and linked servers Many SQL-backed apps depend on scheduled jobs. Check: | Object | Migration question | |---|---| | SQL Agent jobs | Are backup, import, export, report, and cleanup jobs recreated? | | Job schedules | Are schedules correct on the destination? | | Job owners | Do job owners exist and have appropriate permissions? | | Maintenance plans | Are they recreated and enabled? | | Operators/alerts | Are notifications configured? | | Credentials/proxies | Do jobs that need external access still work? | | Linked servers | Are remote data connections recreated? | | SSIS packages | Are packages and connection managers moved? | | File paths | Do jobs use old server folders or drive letters? | | Email settings | Does Database Mail need configuration? | Microsoft describes SQL Server Agent as a Windows service that executes scheduled administrative tasks called jobs. Microsoft also notes that maintenance plans create Integration Services packages that are run by SQL Server Agent jobs. That means a SQL migration is incomplete if the database works but scheduled jobs silently stop. ## Step 6: restore the database on the Windows VPS For a backup/restore migration, restore the database to the destination Windows VPS and test before production cutover. ![SQL Server backup and restore migration flow showing source backup, restore to Windows VPS, testing, final backup, and cutover](https://raff-images.s3.raffusercloud.com/sql_server_backup_restore_migration_flow_webp_0e8363d333.png) A common test restore process: 1. Install SQL Server on the Windows VPS. 2. Patch SQL Server to the required level. 3. Configure storage paths for data, logs, tempdb, and backups. 4. Copy the test backup to the destination. 5. Restore the database with the planned file locations. 6. Check database integrity where appropriate. 7. Recreate logins, jobs, linked servers, and maintenance plans. 8. Map users to logins and fix orphaned users if needed. 9. Update test app connection string. 10. Run real application workflow tests. Do not wait until cutover day to discover that the backup does not restore, the app cannot log in, or the database needs a compatibility fix. ## Step 7: update connection strings and firewall rules After the database is restored, applications must connect to the new SQL Server. Common connection locations: | Location | Example | |---|---| | Web app config | `web.config`, appsettings, environment variables | | Desktop app config | INI, XML, registry, vendor settings | | ODBC DSN | System DSN or user DSN | | Linked apps | Accounting, ERP, inventory, Access, reporting tools | | Scheduled tasks | Scripts that connect to SQL Server | | Reporting tools | Power BI gateways, SSRS, Crystal Reports, custom reports | | Integration jobs | E-commerce sync, warehouse imports, exports | | IIS app pools | App pool identity or service account | Firewall planning matters too. Decide whether the app and SQL Server run on the same Windows VPS or separate servers. | Architecture | Firewall concern | |---|---| | App and SQL on same VPS | Local connections may be simpler | | App server and SQL server separate | Allow only required SQL traffic between servers | | Remote admin tools | Restrict SQL Server Management Studio access | | Branch apps | Avoid broad public SQL exposure | Do not expose SQL Server broadly to the public internet. Restrict access to required app servers, admin IPs, VPN/private networking, or controlled management paths. ## Step 8: test the business application A SQL Server migration is only successful when the app works. Test: | Test area | Example | |---|---| | Login | App users can sign in | | Read data | Users can open existing records | | Write data | Users can create and update records | | Reports | Reports generate correctly | | Exports | CSV, Excel, PDF, or accounting exports work | | Imports | Scheduled or manual imports run | | Permissions | Users see only what they should | | Performance | Common screens and reports respond acceptably | | Jobs | SQL Agent jobs run successfully | | Backups | New backup jobs complete | | Restore | At least one restore test succeeds | Use real business users for the test. The person who runs month-end reports, inventory exports, or accounting sync will catch problems an admin may miss. ## Step 9: run final backup, restore, and cutover When testing is complete, schedule a cutover window. A typical SQL cutover sequence: 1. Announce downtime. 2. Confirm source backup is healthy. 3. Stop application writes. 4. Take final full, differential, or log backup according to plan. 5. Copy final backup to the Windows VPS. 6. Restore final backup and log backups if required. 7. Recover database. 8. Confirm logins, users, jobs, and permissions. 9. Update connection strings or DNS aliases. 10. Start application services. 11. Test app login and key workflows. 12. Confirm backup jobs are running on destination. 13. Keep source server available for rollback. 14. Monitor the first business day closely. If the database uses the full recovery model and you are restoring log backups, follow a clear restore sequence. Microsoft's restore and recovery overview explains that restore scenarios depend on recovery model and SQL Server edition. ## Step 10: validate backups after migration After cutover, create a new backup plan on the Windows VPS. A practical SQL backup model: | Backup layer | Purpose | |---|---| | SQL full backup | Baseline database recovery | | SQL differential backup | Faster backup between full backups | | SQL log backup | Lower data loss for full recovery model databases | | VM backup | Recover the Windows VPS environment | | Snapshot before changes | Roll back infrastructure state before updates | | Off-server copy | Protect against VM, account, or ransomware incidents | | Restore test | Prove the backup can recover the app | Do not rely only on a VM snapshot for SQL Server recovery. SQL Server needs database-aware backup planning, especially when the business cares about transaction-level data loss. ![SQL Server migration recovery stack showing database backup, VM backup, snapshot, restore test, and rollback readiness](https://raff-images.s3.raffusercloud.com/sql_server_migration_cutover_recovery_stack_webp_9440b5a704.png) :::cta Explore Data Protection Protect your SQL Server migration with database backup, VM backup, snapshot, and restore planning before cutover. ::: ## Common SQL Server migration mistakes ### Restoring the database but not the logins The database exists, but the application cannot authenticate because logins were not migrated or users are orphaned. ### Forgetting SQL Agent jobs Backups, imports, exports, reports, and maintenance jobs may stop after migration if SQL Agent jobs are not recreated and enabled. ### Missing connection strings Apps, scripts, and reports may still point to the old SQL Server name or IP. ### Ignoring the recovery model Backup and restore planning depends on whether the database uses simple, full, or bulk-logged recovery model. ### Skipping application testing A successful restore is not enough. The application must read, write, report, export, and complete normal workflows. ### Exposing SQL Server too broadly SQL Server should not be opened to the public internet without strict access controls. Prefer private access, app-server-only access, or controlled admin paths. ### Not testing restore after migration A backup plan is not proven until restore has been tested. ## How Raff fits SQL Server migration Raff fits this use case when a small business or MSP wants a cloud Windows Server destination for SQL-backed Windows workloads. Raff Windows VMs can support SQL Server tools, business applications, ERP/inventory systems, Access and legacy apps, IIS/.NET applications, accounting software, and MSP client environments when the application and licensing requirements are compatible. Raff also provides Windows migration-focused content for local server migration, file server migration, backup planning, remote access, and Windows VPS sizing. Raff is not a SQL Server licensing provider or a replacement for DBA review. The clean model is: use Raff for the Windows VM infrastructure, then migrate SQL Server with a clear plan for databases, logins, jobs, app connections, backups, testing, cutover, and rollback. :::cta Deploy Windows Now Create a Raff Windows VM when your team is ready to move SQL-backed Windows workloads to the cloud. ::: ## Final SQL Server migration checklist Before production cutover, confirm: | Check | Done | |---|---| | Source SQL Server version documented | ☐ | | Destination SQL Server version selected | ☐ | | Database sizes and recovery models reviewed | ☐ | | Source backup completed | ☐ | | Test restore completed on destination | ☐ | | Logins migrated or recreated | ☐ | | Orphaned users checked | ☐ | | Roles and permissions verified | ☐ | | SQL Agent jobs recreated and tested | ☐ | | Maintenance plans recreated and tested | ☐ | | Linked servers and credentials reviewed | ☐ | | Connection strings identified | ☐ | | Firewall rules planned | ☐ | | Application tested with restored database | ☐ | | Final cutover window scheduled | ☐ | | Rollback plan written | ☐ | | Destination backup policy enabled | ☐ | | Post-migration restore test scheduled | ☐ | If any line is unclear, pause before moving production users. ## What's next - Review Raff's [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) if you are planning a migration. - Read [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) before moving production workloads. - Read [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) if SQL Server is part of a larger office server move. - Read [File Server Migration to Windows VPS](https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps) if shared folders are part of the migration. - Read [Windows VPS for ERP and Inventory Software](https://rafftechnologies.com/windows-server/windows-vps-erp-inventory-software) if the SQL database supports operations or inventory. - Read [Windows VPS for Business Software](https://rafftechnologies.com/windows-server/windows-vps-for-business-software) if the database supports several SMB apps. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production databases. - Review [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) and [pricing](https://rafftechnologies.com/pricing) when planning the destination server. ## Sources - Microsoft Learn — [SQL Server migration documentation](https://learn.microsoft.com/en-us/sql/sql-server/migrate/) - Microsoft Learn — [Back up and restore of SQL Server databases](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/back-up-and-restore-of-sql-server-databases) - Microsoft Learn — [Copy databases with backup and restore](https://learn.microsoft.com/en-us/sql/relational-databases/databases/copy-databases-with-backup-and-restore) - Microsoft Learn — [Copy databases to other servers](https://learn.microsoft.com/en-us/sql/relational-databases/databases/copy-databases-to-other-servers) - Microsoft Learn — [Use the Copy Database Wizard](https://learn.microsoft.com/en-us/sql/relational-databases/databases/use-the-copy-database-wizard) - Microsoft Learn — [Recovery models in SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/recovery-models-sql-server) - Microsoft Learn — [Restore and recovery overview for SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/restore-and-recovery-overview-sql-server) - Microsoft Learn — [Transfer logins and passwords between SQL Server instances](https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/security/transfer-logins-passwords-between-instances) - Microsoft Learn — [Troubleshoot orphaned users](https://learn.microsoft.com/en-us/sql/sql-server/failover-clusters/troubleshoot-orphaned-users-sql-server) - Microsoft Learn — [SQL Server Agent](https://learn.microsoft.com/en-us/ssms/agent/sql-server-agent) - Microsoft Learn — [Maintenance plans](https://learn.microsoft.com/en-us/sql/relational-databases/maintenance-plans/maintenance-plans) - Raff — [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) --- ### 25 PowerShell Commands Every Windows VPS Admin Needs URL: https://rafftechnologies.com/windows-server/powershell Description: 25 copy-paste PowerShell commands for daily Windows VPS admin: services, processes, files, networking, users, disk, remote management, and Windows Updates. ## In short A focused reference of the **25 PowerShell commands** that handle 90% of daily Windows VPS admin work — service management, process control, file ops, networking, user accounts, disk, remote management, and Windows Updates. All commands tested on Windows Server 2022 and 2025 with built-in PowerShell 5.1; nothing requires PowerShell 7.x. Copy-paste ready. Bookmark this page. ## How to follow along Open PowerShell **as Administrator** on your Raff Windows VPS: 1. RDP into the VPS (see [Connect to a Raff Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp)) 2. Right-click Start → **Windows PowerShell (Admin)** — or press `Win + X` → `A` Most commands below need admin rights. The ones that don't are noted explicitly. --- ## Service management ### 1. List all services + status ```powershell Get-Service | Select-Object Name, DisplayName, Status, StartType | Format-Table -AutoSize ``` Filter to a name pattern (e.g. all SQL services): ```powershell Get-Service -Name 'MSSQL*' ``` Microsoft Learn: [`Get-Service`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-service) ### 2. Restart a service ```powershell Restart-Service -Name 'W3SVC' -Force ``` `-Force` skips the dependent-service prompt. For IIS specifically, `iisreset` is also a valid one-liner. ### 3. Change service startup type ```powershell # Set to Automatic (starts on boot) Set-Service -Name 'MSSQLSERVER' -StartupType Automatic # Disable a service Set-Service -Name 'Spooler' -StartupType Disabled ``` Microsoft Learn: [`Set-Service`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-service) --- ## Process management ### 4. List running processes ```powershell # All processes, sorted by RAM use Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 20 Name, Id, CPU, @{N='MB';E={[math]::Round($_.WorkingSet64/1MB,1)}} ``` Filter by name: ```powershell Get-Process -Name 'sqlservr*' ``` ### 5. Kill a process ```powershell # By name Stop-Process -Name 'notepad' -Force # By PID (safer when multiple processes share a name) Stop-Process -Id 4452 -Force ``` `-Force` skips the user confirmation prompt. Use sparingly — kills don't run cleanup code. --- ## File and folder operations ### 6. List directory contents recursively ```powershell # Files only, recursive, with size in MB Get-ChildItem -Path 'C:\inetpub' -File -Recurse | Select-Object FullName, @{N='MB';E={[math]::Round($_.Length/1MB,2)}}, LastWriteTime | Sort-Object MB -Descending | Select-Object -First 20 ``` Find files larger than 100 MB (great for "what's eating my disk?"): ```powershell Get-ChildItem -Path 'C:\' -File -Recurse -ErrorAction SilentlyContinue | Where-Object Length -gt 100MB | Select-Object FullName, @{N='MB';E={[math]::Round($_.Length/1MB,1)}} ``` ### 7. Copy with retry + logging (Robocopy wrapper) `Copy-Item` is fine for one-off; for backups, use Robocopy via PowerShell: ```powershell # Mirror a folder, retry 3x on errors, log to file robocopy 'C:\Source' 'D:\Backup' /MIR /R:3 /W:5 /LOG:'C:\Logs\backup.log' /NP ``` Robocopy isn't a PowerShell cmdlet but it's the standard tool for serious file ops on Windows. PowerShell scripts wrap it for backup automation. ### 8. Calculate folder size ```powershell (Get-ChildItem -Path 'C:\inetpub' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1GB ``` Returns size in GB. Wrap in `[math]::Round(..., 2)` for clean output. --- ## System information ### 9. Get OS + hardware overview ```powershell Get-ComputerInfo | Select-Object CsName, OsName, OsVersion, OsBuildNumber, OsHardwareAbstractionLayer, CsTotalPhysicalMemory, CsNumberOfLogicalProcessors ``` Microsoft Learn: [`Get-ComputerInfo`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-computerinfo) ### 10. List installed Windows updates ```powershell Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 20 HotFixID, Description, InstalledOn, InstalledBy ``` ### 11. Read the Event Log ```powershell # Last 50 errors from the System log Get-EventLog -LogName System -EntryType Error -Newest 50 | Format-Table TimeGenerated, Source, EventID, Message -AutoSize -Wrap ``` For Windows Server 2022/2025, prefer the newer cmdlet: ```powershell # Last 50 errors using the new event log API Get-WinEvent -FilterHashtable @{LogName='System'; Level=2} -MaxEvents 50 | Format-Table TimeCreated, Id, ProviderName, Message -AutoSize -Wrap ``` --- ## Networking ### 12. List IP addresses ```powershell Get-NetIPAddress | Where-Object AddressFamily -eq 'IPv4' | Select-Object InterfaceAlias, IPAddress, PrefixLength, AddressState ``` ### 13. Test if a remote port is open ```powershell Test-NetConnection -ComputerName 'google.com' -Port 443 ``` The PowerShell equivalent of `nc -zv` — confirms TCP reachability + DNS resolution. Microsoft Learn: [`Test-NetConnection`](https://learn.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection) ### 14. List Windows Firewall rules ```powershell # All inbound allow rules Get-NetFirewallRule -Direction Inbound -Action Allow -Enabled True | Sort-Object DisplayName | Select-Object DisplayName, Profile, @{N='Port';E={(Get-NetFirewallPortFilter -AssociatedNetFirewallRule $_).LocalPort}} ``` ### 15. Add a firewall rule ```powershell # Allow inbound TCP 8080 New-NetFirewallRule -DisplayName 'Custom App TCP 8080' ` -Direction Inbound -Protocol TCP -LocalPort 8080 ` -Action Allow -Profile Any ``` Restrict by source IP for tighter security: ```powershell New-NetFirewallRule -DisplayName 'SQL from Office' ` -Direction Inbound -Protocol TCP -LocalPort 1433 ` -RemoteAddress '203.0.113.10/32' ` -Action Allow ``` Microsoft Learn: [`New-NetFirewallRule`](https://learn.microsoft.com/en-us/powershell/module/netsecurity/new-netfirewallrule) --- ## User and group management ### 16. List local users ```powershell Get-LocalUser | Format-Table Name, Enabled, LastLogon, Description -AutoSize ``` ### 17. Create a local user ```powershell $password = Read-Host 'Password' -AsSecureString New-LocalUser -Name 'jane.doe' -Password $password -FullName 'Jane Doe' -Description 'Accountant' ``` ### 18. Add a user to a group ```powershell # Grant RDP access Add-LocalGroupMember -Group 'Remote Desktop Users' -Member 'jane.doe' # Grant local admin (use sparingly!) Add-LocalGroupMember -Group 'Administrators' -Member 'jane.doe' ``` Microsoft Learn: [`Add-LocalGroupMember`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/add-localgroupmember) --- ## Disk and storage ### 19. Show disk and volume usage ```powershell # Volumes with free space Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter, FileSystemLabel, @{N='SizeGB';E={[math]::Round($_.Size/1GB,1)}}, @{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,1)}}, @{N='UsedPct';E={[math]::Round((1-$_.SizeRemaining/$_.Size)*100,1)}} ``` ### 20. Show physical disks ```powershell Get-PhysicalDisk | Format-Table FriendlyName, MediaType, Size, HealthStatus ``` Useful to confirm your VPS is on NVMe SSD as expected. --- ## Remote management ### 21. Enable PowerShell remoting (server side) ```powershell # On the server you want to manage remotely Enable-PSRemoting -Force ``` Microsoft Learn: [`Enable-PSRemoting`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting) ### 22. Run a command on a remote server ```powershell # Run on a single remote machine Invoke-Command -ComputerName 'SERVER02' -ScriptBlock { Get-Service W3SVC } # Run on a fleet Invoke-Command -ComputerName 'SRV01','SRV02','SRV03' -ScriptBlock { Get-WmiObject Win32_OperatingSystem | Select-Object PSComputerName, Caption, BuildNumber } ``` ### 23. Open an interactive remote PowerShell session ```powershell Enter-PSSession -ComputerName 'SERVER02' -Credential (Get-Credential) # Now you're 'inside' SERVER02 — every command runs there. Type 'exit' to leave. ``` --- ## Performance ### 24. Live performance counters ```powershell # CPU + memory snapshot every 2 seconds, 10 samples Get-Counter -Counter '\Processor(_Total)\% Processor Time', '\Memory\Available MBytes' ` -SampleInterval 2 -MaxSamples 10 ``` Useful counters for Windows Server admin: | Counter | What it shows | |---------|--------------| | `\Processor(_Total)\% Processor Time` | Overall CPU % | | `\Memory\Available MBytes` | Free RAM | | `\PhysicalDisk(_Total)\Avg. Disk Queue Length` | Disk congestion (>2 = bottleneck) | | `\Network Interface(*)\Bytes Total/sec` | Network throughput per NIC | | `\Process(*)\Working Set` | RAM per process | ### 25. Install + run Windows Updates from PowerShell The built-in Windows Update UI works, but for headless / Server Core / scripted patching: ```powershell # One-time: install the PSWindowsUpdate module from PowerShell Gallery Install-Module -Name PSWindowsUpdate -Force -Scope AllUsers # Check what's available Get-WindowsUpdate # Install everything (will reboot if needed) Get-WindowsUpdate -Install -AcceptAll -AutoReboot # Install only security updates Get-WindowsUpdate -Install -AcceptAll -Category 'Security Updates' -AutoReboot ``` PSWindowsUpdate is community-maintained but widely used. Source: [PowerShell Gallery — PSWindowsUpdate](https://www.powershellgallery.com/packages/PSWindowsUpdate). --- ## Bonus: discoverability When you forget a command name, PowerShell's discovery tools help: ```powershell # Find cmdlets by keyword (no need to know exact name) Get-Command *firewall* # See full help for any cmdlet (requires Update-Help once) Get-Help Get-Service -Full # See examples only Get-Help Get-Service -Examples # Update help files (do once after install) Update-Help -Force -ErrorAction SilentlyContinue ``` ## What's next - [Connect to a Raff Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) — get to the PowerShell prompt - [Install MSSQL Server 2022 / 2025 on a Windows VPS](/windows-server/install-sql-server-2025-windows-server-vps) — uses several of these PowerShell commands - [Deploy ASP.NET Core to IIS on Windows Server](/windows-server/iis-aspnet-core-windows-server-vps) — IIS + app pool management with PowerShell ## Sources - Microsoft Learn — [PowerShell documentation](https://learn.microsoft.com/en-us/powershell/) - Microsoft Learn — [Get-Service](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-service) - Microsoft Learn — [New-NetFirewallRule](https://learn.microsoft.com/en-us/powershell/module/netsecurity/new-netfirewallrule) - Microsoft Learn — [Test-NetConnection](https://learn.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection) - Microsoft Learn — [Enable-PSRemoting](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting) - PowerShell Gallery — [PSWindowsUpdate module](https://www.powershellgallery.com/packages/PSWindowsUpdate) - Date last verified: 2026-04-20 --- ### Promote a Windows VPS to an Active Directory Domain Controller URL: https://rafftechnologies.com/windows-server/active-directory-domain-controller Description: Promote a fresh Windows VPS to the first Active Directory domain controller in a new forest, then verify AD DS, DNS, Netlogon, SYSVOL, and basic users. Promote a Windows VPS to a domain controller only when it is a fresh, dedicated server. The clean workflow is: rename the server, verify stable IP and DNS settings, install the Active Directory Domain Services role, run `Install-ADDSForest` for a new forest, set a strong DSRM password, reboot, then verify AD DS, DNS, Netlogon, SYSVOL, domain controller status, and basic directory operations. ## Quick verdict | Situation | Recommendation | |---|---| | New SMB lab domain | Promote a fresh Windows VPS as the first DC | | Existing production domain | Add an additional DC only after DNS, time sync, connectivity, and replication checks | | Server already running IIS, SQL Server, RDS, ERP, or file workloads | Do not promote it; use a dedicated VM | | Single-DC lab | Acceptable for testing and demos | | Production AD environment | Use at least two domain controllers | | Public internet-facing VPS | Do not expose AD ports publicly; use private networking or VPN | | Before promotion | Rename server, verify IP/DNS, confirm Administrator password requirements | | After promotion | Verify services, DNS zones, SYSVOL, domain controller status, and backups | A domain controller is not just another Windows role. It becomes the identity foundation for the environment. ## What this guide covers This guide demonstrates the first domain controller in a new forest path. You will build this: ```text Fresh Windows Server VPS -> Hostname: DC01 -> AD DS role installed -> New forest created with Install-ADDSForest -> DNS installed during promotion -> Server rebooted as domain controller -> AD DS, DNS, Netlogon, SYSVOL, OU, and user verified ``` This guide does not fully cover production multi-DC replication topology, site design, RODC design, hybrid AD, or migration from an existing on-prem domain. Those require additional planning. ## What we tested on Raff We tested this walkthrough on a fresh Raff Windows VPS running Windows Server 2025 Datacenter Evaluation. ![PowerShell output showing the Raff Windows VPS test environment before Active Directory Domain Services promotion.](https://raff-images.s3.raffusercloud.com/01_domain_controller_test_environment_8935adac6f.png) Test environment: | Item | Value | |---|---| | Provider | Raff Technologies | | OS | Windows Server 2025 Datacenter Evaluation | | Server role | First domain controller in a new forest | | Hostname | `DC01` | | Test domain | `contoso.local` | | Forest NetBIOS name | `CONTOSO` | | AD role | Active Directory Domain Services | | DNS | Installed during promotion | | Test date | 2026-06-09 | | Tester | Serdar Tekin | In this lab, we verified: - server baseline - hostname and IP/DNS pre-flight - AD DS role installation - local Administrator password requirement - `Install-ADDSForest` promotion - AD DS services after reboot - domain controller verification - DNS zone creation - first OU and user creation This guide demonstrates a new forest / first domain controller deployment. Adding a domain controller to an existing forest has different prerequisites and should be tested separately. ## Important: use a dedicated VM Do not promote a general-purpose Windows server to a domain controller if it already runs production workloads such as: - IIS - SQL Server - RDS Session Host - ERP software - accounting software - public web apps - file sharing for users - business applications - backup agents with broad access - third-party tools you do not fully control A domain controller should be treated as a dedicated identity server. Mixing roles creates security and maintenance risk. If a web app, SQL app, RDS workload, or business application is compromised, the domain controller may also be exposed. For production, use at least two domain controllers when possible. ## Production topology before you start For a lab, one domain controller is enough. For production, one DC is a risk. A practical production design is: ```text Private network |-- DC01 | |-- AD DS | |-- DNS | |-- Global Catalog | `-- FSMO roles | `-- DC02 |-- AD DS |-- DNS |-- Global Catalog `-- replication partner ``` If both DCs are in the same private network and location, keep the design simple with one AD site. If one DC is in the cloud and another is in an office or another region, plan AD Sites, Subnets, and Site Links so clients find the right domain controller and replication follows the right path. ## Domain naming note The lab domain in this article uses: ```text contoso.local ``` That is fine for a controlled tutorial. For production, choose your domain name carefully. Many teams use a subdomain of a domain they own, such as: ```text ad.example.com corp.example.com internal.example.com ``` Avoid single-label domain names such as: ```text contoso company localdomain ``` They create unnecessary DNS and compatibility problems. ## What you'll need Before starting, prepare: - Fresh Raff Windows VPS or similar Windows Server VPS - Windows Server 2022 or Windows Server 2025 - Local Administrator access - Stable private IP configuration where possible - Meaningful hostname, such as `DC01` - Strong local Administrator password - Strong DSRM password - Private networking or VPN for domain traffic - 30-45 minutes including reboot - A second DC plan if this will become production For a small lab, a 4 vCPU / 8 GB Windows VPS is enough. For production, size based on users, sites, replication design, DNS usage, monitoring, backups, redundancy, and the number of domain-joined systems. ## Step 1 - Confirm the test environment Start with a fresh Windows Server VM. Run PowerShell as Administrator: ```powershell cls Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsBuildNumber, CsNumberOfLogicalProcessors, CsTotalPhysicalMemory Get-Service | Where-Object {$_.Name -in 'LanmanServer','Dnscache'} | Select-Object Name, Status, DisplayName hostname ``` This records the baseline before AD DS promotion. The important checks are: | Check | Why it matters | |---|---| | Windows version | Confirms the server OS | | CPU and memory | Documents VM size | | Hostname | Should be renamed before promotion | | Basic services | Confirms the server is responsive | Do not promote a server until the hostname is correct. ## Step 2 - Set hostname and verify IP/DNS Rename the server before promotion. Example: ```powershell Rename-Computer -NewName "DC01" -Restart ``` After reboot, reconnect by RDP and verify hostname and IP configuration. ![PowerShell output showing hostname, IP configuration, DNS settings, and reboot status before domain controller promotion.](https://raff-images.s3.raffusercloud.com/02_static_ip_and_hostname_7b429bb2b8.png) Useful checks: ```powershell $adapter = (Get-NetAdapter | Where-Object Status -eq 'Up').Name hostname Get-NetIPAddress -InterfaceAlias $adapter -AddressFamily IPv4 | Select-Object InterfaceAlias, IPAddress, PrefixLength, AddressState Get-DnsClientServerAddress -InterfaceAlias $adapter -AddressFamily IPv4 Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' ``` For a private AD environment, the DC should use stable private IP addressing. For a public VPS-only setup, be careful. Do not expose Active Directory services directly to the internet. Use private networking or VPN for domain traffic. ## Step 3 - Install the AD DS role Install Active Directory Domain Services and management tools: ```powershell Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools ``` Verify the role: ```powershell Get-WindowsFeature -Name AD-Domain-Services ``` ![PowerShell output showing Active Directory Domain Services role installed successfully on Windows Server.](https://raff-images.s3.raffusercloud.com/03_ad_ds_role_installed_1c54b4ce97.png) The AD DS role install alone does not make the server a domain controller. The promotion happens in the next step. ## Step 4 - Make sure the local Administrator password is required Before creating a new forest, the local Administrator account becomes the domain Administrator account. If the local Administrator account does not require a password, promotion can fail. Verify it: ```powershell net user Administrator ``` Look for: ```text Password required Yes ``` ![PowerShell output showing the local Administrator account with Password required set to Yes before AD DS promotion.](https://raff-images.s3.raffusercloud.com/05_local_administrator_password_required_f39de481bf.png) If needed, force the local Administrator account to require a password: ```powershell net user Administrator /passwordreq:yes ``` Then set a strong password: ```powershell net user Administrator "Replace-With-Your-Strong-Password" ``` For production, use a unique password stored in a password manager. ## Step 5 - Promote to a new forest For a brand-new AD environment, use `Install-ADDSForest`. Example lab domain: ```text contoso.local ``` Run: ```powershell Install-ADDSForest ` -DomainName "contoso.local" ` -DomainNetbiosName "CONTOSO" ` -ForestMode "WinThreshold" ` -DomainMode "WinThreshold" ` -InstallDns ` -CreateDnsDelegation:$false ` -DatabasePath "C:\Windows\NTDS" ` -LogPath "C:\Windows\NTDS" ` -SysvolPath "C:\Windows\SYSVOL" ` -NoRebootOnCompletion:$false ` -Force ``` PowerShell will ask for: ```text SafeModeAdministratorPassword ``` This is the Directory Services Restore Mode, or DSRM, password. ![PowerShell output showing Install-ADDSForest running to promote the Windows VPS to the first domain controller of the contoso.local forest.](https://raff-images.s3.raffusercloud.com/04_install_addsforest_command_afd9bf25c3.png) Store the DSRM password securely. It is separate from normal domain login and is used for offline AD recovery. After validation, the server installs the new forest, configures DNS, and reboots automatically. ## Step 6 - After reboot, sign in to the domain After reboot, sign in as: ```text CONTOSO\Administrator ``` Use the Administrator password you configured before promotion. The local Administrator account has become the domain Administrator account for the new forest. If RDP does not accept the short form, try: ```text contoso.local\Administrator ``` or use the domain selector from the Windows sign-in screen. ## Step 7 - Verify AD DS services Open PowerShell as Administrator and run: ```powershell Get-Service -Name "NTDS","ADWS","DNS","Netlogon" | Format-Table Name, Status ``` Expected result: ```text NTDS Running ADWS Running DNS Running Netlogon Running ``` ![PowerShell output showing NTDS, ADWS, DNS, and Netlogon services running after domain controller promotion.](https://raff-images.s3.raffusercloud.com/05_post_promotion_services_running_2877f0712b.png) These services confirm the server is operating as a domain controller with DNS and AD Web Services available. ## Step 8 - Verify domain controller status Run: ```powershell Get-ADDomain | Select-Object Forest, DomainSID, NetBIOSName, PDCEmulator, RIDMaster, InfrastructureMaster Get-ADDomainController -Filter * | Select-Object HostName, Domain, Forest, Site, IsGlobalCatalog ``` ![PowerShell output showing contoso.local domain details and the promoted Windows VPS listed as a domain controller.](https://raff-images.s3.raffusercloud.com/06_domain_controller_verification_2782798b19.png) You should see: - forest: `contoso.local` - NetBIOS name: `CONTOSO` - hostname: `DC01.contoso.local` - server listed as a domain controller - global catalog enabled - FSMO roles held by the first DC At this point, the new forest is operational. ## Step 9 - Verify DNS zones and create the first OU/user First, verify DNS zones: ```powershell Get-DnsServerZone | Format-Table ZoneName, ZoneType, IsDsIntegrated, IsReverseLookupZone ``` You should see zones such as: ```text contoso.local _msdcs.contoso.local ``` Then create an Organizational Unit: ```powershell New-ADOrganizationalUnit -Name "Accounting" -Path "DC=contoso,DC=local" ``` If the OU already exists, verify it instead: ```powershell Get-ADOrganizationalUnit -Filter "Name -eq 'Accounting'" | Select-Object Name, DistinguishedName ``` Create a test user: ```powershell $securePassword = Read-Host "Initial password" -AsSecureString New-ADUser -Name "Jane Doe" -GivenName "Jane" -Surname "Doe" ` -SamAccountName "jane.doe" ` -UserPrincipalName "jane.doe@contoso.local" ` -Path "OU=Accounting,DC=contoso,DC=local" ` -AccountPassword $securePassword ` -Enabled $true ``` Verify the OU and user: ```powershell Get-ADOrganizationalUnit -Filter "Name -eq 'Accounting'" | Select-Object Name, DistinguishedName Get-ADUser -Identity "jane.doe" | Select-Object Name, SamAccountName, UserPrincipalName, Enabled ``` ![PowerShell output showing the Accounting organizational unit and Jane Doe domain user created in Active Directory.](https://raff-images.s3.raffusercloud.com/07_dns_ou_and_user_created_9510a204ac.png) This proves the domain is usable for basic directory operations. ## Step 10 - Run final health checks Before calling the setup complete, run a few simple health checks. ## Confirm SYSVOL and NETLOGON ```powershell net share ``` Look for: ```text SYSVOL NETLOGON ``` These shares are important for Group Policy and logon scripts. ## Run DCDIAG ```powershell dcdiag ``` For a clean new lab DC, the main tests should pass. If you see DNS warnings, investigate them before joining clients. ## Confirm the DC list ```powershell nltest /dclist:contoso.local ``` Expected result: ```text DC01.contoso.local ``` ## Confirm the site ```powershell nltest /dsgetsite ``` In a one-DC lab, the site will usually be: ```text Default-First-Site-Name ``` You can rename this later in Active Directory Sites and Services if the environment becomes production. ## Additional DC path for existing domains If you already have an Active Directory domain, do not use `Install-ADDSForest`. Use `Install-ADDSDomainController` instead. Example: ```powershell $cred = Get-Credential Install-ADDSDomainController ` -DomainName "contoso.local" ` -InstallDns ` -Credential $cred ` -DatabasePath "C:\Windows\NTDS" ` -LogPath "C:\Windows\NTDS" ` -SysvolPath "C:\Windows\SYSVOL" ` -NoRebootOnCompletion:$false ` -Force ``` Before adding an additional DC, confirm: - network reachability to the existing DC - DNS points to the existing DC - domain admin credentials work - time is synchronized - replication health is clean - private connectivity exists between servers - firewall rules allow required AD traffic - the new DC name is unique - the server is not already running other production roles This guide tested the first-DC / new-forest path only. ## Production recommendations A single DC is acceptable for a lab or simple test environment. For production, plan for: | Area | Recommendation | |---|---| | Number of DCs | At least two | | Networking | Private network or VPN | | DNS | AD-integrated DNS on DCs | | Backups | System State backups | | Time sync | Reliable NTP/source hierarchy | | Security | Dedicated VM, minimal roles | | Monitoring | AD DS, DNS, replication, disk, event logs | | Access | Restrict RDP and admin access | | Replication | Verify with `repadmin /replsummary` once you have 2+ DCs | | Recovery | Document DSRM, backup, restore, and FSMO recovery steps | Do not expose domain controller services directly to the public internet. ## Basic firewall and port warning Active Directory is not a single-port service. Domain controllers may need DNS, Kerberos, LDAP, SMB, RPC Endpoint Mapper, and dynamic RPC port access between domain members and DCs. For modern Windows Server environments, dynamic RPC commonly uses: ```text 49152-65535 ``` That is one reason AD traffic should live on a private network, VPN, or trusted internal path. Do not try to make AD work by opening broad public firewall access. ## Backups for domain controllers Replication is not a backup. If you accidentally delete an OU, break DNS, damage Group Policy, or remove users, that change can replicate. For production, plan: - system state backups - VM-level backups or snapshots - restore testing - Active Directory Recycle Bin if appropriate - documented FSMO transfer or seizure plan - metadata cleanup process for failed DCs - backup access control Snapshots are useful before risky changes. Backups are required for recovery. ## Common mistakes ### Promoting before renaming the server The server name becomes part of AD metadata. Rename before promotion. ### Skipping stable IP/DNS planning Domain controllers need reliable IP and DNS configuration. AD depends heavily on DNS. ### Using a server that already runs IIS, SQL, RDS, or ERP Domain controllers should be dedicated. Mixing roles increases security and recovery risk. ### Forgetting the local Administrator password requirement If the local Administrator account does not require a password, promotion can fail. ### Losing the DSRM password The DSRM password is needed for offline AD recovery. Store it securely. ### Pointing DNS only to public resolvers Domain members must use AD DNS to locate domain services. Public DNS alone breaks AD discovery. ### Building a single DC for serious production A single DC is a single point of failure. Use at least two DCs for production. ### Opening AD ports to the internet Do not expose LDAP, Kerberos, SMB, RPC, DNS, or dynamic RPC ports to the public internet unless you have a very specific and secured architecture. ### Treating replication as backup Replication copies both good and bad changes. Use backups and test restores. ### Not checking SYSVOL and NETLOGON A promoted DC is not fully usable for domain operations if SYSVOL and NETLOGON are missing. ## What Raff recommends For Active Directory on Windows VPS, Raff recommends: 1. Use a fresh dedicated Windows VPS for the domain controller. 2. Rename the server before promotion. 3. Use stable private IP addressing where possible. 4. Install only the AD DS/DNS roles needed for the DC. 5. Store the DSRM password securely. 6. Verify AD DS services after reboot. 7. Verify DNS zones and domain controller status. 8. Verify SYSVOL and NETLOGON. 9. Create test OU/user objects to confirm AD works. 10. Use at least two DCs for production. 11. Place DC-to-DC traffic on private networking or VPN. 12. Do not expose AD services directly to the public internet. 13. Plan backups and recovery before joining production clients. For most SMB production environments, Active Directory should be part of a broader private network design, not a standalone public server. ## Tested on > Tested on Raff Windows VPS, Windows Server 2025 Datacenter Evaluation, promoted as the first domain controller of the `contoso.local` forest, 2026-06-09. We installed the AD DS role, verified local Administrator password requirements, ran `Install-ADDSForest`, rebooted, verified AD DS/DNS/Netlogon/ADWS services, confirmed domain controller status, checked DNS zones, and created an Accounting OU with a Jane Doe test user. Tester: Serdar Tekin. ## What's next - [Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-rdp) - connect to your server first - [Active Directory replication topology for 2-DC setups](/windows-server/ad-replication-topology) - plan the second DC before production - [Windows Server Hardening Checklist](/windows-server/windows-server-hardening-checklist) - secure the new domain controller - [Windows Update Strategy on Production Servers](/windows-server/windows-update-strategy) - patch domain controllers safely - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - understand licensing before adding RDS - [Raff Windows VPS](/products/windows-vm) - deploy a Windows Server VPS for Active Directory, DNS, IIS, SQL Server, and business apps ## Sources - Microsoft Learn - [Active Directory Domain Services overview](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/virtual-dc/active-directory-domain-services-overview) - Microsoft Learn - [Install-ADDSForest](https://learn.microsoft.com/en-us/powershell/module/addsdeployment/install-addsforest) - Microsoft Learn - [Install-ADDSDomainController](https://learn.microsoft.com/en-us/powershell/module/addsdeployment/install-addsdomaincontroller) - Microsoft Learn - [Service overview and network port requirements for Windows](https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/service-overview-and-network-port-requirements) - Microsoft Learn - [Active Directory replication concepts](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/replication/active-directory-replication-concepts) - Raff - [Windows VM](https://rafftechnologies.com/products/windows-vm) - Date last verified: 2026-07-07 --- ### Microsoft 365 Apps with Shared Computer Activation URL: https://rafftechnologies.com/windows-server/m365-apps-sca Description: Learn how to install Microsoft 365 Apps on a Windows VPS for multiple RDS users using Shared Computer Activation, eligible Microsoft 365 licensing, ODT configuration, and activation troubleshooting. Microsoft 365 Apps on a multi-user Windows VPS or RDS Session Host requires **Shared Computer Activation**. SCA lets Office be installed once on the server while each Remote Desktop user activates Word, Excel, Outlook, and other apps with their own eligible Microsoft 365 account. Use SCA when: - multiple users connect to the same Windows Server; - Office is installed on an RDS Session Host; - users launch Office apps from Remote Desktop sessions; - each user has their own Microsoft 365 identity; - you do not want Office activation tied to the install-time admin account. The practical setup is: ```text Windows VPS ↓ RDS Session Host ↓ Microsoft 365 Apps installed with Office Deployment Tool ↓ SharedComputerLicensing = 1 ↓ Each user signs in with an eligible Microsoft 365 license ``` The important rule: ```text Microsoft 365 license = right to use Office apps. RDS CAL = right to connect to the RDS Session Host. You usually need both. ``` ## Critical support note before you deploy Before installing Microsoft 365 Apps on Windows Server, verify Microsoft's current support matrix. Microsoft's RDS deployment documentation currently lists Microsoft 365 Apps support on Windows Server 2022 only until October 2026 and does not list Windows Server 2025 as a supported RDS host for Microsoft 365 Apps in that article. That means this is not a normal "newest Windows Server is always best" workload. For Microsoft 365 Apps on RDS, the safest rule is: ```text Choose the Windows Server version Microsoft currently supports for Microsoft 365 Apps on RDS. Do not assume Windows Server 2025 is supported unless Microsoft documentation confirms it. ``` If you are publishing this article for production buyers, verify the Microsoft support page on the same day and update this section if Microsoft changes support. ## Quick verdict | Situation | Recommendation | |---|---| | One user using Office on their own Windows PC | Normal Microsoft 365 Apps install | | Multiple users signing into one RDS host | Use Shared Computer Activation | | Microsoft 365 Apps for Enterprise users | Supported with SCA | | Microsoft 365 E3 / E5 users | Supported with SCA | | Microsoft 365 Business Premium users | Supported with SCA | | Microsoft 365 Business Standard users | Not supported for SCA | | Business Basic users | Not supported for desktop Office apps | | Personal or Family users | Not for business RDS/SCA scenarios | | Multiple RDP users on Windows Server | Plan RDS role and RDS CALs separately | | Production RDS host | Verify Microsoft 365 Apps + Windows Server support lifecycle | ## What is Shared Computer Activation? Shared Computer Activation is a Microsoft 365 Apps licensing mode for shared computers. Without SCA, Microsoft 365 Apps activation is designed around a normal user device. That works well when one person uses Office on their own PC. It breaks down when many users sign in to the same server. Example: ```text User A signs into RDS and opens Word. User B signs into the same RDS host and opens Word. User C signs into the same RDS host and opens Excel. ``` In that situation, the Office installation is shared, but the license entitlement must be checked per user. SCA solves this by making activation user-based: - Office is installed once on the Windows Server. - A user signs in to the RDS session. - The user opens Word, Excel, Outlook, or another Office app. - Microsoft 365 Apps contacts Microsoft licensing services. - The user's Microsoft 365 license is checked. - A licensing token is saved for that user. - The same process happens separately for every user. One user's activation does not activate Office for everyone. Each user needs their own eligible Microsoft 365 license. ## Why SCA matters on a Windows VPS A Windows VPS used for RDP can become a shared application server. Common use cases: - accountants using Excel and Outlook on a shared RDS server; - office staff using Word, Excel, and Outlook next to ERP software; - consultants connecting to the same Windows Server desktop; - small businesses centralizing business apps on a cloud Windows VPS; - MSPs hosting Microsoft 365 Apps for client users in an RDS environment. In these scenarios, installing Office normally is not enough. You need the correct activation mode. Otherwise you may see: - second user cannot activate Office; - Office asks users to sign in repeatedly; - Office enters reduced functionality mode; - Outlook profile problems; - activation tied to the admin account; - licensing errors after profile cleanup; - users blocked even though they have a Microsoft 365 account. SCA keeps the Office installation shared while the licensing remains per user. ## Eligible Microsoft 365 plans Not every Microsoft 365 plan supports Shared Computer Activation. Supported plans include: - Microsoft 365 Apps for enterprise; - Office 365 E3 / E5; - Microsoft 365 E3 / E5; - Education plans that include Microsoft 365 Apps for enterprise; - Microsoft 365 Business Premium; - Project or Visio plans that include desktop apps, for those specific apps. Not supported for SCA: - Microsoft 365 Business Standard; - Microsoft 365 Business Basic; - Microsoft 365 Apps for business when not included through Business Premium SCA entitlement; - Microsoft 365 Personal; - Microsoft 365 Family; - consumer Office licenses; - unlicensed Microsoft accounts. Important: ```text Microsoft 365 Business Premium is the only Microsoft 365 business plan in the Business tier that supports Shared Computer Activation. ``` Business Standard includes desktop Office apps, but it does not include the Shared Computer Activation entitlement. That is the licensing detail that often breaks RDS Office deployments. ## M365 license vs RDS CAL Do not confuse Microsoft 365 licensing with Remote Desktop licensing. They solve different problems. | License | What it covers | |---|---| | Microsoft 365 Apps license | The user's right to use Office apps such as Word, Excel, Outlook, PowerPoint | | RDS CAL | The user's or device's right to connect to a Windows Server Remote Desktop Session Host | | Windows Server license | The server operating system rights | | Raff Windows VPS | The cloud server infrastructure | For a real multi-user Office-on-RDS deployment, users usually need: ```text Eligible Microsoft 365 license + RDS CAL + Windows Server/RDS configuration + SCA-enabled Office install ``` There is no Microsoft 365 license that magically replaces the RDS CAL requirement for a Windows Server Session Host. Plan both before production. ## What you will build This guide sets up Microsoft 365 Apps on a Windows VPS or RDS Session Host using the Office Deployment Tool. Target architecture: ```text Remote users ↓ RDP / RDS Session Host ↓ Windows VPS ├── Microsoft 365 Apps installed once ├── SharedComputerLicensing = 1 ├── Per-user Microsoft 365 activation tokens ├── User profiles / profile containers └── Internet access to Microsoft licensing services ``` Each user signs in with their own Microsoft 365 account. Office activation is not tied to the server administrator account. ## What you'll need Before starting, prepare: - a Raff Windows VPS or similar Windows Server VM; - RDS Session Host role installed if multiple users will connect; - eligible Microsoft 365 licenses assigned to each user; - RDS CAL planning for users or devices; - local Administrator access on the VPS; - Office Deployment Tool from Microsoft; - reliable outbound internet access from the VPS; - a profile strategy for Outlook and Office token caching; - 45-60 minutes for first install. Recommended Microsoft 365 plan options: | User plan | SCA support | |---|---:| | Microsoft 365 Apps for enterprise | Yes | | Office 365 E3 / E5 | Yes | | Microsoft 365 E3 / E5 | Yes | | Microsoft 365 Business Premium | Yes | | Microsoft 365 Business Standard | No | | Microsoft 365 Business Basic | No desktop Office apps | | Microsoft 365 Personal / Family | No for this business RDS scenario | ## Step 1 — Prepare the Windows VPS Start with a clean Windows Server environment. Before installing Microsoft 365 Apps: 1. Confirm Windows Server version support. 2. Install Windows updates. 3. Reboot the server. 4. Confirm RDS Session Host is installed if multiple users will connect. 5. Confirm users can sign in through RDP. 6. Confirm each user has an eligible Microsoft 365 license. 7. Confirm the VPS has internet access. 8. Confirm no old MSI Office installation exists. 9. Decide whether to use local profiles, User Profile Disks, FSLogix, or another profile method. Do not install Office first and solve licensing later. For RDS, licensing and profile planning come first. ## Step 2 — Download the Office Deployment Tool Download the Office Deployment Tool from Microsoft on the Windows VPS. Create a folder: ```powershell New-Item -ItemType Directory -Path "C:\ODT" -Force ``` Run the ODT executable and extract files into: ```text C:\ODT ``` You should see: ```text setup.exe configuration.xml ``` You can replace the sample configuration file with your own. ## Step 3 — Choose the correct product ID Use the product ID that matches your Microsoft 365 license family. For Microsoft 365 Apps for enterprise / E3 / E5: ```xml ``` For Microsoft 365 Business Premium: ```xml ``` This matters. Business Premium supports SCA, but it includes Microsoft 365 Apps for business, not Apps for enterprise. If you deploy the wrong product ID, activation and licensing behavior may not match the user's license. ## Step 4 — Create configuration.xml Create: ```text C:\ODT\configuration.xml ``` ## Option A — Microsoft 365 Apps for enterprise Use this for Microsoft 365 Apps for enterprise, Office 365 E3/E5, or Microsoft 365 E3/E5 users. ```xml ``` ## Option B — Microsoft 365 Business Premium Use this for Microsoft 365 Business Premium users. ```xml ``` Key line: ```xml ``` This enables Shared Computer Activation. ## Step 5 — Decide whether to exclude OneDrive The examples above exclude OneDrive. That is a conservative default for RDS hosts unless you have planned OneDrive sync carefully. Reasons to exclude OneDrive on simple RDS hosts: - sync cache can grow quickly; - multiple user profiles can consume storage; - support issues are common when profile strategy is weak; - OneDrive may need additional policy planning; - small VPS deployments usually do not need local OneDrive sync on the server. If your users need OneDrive, do not exclude it blindly. Plan profile storage, tenant policies, disk usage, and user training first. ## Step 6 — Download Microsoft 365 Apps source files Open PowerShell as Administrator. Run: ```powershell cd C:\ODT .\setup.exe /download configuration.xml ``` This downloads Microsoft 365 Apps installation files. The download can take 10-30 minutes depending on connection speed. You should see an `Office` folder appear under: ```text C:\ODT\Office ``` ## Step 7 — Install Microsoft 365 Apps with SCA enabled Run: ```powershell cd C:\ODT .\setup.exe /configure configuration.xml ``` The install runs silently if `Display Level="None"` is set. Wait until setup completes. Do not interrupt the install. ## Step 8 — Verify Shared Computer Activation is enabled After installation, check the Click-to-Run configuration. Run PowerShell as Administrator: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' (Get-ItemProperty -Path $key).SharedComputerLicensing ``` Expected output: ```text 1 ``` If the value is missing or `0`, SCA is not enabled. Fix options: 1. Re-run Office setup with the correct `configuration.xml`. 2. Enable SCA with registry. 3. Enable SCA with Group Policy where supported. 4. Use Microsoft Support and Recovery Assistant for activation repair. Registry method: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' New-Item -Path $key -Force | Out-Null Set-ItemProperty -Path $key -Name 'SharedComputerLicensing' -Value '1' -Type String ``` Reboot the server after changing activation mode. ## Step 9 — Test with a real non-admin user Do not test only with the Administrator account. Use a real user account that has: - RDP access; - an eligible Microsoft 365 license; - correct password/MFA path; - normal user permissions; - profile created on the server. Test flow: 1. Sign out of the Administrator session. 2. RDP into the server as the test user. 3. Launch Word. 4. Sign in with the user's Microsoft 365 work account. 5. Confirm Word opens normally. 6. Go to **File → Account**. 7. Confirm Office shows the signed-in licensed user. 8. Sign out and repeat with a second user. Each user should get their own activation token. ## Step 10 — Understand where activation tokens are stored With SCA, each user gets a licensing token. By default, the token is stored in the user's profile. Default location: ```text %localappdata%\Microsoft\Office\16.0\Licensing ``` Microsoft 365 Apps needs internet access to obtain and renew these tokens. Tokens are valid for a limited time and renew automatically when users open Office while online. If a user does not use the shared computer for a long period, the token can expire and Office will contact Microsoft again on next launch. This is normal. ## Step 11 — Configure token roaming only if needed For normal persistent user profiles, the default token location is usually enough. For non-persistent profiles, pooled desktops, or profile reset scenarios, consider token roaming. You can configure token roaming with ODT properties: ```xml ``` Or with registry: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' Set-ItemProperty -Path $key -Name 'SCLCacheOverride' -Value '1' -Type String Set-ItemProperty -Path $key -Name 'SCLCacheOverrideDirectory' -Value '\\server\share\%username%' -Type String ``` Do not redirect all users to the same folder. The token location must be unique per user and writable by that user. For a simple single RDS host with persistent local profiles, token roaming may not be required. ## Step 12 — Plan Outlook profiles carefully Outlook is usually the hardest part of Office on RDS. Word and Excel are simple. Outlook creates mail profiles, cached data, signatures, add-ins, and search indexes. Plan: - profile storage method; - OST cache location; - mailbox size; - shared mailboxes; - add-ins; - search performance; - disk growth; - profile cleanup; - MFA and modern authentication; - whether Cached Exchange Mode is enabled. Common profile strategies include: - persistent local profiles; - User Profile Disks; - FSLogix profile containers; - other profile container solutions. For small deployments, persistent local profiles may be enough. For serious RDS deployments, use a profile container strategy so users keep Outlook state reliably across sessions. ## Step 13 — Assign users to Remote Desktop access Each Office user also needs access to the RDS host. For a basic standalone server, add users to: ```text Remote Desktop Users ``` PowerShell example: ```powershell Add-LocalGroupMember -Group "Remote Desktop Users" -Member "DOMAIN\jane.doe" ``` If this is a domain environment, manage access with domain groups instead of adding users one by one. Example: ```text RDS-Office-Users ``` Then add that group to Remote Desktop Users on the server. ## Step 14 — Confirm each user has the right license Before telling users to connect, check Microsoft 365 admin center. For each user, verify: - Microsoft 365 Apps for enterprise, E3, E5, or Business Premium is assigned; - Office apps are enabled under the license details; - account sign-in is allowed; - MFA/Conditional Access does not block RDS sign-in; - the user knows their work account password; - Business Standard users are upgraded if SCA is required. Do not troubleshoot Office installation if the user simply has the wrong license. ## Step 15 — Verify Office activation status From an Office app: 1. Open Word. 2. Go to **File → Account**. 3. Confirm the user is signed in. 4. Confirm the product is activated. From Command Prompt, you can also inspect Office licensing scripts, but the exact path varies by Office version and architecture. Common location: ```text C:\Program Files\Microsoft Office\Office16 ``` Example: ```cmd cd "C:\Program Files\Microsoft Office\Office16" cscript ospp.vbs /dstatus ``` Use this for troubleshooting, not as the only success check. The best test is still: ```text User signs in → opens Word/Excel/Outlook → edits and saves a document successfully. ``` ## Common errors and fixes ## Error 1 — "We can't sign you in because you don't have a license" The user does not have an eligible Microsoft 365 license. Check: - license assignment in Microsoft 365 admin center; - whether Office apps are enabled under that license; - whether the plan supports SCA; - whether the user signed in with the correct work account. Business Standard is a common cause. It includes desktop Office apps for normal device installs, but it does not support Shared Computer Activation. ## Error 2 — "Microsoft 365 Apps cannot be activated because shared computer activation is not enabled" SCA is not enabled. Check: ```powershell $key = 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' (Get-ItemProperty -Path $key).SharedComputerLicensing ``` Expected: ```text 1 ``` If not, enable SCA by ODT, registry, Group Policy where supported, or Support and Recovery Assistant. Reboot after changing activation mode. ## Error 3 — Second user is blocked after the first user activates Office This usually means Office was installed without SCA or activation happened in the wrong mode. Fix: 1. Enable SCA. 2. Reset Office activation state. 3. Reboot. 4. Test with two separate licensed users. Do not rely on the admin account test. Always test multiple non-admin users. ## Error 4 — Office keeps asking users to sign in Possible causes: - token cache is not preserved; - user profiles are temporary; - RDS profile cleanup deletes token folders; - no reliable internet access; - Conditional Access blocks sign-in; - MFA flow cannot complete inside the RDS session; - token roaming path is wrong; - Office activation was previously cached incorrectly. Check: ```text %localappdata%\Microsoft\Office\16.0\Licensing ``` If profiles are deleted at logoff, token loss is expected. Use a persistent profile or token roaming strategy. ## Error 5 — Outlook profile disappears after logout This is a profile management problem, not only an Office activation problem. Fix options: - use persistent profiles; - use User Profile Disks; - use FSLogix profile containers; - reduce or disable Cached Exchange Mode if storage is limited; - check profile cleanup policies; - verify users have write access to profile storage. Outlook on RDS should not be deployed without profile planning. ## Error 6 — Business Premium users cannot activate Check the product ID. For Business Premium, use: ```xml ``` If you installed the enterprise product ID but users only have Business Premium, licensing may not match. Also confirm the tenant actually assigned Business Premium to the user and that Microsoft 365 Apps is enabled in the license details. ## Error 7 — Business Standard users cannot activate with SCA This is expected. Business Standard does not support Shared Computer Activation. Upgrade affected users to Business Premium or an enterprise plan that supports SCA. ## Error 8 — Office is in reduced functionality mode Reduced functionality mode usually means Office is installed but not activated for that user. Causes: - no eligible license; - no internet access to Microsoft licensing service; - sign-in prompt was closed; - token expired and cannot renew; - SCA not enabled; - profile/token issue. Fix the licensing and activation path. Do not reinstall Windows or rebuild the server before checking SCA and user license assignment. ## Security and operations checklist Before production, review: - Windows Server support status for Microsoft 365 Apps; - RDS Session Host installed and licensed; - RDS CALs planned; - Microsoft 365 licenses assigned; - SCA enabled; - each user signs in with their own account; - no shared Microsoft 365 account; - profile strategy selected; - Outlook tested; - OneDrive plan defined; - Office update channel selected; - backups enabled before production; - users do not have local admin rights; - RDP access is restricted where possible; - MFA/Conditional Access tested; - support runbook created. ## Recommended update channel For RDS hosts, use a controlled update channel. A practical default: ```xml Channel="MonthlyEnterprise" ``` Why Monthly Enterprise is a good default: - predictable monthly update cadence; - less change noise than Current Channel; - still receives regular security and feature updates. For highly conservative environments, consider Semi-Annual Enterprise Channel only if the business understands the slower feature cadence. Avoid letting every RDS host update unpredictably. Office updates can affect all users on that server. ## How Raff fits Microsoft 365 Apps on RDS Raff Windows VPS gives you the Windows Server foundation for running RDS-style workloads. Raff can help with: - Windows VPS deployment; - RDP access; - Windows Server version selection; - VM sizing; - backups and snapshots; - private networking; - migration planning; - support for the Windows server layer. Raff does not replace Microsoft 365 licensing. You still need: - eligible Microsoft 365 licenses; - RDS CALs where required; - correct Microsoft 365 tenant configuration; - user identity and MFA planning; - Office Deployment Tool configuration. A practical Raff setup looks like this: ```text Raff Windows VPS ↓ RDS Session Host ↓ Microsoft 365 Apps with SCA ↓ Licensed users connect over RDP ``` For production teams, combine this with: - RDP hardening; - backup strategy; - user profile strategy; - restricted admin access; - documented license assignment. ## What Raff recommends For Microsoft 365 Apps on a Windows VPS: 1. Verify Microsoft support for the Windows Server version first. 2. Use RDS Session Host for real multi-user access. 3. Assign eligible Microsoft 365 licenses to every user. 4. Do not use Business Standard for SCA. 5. Plan RDS CALs separately. 6. Install Microsoft 365 Apps with ODT, not a normal click-through installer. 7. Set `SharedComputerLicensing` to `1`. 8. Test with two real non-admin users. 9. Plan Outlook and profile storage before production. 10. Keep Office update cadence controlled. The key point: ```text A working Office install is not enough. You need the right activation mode, user licenses, RDS licensing, and profile strategy. ``` ## Tested on > Compatible with Raff Windows VPS and RDS-style Windows Server deployments. Do not publish that claim until the environment has been tested. ## What's next - [Multi-user RDP: 2 Admin Sessions vs RDS Session Host](/windows-server/multi-user-rdp-admin-sessions-vs-rds) - [RDS CAL Licensing on Windows Server](/windows-server/rds-cal-licensing-guide) - [Connect to a Windows VPS via RDP](/windows-server/connect-to-windows-vps-via-rdp) - [RDP Performance Tuning for Smooth Remote Desktop](/windows-server/rdp-performance-tuning) - [ERP on Windows VPS: Hosting, Sizing, and Migration](/windows-server/erp-on-vps) - [Raff Windows VPS](/products/windows-vm) ## Sources - Microsoft Learn — Overview of shared computer activation for Microsoft 365 Apps - Microsoft Learn — Deploy Microsoft 365 Apps by using Remote Desktop Services - Microsoft Learn — Configuration options for the Office Deployment Tool - Microsoft Learn — Troubleshoot shared computer activation for Microsoft 365 Apps - Microsoft Learn — Remote Desktop Services overview - Date last verified: 2026-07-07 --- ### File Server Migration to Windows VPS URL: https://rafftechnologies.com/windows-server/file-server-migration-to-windows-vps Description: Plan a file server migration to Windows VPS, including shared folders, SMB access, NTFS permissions, mapped drives, backups, testing, cutover, and rollback. A file server migration to Windows VPS is not just copying folders. A safe migration needs an inventory of SMB shares, NTFS permissions, user groups, mapped drives, storage size, backup policy, access method, final sync, user testing, and rollback. Raff Technologies provides Windows VMs for small businesses and MSPs that want to move shared folders from local office hardware to a cloud-hosted Windows Server environment. File servers look simple because users only see folders. Behind those folders are permissions, drive letters, scripts, app paths, backup jobs, access policies, and years of business habits. If those details are missed, the new server may technically contain the files but still fail the business workflow. The goal of file server migration is not only to move data. The goal is to make sure users can find, open, edit, save, protect, and restore the files they depend on. ## Quick verdict: when file server migration to Windows VPS makes sense Use this table before migrating a Windows file server to a cloud Windows VPS. | Situation | Windows VPS fit | Why | |---|---|---| | Office server hardware is aging | Strong fit | The file server can move away from local hardware. | | Remote users need shared folders | Strong fit with access planning | Users can reach files through RDP/RDS, VPN/private access, or controlled SMB patterns. | | Multiple offices need the same folders | Good fit | Centralized file storage can reduce branch-to-branch syncing. | | Files support hosted Windows apps | Strong fit | Apps and files can stay close inside the Windows environment. | | SMB shares are tied to legacy apps | Good fit after testing | Paths, drive letters, and permissions must be validated. | | Team wants direct SMB from anywhere | Risky | SMB should not be broadly exposed to the public internet. | | Large media files move all day | Depends | Performance, latency, and storage cost need testing. | | Compliance rules are strict | Review first | Access, retention, logging, and backup requirements must be designed. | The best fit is a small business that wants a central Windows file server for shared folders, remote users, business apps, backups, and office server replacement. :::cta Talk to Windows Engineer Review file shares, NTFS permissions, mapped drives, backups, and cutover timing before migrating your file server. ::: ## What changes when file shares move to a Windows VPS A local file server usually sits inside one office. Users reach it through the LAN, mapped drives, shortcuts, or applications that expect certain paths. ![Architecture visual showing local Windows file server migration to cloud Windows VPS with SMB shares, users, backups, and secure access](https://raff-images.s3.raffusercloud.com/file_server_migration_architecture_windows_vps_webp_77a9232aed.png) A Windows VPS changes the access model. | Area | Local file server | Windows VPS file server | |---|---|---| | Server location | Office hardware | Cloud-hosted Windows Server VM | | User access | LAN, mapped drives, local SMB | RDP/RDS, VPN/private access, or controlled SMB access | | Remote work | VPN or office firewall dependency | Planned remote access model | | Backups | Often local or inconsistent | VM backup, snapshot, file-level backup, off-server copy | | Hardware risk | Office server failure affects users | Cloud VM removes local hardware dependency | | File paths | Local server name and shares | New share paths, DNS alias, or planned identity transfer | | Permissions | Old NTFS/share rules | Preserved, cleaned, or redesigned permissions | | Support | May require office access | MSP/team can manage a known cloud environment | Cloud does not remove file server administration. You still need permissions, backups, monitoring, user documentation, restore testing, and access control. ## File server migration is not just copying folders A basic copy may move documents, but it can miss the context that makes the file server usable. A proper migration includes: | Migration area | What to preserve or redesign | |---|---| | SMB shares | Share names, paths, descriptions, access | | NTFS permissions | Folder-level and file-level security | | User groups | Department groups, modify/read groups, stale users | | Mapped drives | Drive letters, GPOs, scripts, shortcuts | | App paths | UNC paths or hardcoded drive letters used by software | | Open files | Files in use during copy or final sync | | Long paths | Files that may fail due to path length | | Ownership | File owners, orphaned SIDs, old accounts | | Backups | What is protected, how often, and how restore works | | Cutover | Final sync, user communication, rollback | Microsoft describes SMB as the protocol Windows and Windows Server use to share resources such as files, printers, and named pipes. That means file server migration is also an SMB, permissions, and access migration, not only a data migration. ## Step 1: inventory existing shares and permissions Start with a file server inventory. Document: | Inventory item | What to capture | |---|---| | Server name | Current server name and aliases | | IP address | Current IP and DNS dependencies | | Shares | Share names, local paths, purpose | | NTFS permissions | Folder and file access rules | | Share permissions | Network share-level access | | Security groups | Groups used for access control | | Mapped drives | GPOs, logon scripts, manual mappings | | Folder size | Size per share and top-level folder | | File count | Number of files and folders | | Old data | Archive, duplicate, unused, or stale folders | | App dependencies | Apps that read/write to file paths | | Backup state | Current backup schedule and last restore test | The inventory should answer a simple question: if this file server disappeared tomorrow, what exactly would need to exist on the new Windows VPS for users to keep working? ## Step 2: clean up old data before migration Many file servers contain years of old downloads, duplicate folders, abandoned user profiles, old installers, temporary exports, and unclear archives. Before migration, sort data into: | Group | Meaning | |---|---| | Active | Used in current business workflows | | Archive | Needed for history but rarely changed | | Retire | Duplicate, obsolete, or safe to exclude | | Review | Ownership unclear; needs business decision | Do not let IT decide every file alone. Folder owners should review business folders, especially finance, HR, client records, legal documents, and old project data. A cleanup pass reduces migration time, storage cost, backup size, and future permission confusion. ## Step 3: plan the SMB access model The access model is one of the most important decisions. Use this table: | Access model | Best fit | |---|---| | Users access files inside RDP/RDS sessions | Good for remote Windows desktop environments | | Users map drives over VPN/private access | Good when endpoint file access is required | | Apps access file paths on the Windows VPS | Good when apps and files stay close together | | SMB over QUIC where supported | Good for specific modern Windows scenarios | | Direct SMB exposed publicly | Avoid | | Public file downloads from the file server | Usually avoid; consider object storage or app delivery | Microsoft’s SMB feature guidance highlights security and connectivity features such as signing, encryption, NTLM blocking, authentication rate limiting, SMB over QUIC, and alternative ports in newer Windows versions. The practical point is simple: SMB access should be designed, not casually opened to the internet. If most users already work through Remote Desktop, the cleanest pattern may be to keep file access inside the Windows VPS session instead of mapping SMB shares directly from every home network. :::cta Explore Windows VM Use Raff Windows VM as the destination for shared folders, remote users, business files, and cloud file server workloads. ::: ## Step 4: preserve or redesign NTFS permissions NTFS permissions are where many migrations become messy. You have two options: | Option | When it fits | |---|---| | Preserve existing permissions | The current model is clean, documented, and still accurate | | Redesign permissions | The current model has stale users, broad access, or unclear ownership | For most small businesses, a light redesign is useful. Instead of assigning permissions directly to individual users, use groups. ![Visual showing NTFS permissions, security groups, mapped drives, UNC paths, and user access dependencies during file server migration](https://raff-images.s3.raffusercloud.com/file_server_permissions_mapped_drives_migration_webp_7cba06b031.png) Example group model: ```text Accounting_Read Accounting_Modify HR_Read HR_Modify Operations_Read Operations_Modify Projects_Read Projects_Modify ``` Then assign users to groups. This makes onboarding, offboarding, and audits easier. Check for: | Permission issue | Why it matters | |---|---| | Everyone has modify access | Too much risk | | Old users still appear | Stale access or orphaned SIDs | | Permissions are set per user | Hard to manage | | Deny rules are used casually | Can create confusing access behavior | | Inheritance is broken everywhere | Troubleshooting becomes harder | | App folders need write access | Users or services may fail after migration | The migration is a good time to simplify permissions, but do not redesign everything during cutover. Decide and test first. ## Step 5: plan mapped drives and user access Users often think in drive letters, not server names. Common examples: ```text S: = Shared F: = Finance P: = Projects X: = AppData ``` If those drives change unexpectedly, users may think files are missing even when the migration succeeded. Plan: | Mapped drive item | What to verify | |---|---| | Drive letters | Which letters are used and by whom | | UNC paths | Old and new server paths | | GPOs | Drive mapping policies | | Logon scripts | Scripts that map drives | | Shortcuts | Desktop and app shortcuts | | Application paths | Apps that expect a mapped drive | | DNS alias | Whether a friendly server name should point to the new VPS | | User instructions | What changes users will see | If applications depend on a path such as `\\OldServer\Shared`, consider whether to update the application path, use DNS aliasing, or use a migration method that preserves server identity. Microsoft’s Storage Migration Service can optionally transfer the identity of a source server to the destination so apps and users can access data without changing links or paths. That can be useful when the file server identity itself is part of the workflow. ## Step 6: choose destination Windows VPS size and storage File servers are storage-heavy, but CPU and RAM still matter when users connect through RDP/RDS or apps run on the same server. Plan storage for: | Storage area | Examples | |---|---| | Production shares | Department folders, client folders, business documents | | Archive data | Prior-year files, historical projects | | App data | Legacy app files, Access back ends, export folders | | User profiles | RDP/RDS profiles if stored on the server | | Temporary data | Downloads, reports, migration staging | | Logs | Windows and application logs | | Backups | Local staging, snapshots, restore points | | Growth | 12-24 months of new files | Use this starting guide: | File server workload | Starting thought | |---|---| | Small shared folder server | 2 vCPU / 4-8 GB RAM, storage based on data size | | 3-5 users with RDP access | 4 vCPU / 8-16 GB RAM | | 5-10 users using files and apps | 4-8 vCPU / 16-32 GB RAM | | File server plus business apps | Size for apps, not files alone | | Heavy file workload | Test latency, throughput, and backup window | Do not run the destination disk near full. Full disks can break user saves, app exports, backups, and profile behavior. :::cta View Pricing Compare Raff Windows VM plans when sizing CPU, memory, storage, and monthly cost for your file server migration. ::: ## Step 7: run a test copy Before the production cutover, run a test copy to the Windows VPS. ![Migration visual showing test copy, final sync, validation, and cutover from file server to Windows VPS](https://raff-images.s3.raffusercloud.com/file_server_test_copy_final_sync_webp_7ce1e67868.png) The test copy should validate: | Test copy item | What to check | |---|---| | File count | Did all expected files copy? | | Folder size | Does destination size match source? | | Permissions | Are NTFS permissions correct? | | Share access | Can users access shares as expected? | | Long paths | Did any files fail? | | Locked files | Were any files skipped because they were open? | | Hidden/system files | Were important files excluded? | | App folders | Do business apps see the expected paths? | | Backup | Is destination data protected after copy? | Tools vary by migration plan. Some teams use Storage Migration Service. Others use scripted copy methods such as Robocopy. The important thing is not the tool name alone; it is whether the copy is repeatable, logged, tested, and reversible. ## Step 8: configure backups before production Do not migrate production folders to a Windows VPS and then “set up backups later.” A practical backup model: | Backup layer | Purpose | |---|---| | VM backup | Recover the full Windows VPS | | Snapshot before cutover | Roll back infrastructure state before migration changes | | File-level backup | Restore individual files or folders | | Off-server copy | Protect against VM, account, or ransomware scenarios | | Retention policy | Recover older versions when issues are discovered late | | Restore test | Prove the recovery process works | Backups must protect the new environment before users start writing files to it. If the destination server becomes production, new files may exist only there after cutover. ![Backup and rollback visual for file server migration to Windows VPS with source backup, destination backup, restore test, and rollback path](https://raff-images.s3.raffusercloud.com/file_server_migration_backup_rollback_stack_webp_a01e0adbaa.png) :::cta Explore Data Protection Protect your file server migration with backup, snapshot, and restore planning before moving production folders. ::: ## Step 9: run final sync and cutover After testing, schedule the final migration window. A typical cutover sequence: 1. Announce downtime or read-only window. 2. Confirm source backup. 3. Freeze writes on the old file server. 4. Run final sync to the Windows VPS. 5. Review copy logs and errors. 6. Create or verify SMB shares on the destination. 7. Verify NTFS and share permissions. 8. Update DNS, mapped drives, GPOs, scripts, or shortcuts. 9. Test access with admin account. 10. Test access with real user accounts. 11. Confirm backups are running on destination. 12. Allow users to begin work. 13. Keep the old server available but controlled. 14. Monitor first-day issues. The final sync should be boring because the test copy already proved the path. ## Step 10: test users and rollback File server migration succeeds only when users can work. Test with several user types: | User type | What to test | |---|---| | Standard staff user | Open, edit, save, rename, delete where allowed | | Read-only user | Confirm they cannot modify files | | Department manager | Access department folders | | Finance/HR user | Access restricted folders | | App user | Confirm business software can read/write | | Remote user | Test access from outside the office | | Admin | Confirm support and restore access | Rollback should also be defined before cutover. Ask: | Rollback question | Why | |---|---| | What issue triggers rollback? | Avoid panic decisions | | Who decides rollback? | Clear ownership | | How long is rollback practical? | New writes complicate return | | Is the old server still intact? | Needed for fallback | | Are users told where to save files during issues? | Prevent data split | | How will new files be reconciled? | Avoid data loss | Do not wipe the old file server immediately. Keep it available until the new environment is stable and backed up. ## Common file server migration mistakes ### Copying files without permissions The destination may contain the files but allow the wrong people to access them, or block users who need them. ### Forgetting mapped drives Users may rely on drive letters or shortcuts. If these are not updated, the migration looks broken to them. ### Exposing SMB directly to the internet Do not broadly expose SMB file sharing to the public internet. Use RDP/RDS, VPN/private access, SMB over QUIC where supported, or another controlled access design. ### Migrating old clutter Moving every old download, installer, duplicate archive, and abandoned user folder increases storage and backup cost. ### Skipping restore tests A backup plan that has never been restored is not proven. ### Retiring the old server too early Keep the old file server available until the Windows VPS is verified with real users and backups. ## How Raff fits file server migration Raff fits this use case when a small business or MSP wants to move shared folders from a local office server to a cloud Windows Server environment. Raff Windows VMs can serve as the destination for cloud file server workloads, shared folders, Remote Desktop users, business files, Access back ends, app exports, and office server replacement. Raff’s Windows migration and cloud file server guides help connect the file server move to broader planning around remote access, backups, and user workflows. Raff is not a replacement for file governance. The business or MSP still needs to decide folder ownership, permissions, retention, backup rules, access paths, and restore process. The Windows VPS provides the infrastructure foundation; the migration plan makes it safe. :::cta Deploy Windows Now Create a Raff Windows VM when your team is ready to move shared files from local office hardware to the cloud. ::: ## Final file server migration checklist Before cutover, confirm: | Check | Done | |---|---| | Source backup completed | ☐ | | Source restore test completed | ☐ | | Destination Windows VPS built and patched | ☐ | | Destination backups enabled | ☐ | | Existing shares inventoried | ☐ | | NTFS permissions reviewed | ☐ | | Stale data cleaned or archived | ☐ | | Test copy completed | ☐ | | Copy logs reviewed | ☐ | | Mapped drives planned | ☐ | | GPOs or scripts updated | ☐ | | User groups verified | ☐ | | App file paths tested | ☐ | | Final sync window scheduled | ☐ | | Real user access tested | ☐ | | Rollback plan written | ☐ | | Old server preserved after cutover | ☐ | If any item is unclear, pause before moving production users. ## What's next - Review Raff’s [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) if you want migration help. - Read [Windows Server Migration Checklist for Small Businesses](https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business) before moving production workloads. - Read [Local Office Server to Cloud Windows VPS Migration](https://rafftechnologies.com/windows-server/local-server-to-cloud-windows-vps-migration) if the file server is part of a larger office server move. - Read [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) if you are still deciding the file server architecture. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before moving production folders. - Read [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) before giving users remote access. - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing CPU, RAM, and storage. - Review [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) and [pricing](https://rafftechnologies.com/pricing) when planning the destination server. ## Sources - Microsoft Learn — [Storage Migration Service overview](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/overview) - Microsoft Learn — [Migrate a file server by using Storage Migration Service](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/migrate-data) - Microsoft Learn — [What is SMB File Sharing for Windows and Windows Server?](https://learn.microsoft.com/en-us/windows-server/storage/file-server/file-server-smb-overview) - Microsoft Learn — [SMB features in Windows and Windows Server](https://learn.microsoft.com/en-us/windows-server/storage/file-server/smb-feature-descriptions) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Raff — [Windows Server migration page](https://rafftechnologies.com/windows-server/migration) - Raff — [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) - Raff — [Windows VM product page](https://rafftechnologies.com/products/windows-vm) - Raff — [Pricing](https://rafftechnologies.com/pricing) --- ### Windows Server Migration Checklist for Small Businesses URL: https://rafftechnologies.com/windows-server/windows-server-migration-checklist-small-business Description: Use this Windows Server migration checklist to plan apps, files, users, RDP/RDS, SQL Server, Active Directory, backups, testing, cutover, and rollback. Category: migration A Windows Server migration checklist helps small businesses move users, apps, files, databases, Remote Desktop access, and backups without turning the cutover into guesswork. Before migrating to a new Windows Server or cloud Windows VPS, document what the old server does, test the destination, protect the data, plan rollback, and move production only after users can complete real workflows. Raff Technologies provides Windows VMs and Windows migration support for teams that want to move Windows workloads to cloud-hosted infrastructure. A server migration is not only an operating system task. It is a business continuity task. The server may hold files, accounting software, SQL Server databases, Active Directory, Remote Desktop users, IIS apps, printers, scheduled jobs, certificates, mapped drives, and vendor software. That is why small businesses should not start with “copy everything to the new server.” Start with the checklist. Then decide what should migrate, what should be rebuilt, what should be retired, and what needs a test before the cutover. ## Quick migration checklist Use this table as the short version before starting the project. | Phase | Checklist item | |---|---| | Scope | List every server role, app, database, share, user, and dependency. | | Destination | Decide whether the new environment is a physical server, cloud Windows Server, or Windows VPS. | | Access | Plan RDP, RDS, RD Gateway, VPN, DNS, firewall rules, and user access. | | Apps | Confirm vendor support, installers, licenses, versions, and data locations. | | Files | Inventory shared folders, NTFS permissions, mapped drives, and storage growth. | | Databases | Plan SQL Server backup/restore, logins, jobs, connection strings, and tests. | | Active Directory | Review domain controllers, DNS, FSMO roles, GPOs, and replication if AD is involved. | | Backups | Take source backups and confirm destination backup policy before cutover. | | Testing | Test real user workflows, not only server login. | | Cutover | Schedule downtime, freeze writes, copy final data, switch users, and verify. | | Rollback | Keep the old environment available until the new one is proven. | | Documentation | Record credentials, access paths, support owners, backups, and restore steps. | The goal is not to make migration complicated. The goal is to prevent surprises after users start working on the new server. ![Roadmap visual showing Windows Server migration phases from inventory to cutover and monitoring](https://raff-images.s3.raffusercloud.com/windows_server_migration_phases_roadmap_webp_5265197bcc.png) :::cta Talk to Windows Engineer Need help planning your Windows Server migration? Talk to Raff before moving production users, files, apps, databases, and remote access. ::: ## Why migration planning matters for small businesses Small businesses often run a lot of business logic on one server. The server may have started as a file share, then gained accounting software, remote users, SQL Server, printers, scheduled exports, vendor tools, and backup jobs over time. That creates hidden migration risk. Common hidden dependencies include: | Hidden dependency | Why it matters | |---|---| | Mapped drives | Apps may expect the same drive letter or UNC path. | | Local service accounts | Services may stop if credentials are missing. | | Scheduled tasks | Reports, exports, sync jobs, and backups may not run. | | SQL logins | Database restores can succeed while app logins fail. | | Printer drivers | Reports, labels, and PDFs may print differently. | | Certificates | IIS, RD Gateway, VPN, or apps may depend on them. | | DNS records | Users and apps may still point to the old server. | | Firewall rules | Apps may need specific inbound or outbound ports. | | Vendor licensing | Software activation may not survive a server move. | | User permissions | Access may break if groups and NTFS permissions are not migrated correctly. | ![Visual showing hidden Windows Server migration dependencies including mapped drives, SQL logins, certificates, DNS, printers, and scheduled tasks](https://raff-images.s3.raffusercloud.com/windows_server_migration_hidden_dependencies_webp_1c8464c54c.png) A migration checklist forces those issues into the open before the cutover. ## Choose the migration approach first Microsoft describes several methods for moving to a newer Windows Server version, including in-place upgrade, clean install, migration, cluster rolling upgrade, and edition conversion. Each method has different trade-offs for downtime, complexity, and hardware requirements. For small businesses, the most common choices are: | Approach | What it means | Best fit | |---|---|---| | In-place upgrade | Upgrade the existing server OS while keeping roles and data | Lower hardware change, but higher risk if the old server is messy | | Side-by-side migration | Build a new server and move roles/data/apps to it | Best for cleaner migrations and cloud Windows VPS moves | | Clean rebuild | Reinstall apps and recreate settings manually | Good when old server is undocumented or unhealthy | | File/data migration | Move shares and permissions to a new server | Good for file server replacement | | App/database migration | Move app and database together | Good for business software, SQL, ERP, Access, tax tools | | Hybrid migration | Keep some roles local and move others to cloud | Good when local devices or compliance needs remain | ![Architecture visual showing side-by-side Windows Server migration from old office server to cloud Windows VPS](https://raff-images.s3.raffusercloud.com/windows_server_side_by_side_migration_architecture_webp_85380d8f15.png) For Raff Windows VPS migrations, side-by-side migration is usually the cleaner model. You build the destination Windows VM, test it, copy data, verify apps, then cut over users. ## Phase 1: inventory the current server Do not migrate what you do not understand. Start with inventory. Document: | Area | What to capture | |---|---| | Server identity | Name, IP address, OS version, domain membership | | Roles | File server, AD DS, DNS, DHCP, RDS, IIS, SQL Server, print server | | Applications | Business apps, versions, install paths, vendor contacts | | Users | Admins, staff users, groups, service accounts | | Files | Shares, folders, permissions, mapped drives | | Databases | SQL instances, databases, jobs, maintenance plans | | Scheduled tasks | Exports, reports, backups, scripts | | Certificates | IIS, RD Gateway, VPN, internal app certificates | | Firewall | Inbound/outbound rules and app-specific ports | | Backups | Tools, schedules, destinations, retention, restore status | | Dependencies | Printers, scanners, USB devices, integrations, APIs | Write this down before touching the destination server. Many migration problems are actually discovery problems. ## Phase 2: decide what moves and what retires Migration is a good moment to clean up. Not everything should move. Sort workloads into four groups: | Group | Meaning | |---|---| | Migrate | Still used and must move to the new server | | Rebuild | Still used, but should be installed cleanly | | Replace | Better handled by SaaS, managed service, or newer architecture | | Retire | No longer needed and should not move | Examples: | Item | Possible decision | |---|---| | Active accounting app | Migrate or rebuild | | Old employee folders | Archive or retire | | Abandoned app installer folders | Retire | | SQL database for active ERP | Migrate carefully | | Legacy Access database | Test and migrate with split design | | Old user profiles | Migrate selectively | | Print server role | Migrate only if still needed | | Local backup folders | Replace with new backup strategy | Moving every old folder and app without review creates a new server with old clutter. ## Phase 3: choose the destination environment For small businesses, the destination is usually one of three options: | Destination | Best fit | |---|---| | New local server | Best when users are on-site, internet is unreliable, or local hardware is required | | Cloud Windows Server / Windows VPS | Best for remote access, hosted apps, multi-location users, and office server replacement | | Hybrid setup | Best when some roles must stay local and others can move to cloud | A Windows VPS is a strong fit when the business needs: - Remote Desktop access - shared Windows apps - cloud file server workloads - accounting or tax software - Microsoft Access or legacy apps - ERP or inventory software - SQL Server tools - IIS/.NET workloads - a replacement for aging office hardware It is not always the right fit for high-availability architectures, heavy LAN-only file workloads, unsupported vendor apps, or local hardware dependencies that have not been tested. :::cta Explore Windows VM Use Raff Windows VM as the destination environment for Windows Server migration, remote access, apps, and shared workloads. ::: ## Phase 4: plan remote access and user sessions If users will access the new server remotely, plan the access model before migration. Use this table: | Access need | Planning direction | |---|---| | One or two admins only | Restricted admin RDP can work | | Staff need daily desktop sessions | Plan RDS Session Host and RDS CALs | | Users connect from changing networks | Consider RD Gateway or another controlled access layer | | Users need mapped drives | Plan VPN/private access or RDP/RDS workflow | | Users only need a web app | Do not give full desktop access unnecessarily | | MSP manages the environment | Standardize access policy and documentation | Microsoft states that each user or device connecting to an RD Session Host running Windows Server needs an RDS Client Access License. Build that into migration planning before staff start using the new server daily. Remote access is not just a port. It affects licensing, security, user experience, support, and backup risk. ## Phase 5: protect the source before changing anything Before migration work begins, protect the current environment. Do this before the first major change: | Backup item | Why it matters | |---|---| | Full server backup | Recover if migration work damages the source | | File backup | Restore shares and user data | | Database backup | Recover SQL/app data cleanly | | System state backup | Important for AD/domain-controller scenarios | | App-specific backup | Required for accounting, ERP, tax, Access, and vendor apps | | Export key settings | IIS, certificates, scheduled tasks, firewall rules, app configs | | Restore test | Proves backup is usable | A backup that has never been restored is an assumption. At minimum, test restoring a file, a folder, and one business-critical app or database backup before cutover. ## Phase 6: build the destination server cleanly Build the destination before moving production data. For a Windows VPS destination, prepare: | Item | Checklist | |---|---| | OS version | Choose supported Windows Server version | | VM size | Size CPU, RAM, and storage for users and workload | | Storage layout | Separate OS, data, app, or backup staging where useful | | Admin users | Named admin accounts, no shared daily admin login | | Firewall | Allow only required access paths | | Updates | Patch Windows before production | | Security baseline | Apply reasonable hardening before users connect | | Monitoring | Track CPU, RAM, disk, backups, and failed logins | | Backups | Enable backup policy before production data is stored | | Documentation | Record server name, IPs, roles, users, and access model | Do not build the new server in a hurry and then try to harden it later. Production hardening should happen before cutover. ## Phase 7: migrate file shares carefully File server migration is often more sensitive than it looks. Users care about folder paths, permissions, mapped drives, and file versions. For file shares, document: | File migration item | What to check | |---|---| | Share names | Keep or update share names deliberately | | NTFS permissions | Preserve or redesign permissions | | Share permissions | Confirm effective access | | Security groups | Use groups instead of per-user permissions where possible | | Mapped drives | Update scripts, GPOs, or documentation | | File ownership | Watch for orphaned SIDs or old users | | Long paths | Identify files that may fail to copy | | Open files | Schedule cutover during low activity | | Archive data | Do not migrate unnecessary old data | | Backup | Confirm new file backup policy | Microsoft’s Storage Migration Service is designed to inventory servers, transfer data to newer Windows servers or Azure virtual machines, and optionally transfer the source server identity so apps and users do not need to change links or paths. For SMB file server migrations, that tool can be useful when the migration scope fits. ## Phase 8: migrate applications and dependencies Business apps are usually the hardest part of the migration. Before installing or moving an app, confirm: | App migration item | What to check | |---|---| | Installer | Do you have the installer and license details? | | Vendor support | Does the vendor support Windows Server / RDS / cloud VM use? | | Data path | Where does the app store data? | | Service accounts | Which Windows accounts run services? | | Dependencies | .NET, ODBC, runtimes, drivers, Office/Access runtime | | Printers | Reports, labels, PDFs, and print drivers | | Mapped drives | Hardcoded drive letters or UNC paths | | Firewall | Required ports and outbound access | | Updates | App patch process and update timing | | Rollback | How to return to the old app if testing fails | Do not judge migration success by whether the app opens. Test real workflows: create a record, edit data, run a report, export a file, print, email, sync, and close the day. ## Phase 9: handle SQL Server and databases separately SQL Server migration needs its own plan. Copying database files is not the same as a validated database migration. For SQL Server, check: | SQL item | What to plan | |---|---| | Instances | Default and named instances | | Databases | Size, recovery model, owner, compatibility level | | Logins | SQL logins and Windows logins | | Jobs | SQL Agent jobs, schedules, maintenance | | Backups | Full, differential, log backups where needed | | Connection strings | Apps may point to old server name or IP | | Firewall | SQL ports and app connectivity | | Permissions | Database users and roles | | Collation | Compatibility with the application | | Restore test | Confirm app works after database restore | Microsoft documents SQL Server database copy by backup and restore, and SQL Server backup/restore planning includes strategy and security considerations. For small businesses, backup/restore is often the cleanest migration method because it creates a repeatable test before production cutover. If the app depends on SQL Server, test the app against the restored database on the new server before scheduling cutover. ## Phase 10: plan Active Directory carefully Active Directory migration is not a casual copy operation. If the old server is a domain controller, DNS server, or FSMO role holder, migration must be planned carefully. Check: | AD item | What to verify | |---|---| | Domain controllers | Which servers hold AD DS | | DNS | Which DNS zones and clients point to the server | | DHCP | Whether DHCP runs on the old server | | FSMO roles | Which server holds each role | | GPOs | Logon scripts, mapped drives, security policies | | Users/groups | Active, disabled, stale, service accounts | | Replication | Health of domain replication | | Time sync | Domain time source | | Certificates | AD CS or internal cert dependencies | | Decommission | Old DC removal plan after migration | Microsoft provides documentation for transferring FSMO roles in Active Directory Domain Services. If AD is involved, keep this article as a checklist and use a dedicated AD migration plan for the technical work. For many small businesses, AD migration is the point where it is worth talking to an engineer instead of improvising. :::cta Talk to Windows Engineer Review Active Directory, file shares, SQL Server, RDS, and app dependencies before cutting over your Windows Server migration. ::: ## Phase 11: test with real users A migration is not validated until real users can complete real work. Test: | Test area | Example | |---|---| | Login | Users can sign in with correct permissions | | Remote access | RDP/RDS/RD Gateway works from expected locations | | Files | Users can open, edit, save, and find shared folders | | Apps | Business software launches and completes normal workflow | | Database | App connects to SQL or local database correctly | | Reports | Reports generate and export correctly | | Printing | Printers, labels, PDFs, and forms work | | Scanning | Scanner or document workflow is usable | | Scheduled tasks | Reports, backups, and sync jobs run | | Backups | Destination backups complete successfully | | Restore | At least one restore test succeeds | Do not let only the technical admin test the new server. Include the person who uses the accounting app, the person who prints labels, the person who runs reports, and the person who needs remote access. ## Phase 12: plan the cutover window A cutover should have a written sequence. Example cutover plan: 1. Announce downtime window. 2. Confirm latest source backup. 3. Freeze writes on the old server. 4. Stop relevant services or app access. 5. Run final file/database sync. 6. Restore or attach final database on destination. 7. Update DNS, mapped drives, shortcuts, or connection strings. 8. Start destination services. 9. Test admin login. 10. Test user login. 11. Test files, apps, reports, printing, and backups. 12. Confirm users can work. 13. Keep old server online but read-only or isolated. 14. Monitor logs and user reports after launch. The cutover should be boring. If it feels exciting, too much was left unknown. ## Phase 13: keep rollback available Rollback is not failure. It is risk management. Before cutover, define: | Rollback item | Question | |---|---| | Trigger | What problem requires rollback? | | Owner | Who decides rollback? | | Time limit | How long before rollback becomes harder? | | Data state | How will writes on the new server be handled? | | Old server | Is it still intact and accessible? | | DNS/access | How do users return to the old path? | | Communication | Who tells users what to do? | Keep the old environment available until the new one is proven. Do not wipe or repurpose the old server immediately after first login works. ## Phase 14: monitor after migration The first week after migration matters. Monitor: | Signal | Why | |---|---| | CPU | Detect undersizing or app spikes | | RAM | Identify RDS/user/app pressure | | Disk free space | Prevent file, profile, and backup failures | | Backup success | Confirm new protection is working | | Failed logins | Detect remote access issues or attacks | | Event logs | Catch services, drivers, app errors | | User complaints | Slow workflows reveal real bottlenecks | | Scheduled tasks | Ensure reports and sync jobs still run | | SQL jobs | Confirm maintenance and backups run | | RDP/RDS sessions | Understand peak concurrent usage | Migration is not done when the old server is shut down. It is done when the new server is stable, backed up, documented, and users can work normally. ## Checklist by workload type Different server roles need different migration attention. | Workload | Migration focus | |---|---| | File server | Shares, NTFS permissions, mapped drives, backup, cutover | | RDP/RDS server | User sessions, RDS CALs, profiles, RD Gateway, performance | | SQL Server | Backup/restore, logins, jobs, connection strings, restore test | | Active Directory | DC health, DNS, FSMO, GPOs, replication, decommission | | IIS/.NET | Sites, app pools, certificates, bindings, configs, databases | | Accounting software | Vendor support, data path, printers, backups, user testing | | Access/legacy apps | Split design, file paths, RDP/RDS testing, backups | | Tax software | Seasonal users, client files, vendor support, backups | | ERP/inventory | Database, reports, integrations, devices, warehouse workflows | This is why one generic migration plan is not enough. Use the checklist as the control layer, then use workload-specific guides for detailed execution. ## How Raff fits Windows Server migration Raff fits Windows Server migration when a small business wants to move from an aging office server, unsupported Windows Server version, branch server, or local business software environment to a cloud-hosted Windows Server VM. Raff Windows VMs can serve as the destination for Remote Desktop environments, business apps, cloud file servers, SQL Server tools, Access and legacy apps, tax software, ERP/inventory workloads, and MSP-managed client environments. Raff is not a replacement for application vendor support, licensing review, or workload-specific testing. The clean model is: use Raff for the Windows VM infrastructure, then migrate with a clear plan for apps, users, files, databases, backups, access, and cutover. :::cta Explore Data Protection Protect your Windows Server migration with backup, snapshot, and restore planning before moving production workloads. ::: ## Final pre-cutover checklist Before production cutover, confirm: | Check | Done | |---|---| | Source backup completed | ☐ | | Source restore test completed | ☐ | | Destination Windows VM built and patched | ☐ | | Destination backups enabled | ☐ | | Users and admins documented | ☐ | | Apps installed and tested | ☐ | | File shares copied and permissions verified | ☐ | | SQL databases restored and app-tested | ☐ | | RDS/RD Gateway/RDP access tested | ☐ | | RDS CAL requirements reviewed | ☐ | | Printers/scanners/reports tested | ☐ | | DNS/mapped drives/connection strings planned | ☐ | | Cutover window approved | ☐ | | Rollback plan written | ☐ | | Old server preserved after cutover | ☐ | | Post-migration monitoring assigned | ☐ | ![Final Windows Server migration cutover checklist showing backups, apps, files, RDS, SQL, rollback, and monitoring](https://raff-images.s3.raffusercloud.com/windows_server_migration_cutover_checklist_webp_7471522113.png) If any line is unclear, pause before moving production users. ## What's next - Review Raff’s [Windows Server migration service](https://rafftechnologies.com/windows-server/migration) if you want migration help. - Read [How to Migrate Windows Server 2016 to 2025](https://rafftechnologies.com/windows-server/migrate-windows-server-2016-to-2025) if your source server is still Windows Server 2016. - Read [Cloud Windows Server vs Local Office Server](https://rafftechnologies.com/windows-server/cloud-windows-server-vs-local-office-server) if you are deciding whether to keep local hardware. - Read [Windows VPS sizing for remote users](https://rafftechnologies.com/windows-server/windows-vps-sizing-remote-users) before choosing CPU, RAM, and storage. - Read [Windows VPS Backup Strategy for Small Businesses](https://rafftechnologies.com/windows-server/windows-vps-backup-strategy-small-business) before migrating production data. - Read [Remote Desktop Gateway vs Direct RDP](https://rafftechnologies.com/windows-server/remote-desktop-gateway-vs-direct-rdp) before exposing remote access. - Read [Windows VPS as a Cloud File Server](https://rafftechnologies.com/windows-server/windows-vps-cloud-file-server) if file shares are part of the migration. - Review [Raff Windows VM](https://rafftechnologies.com/products/windows-vm) and [pricing](https://rafftechnologies.com/pricing) when planning the destination server. ## Sources - Microsoft Learn — [Plan Your Windows Server Upgrade Path](https://learn.microsoft.com/en-us/windows-server/get-started/install-upgrade-migrate) - Microsoft Learn — [Upgrade and migrate roles and features in Windows Server](https://learn.microsoft.com/en-us/windows-server/get-started/upgrade-migrate-roles-features) - Microsoft Support — [Support for Windows Server 2016 will end in January 2027](https://support.microsoft.com/en-us/topic/support-for-windows-server-2016-will-end-in-january-2027-ffd9e92c-5027-4201-b6e1-ed46f8486b43) - Microsoft Learn — [Storage Migration Service overview](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/overview) - Microsoft Learn — [Migrate a file server by using Storage Migration Service](https://learn.microsoft.com/en-us/windows-server/storage/storage-migration-service/migrate-data) - Microsoft Learn — [License Remote Desktop Services with Client Access Licenses](https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-access-license) - Microsoft Learn — [Ba