[{"data":1,"prerenderedAt":223},["ShallowReactive",2],{"seo-verification":3,"blog-hosting-directus-on-a-vps-ma-en":6,"promo-bar-likely":222},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-hosting-directus-on-a-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":162,"ctaBody":163,"ctaButton":164,"ctaUrl":165,"relatedPosts":166},63,"hosting-directus-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"heberger-directus-vps","استضافة-directus-على-خادم-vps","alojar-directus-en-un-vps","Hosting Directus on a VPS","Host Directus on your VPS: an open source headless CMS and data platform on top of your SQL database. Docker, Postgres, reverse proxy, and SSL guide.",11,0,false,"2026-04-18T00:00:00+00:00","2026-11-04T16:30:25+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},6,"Databases","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fheberger-directus-vps-poster.svg",{"categorySlug":34,"appSlug":35},"cms-websites","directus","Directus turns any SQL database into an instant REST and GraphQL API, with a no-code administration interface on top. It's a headless CMS and a complete data platform, perfect to self-host on a VPS to manage the content of your sites and applications. Here's how to deploy it with PostgreSQL, Docker, and an SSL certificate.",[38,42,52,55,77,80,83,86,95,113,116,144,147,157,159],{"type":39,"title":40,"body":41},"h2","Why self-host Directus on a VPS","Directus plugs into your existing database (PostgreSQL, MySQL, SQLite, MariaDB) without imposing its own schema: it introspects your tables and generates an API and an admin interface on top. By self-hosting it on a VPS, you avoid the per-seat pricing of the official Cloud offering and you keep your content, your media, and your SQL database on your own infrastructure. It's a structuring choice for agencies that deliver several sites: a single Directus can serve as the back office for multiple front-ends (Nuxt, Next, mobile). Control of the database, extensions, and webhooks lets you integrate Directus into any data pipeline without depending on a third-party provider, with no third-party service sitting between your front-ends and your data.",{"type":43,"title":44,"items":45},"ul","The concrete benefits of self-hosting Directus",[46,47,48,49,50,51],"REST and GraphQL APIs generated automatically from your SQL schema, without writing code.","A no-code admin interface to model content, manage roles, and set granular permissions.","Compatible with an existing SQL database: you can expose it without migrating or altering it.","Media management, on-the-fly image transformations, and local or S3 storage of your choice.","Built-in Flows and webhooks to automate processing (notifications, synchronizations).","Pooling: a single Directus VPS can power several sites and front-end applications.",{"type":39,"title":53,"body":54},"Hardware and software prerequisites","Directus is a Node.js application that relies on an external database. Count on a minimum of 2 GB of RAM to comfortably run Directus and PostgreSQL on the same VPS; 4 GB are recommended in production with image transformations and several simultaneous administrators. One to two vCPU are enough to start. Plan for a Redis cache (optional but recommended for sessions and rate limiting) and a 30 to 60 GB SSD volume depending on your media library. You'll need Docker and Docker Compose, a domain pointing to the VPS, and a robust secret key for `SECRET` and token hashing. Postgres remains the recommended database for advanced features.",{"type":56,"title":57,"steps":58},"steps","Deploying Directus step by step",[59,62,65,68,71,74],{"title":60,"body":61},"Provision the VPS and Docker","After connecting via SSH, install Docker and Docker Compose. Create an A DNS record for `cms.mydomain.com` pointing to the VPS IP. Open only ports 80 and 443 in the firewall (`ufw allow 80,443\u002Ftcp`).",{"title":63,"body":64},"Define the stack in docker-compose.yml","Declare three services: `database` (image `postgres:16` with a persistent volume), `cache` (`redis`), and `directus` (`directus\u002Fdirectus`). Connect Directus to Postgres via the variables `DB_CLIENT=pg`, `DB_HOST=database`, `DB_DATABASE`, `DB_USER`, `DB_PASSWORD`.",{"title":66,"body":67},"Configure the environment variables","Fill in `KEY` and `SECRET` with random strings (`openssl rand -hex 32`), set `ADMIN_EMAIL` and `ADMIN_PASSWORD` for the first account, and `PUBLIC_URL=https:\u002F\u002Fcms.mydomain.com` so that links and uploads are correct.",{"title":69,"body":70},"Start and initialize the database","Run `docker compose up -d`. On the first startup, Directus automatically creates the system tables and the admin account. Follow the initialization with `docker compose logs -f directus`.",{"title":72,"body":73},"Connect the reverse proxy and TLS","Put Caddy or Traefik in front of Directus to handle Let's Encrypt. With Traefik, add the routing labels on the `directus` service and the ACME certresolver. Make sure `PUBLIC_URL` exactly matches the HTTPS domain to avoid CORS and upload issues.",{"title":75,"body":76},"Secure and back up","Restrict the CORS origins to your front-ends' domains, disable public registration if unnecessary, then schedule a daily `pg_dump` plus a copy of the `uploads` folder to remote storage.",{"type":78,"body":79},"tip","To serve images efficiently, enable media storage on an S3-compatible bucket rather than the local disk, and set `ASSETS_CACHE_TTL`: this variable sets the browser-side cache duration (the `max-age` value of the `Cache-Control` header, 30 days by default); it does not cache transformations on the server. Put a CDN in front of Directus to offload media requests from the VPS. Then bound on-the-fly transformations: `ASSETS_TRANSFORM_MAX_OPERATIONS` limits the number of operations per request (5 by default, excluding saved presets), `ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION` the size in pixels (6000 by default) and `ASSETS_TRANSFORM_MAX_CONCURRENT` the number of simultaneous transformations (25 by default).",{"type":39,"title":81,"body":82},"Serving files from S3: what it changes for memory","When media storage points to an S3-compatible bucket, Directus does not redirect the visitor to the bucket: the `\u002Fassets\u002FFILE_ID` request goes through the Node process, which reads the object from the provider and streams it back to the client. The driver is configured with variables: `STORAGE_LOCATIONS=s3`, then `STORAGE_S3_DRIVER=s3`, `STORAGE_S3_KEY`, `STORAGE_S3_SECRET`, `STORAGE_S3_BUCKET`, `STORAGE_S3_REGION` and, for compatible storage such as MinIO, `STORAGE_S3_ENDPOINT` with `STORAGE_S3_FORCE_PATH_STYLE=true`. In practice, the container's memory depends on the number of simultaneous downloads and the speed of each client, not only on the size of the database. This is the path where users report memory that never comes back down, especially with videos or large files.",{"type":39,"title":84,"body":85},"Troubleshooting: memory climbs until the container is killed","The symptom is described in issue 26206 of the directus\u002Fdirectus repository, opened in November 2025 on a self-hosted Docker instance running 11.13.2 with PostgreSQL 16: the pod's memory rises steadily to the configured limit, then the pod is killed and restarts. The slope is lower at night and on weekends, which points to file traffic rather than an idle leak. At the time of writing (late October 2026), the issue is still open, labelled Bug, Performance and AWS S3. No Directus team member has confirmed a cause there: everything below is participants' hypotheses, not a maintainer diagnosis.",{"type":43,"title":87,"items":88},"What the issue participants report",[89,90,91,92,93,94],"**Heavy files** — the problem is reproduced with a k6 load script on videos of 36 to 86 MB, and on twelve files of about 500 MB; the request goes through `\u002Fassets`.","**Several storage backends** — AWS S3 and MinIO are mentioned, as well as another S3-compatible service at an application host.","**Slow growth with images** — one participant goes from about 200 MB after a redeploy to 1 GB within a few days; another sees pods climb from 1.3 GB to over 2 GB in nearly two weeks.","**Unclosed streams hypothesis** — a fix cleans up streams when a client disconnects mid-download; a contributor places it in 11.17.2, and one participant sees an improvement without the growth disappearing.","**Checksum hypothesis** — in October 2026, a participant blames the response checksum validation of the AWS S3 SDK: the validation stream (`ChecksumStream`, package `@smithy\u002Futil-stream`) would ignore backpressure. Their test bench: a 1 GiB limit and a 150 MB object; one slow client takes external memory from 8 to 160 MB, three clients cause a kill within 15 seconds, and files uploaded as multipart do not trigger it. They add that this does not explain slow growth over several days without large downloads.","**Report on version 12** — another participant says upgrading to version 12 fixed the problem for them, while the issue remains open.",{"type":56,"title":96,"steps":97},"Diagnosing without guessing",[98,101,104,107,110],{"title":99,"body":100},"Confirm the out-of-memory kill","Look for the kernel trace with `dmesg -T | grep -i \"out of memory\"`, follow `docker events --filter event=oom` or read the `OOMKilled` field of `docker inspect`. A kill of this kind leaves no Directus error message: the container simply restarts.",{"title":102,"body":103},"Set an explicit memory limit","In the Compose file, give the `directus` service a limit (`mem_limit` or `deploy.resources.limits.memory`) below the VPS's free RAM, with `restart: unless-stopped`. Without a limit, the host kernel picks which process to kill, sometimes PostgreSQL rather than Directus.",{"title":105,"body":106},"Measure the curve","Log `docker stats --no-stream` every minute to a file, along with the number of `\u002Fassets` requests in flight. Note the value after a restart, the plateau, and whether the curve follows traffic or climbs while idle. A Node heap limit (`--max-old-space-size`) does not bound off-heap memory, the buffers, which is the area targeted by the checksum hypothesis.",{"title":108,"body":109},"Reproduce with a slow client","On a test environment, never in production, download a large file with `curl --limit-rate 200k -o \u002Fdev\u002Fnull https:\u002F\u002Fcms.mydomain.com\u002Fassets\u002FFILE_ID` from several terminals and watch `docker stats`. A k6 script does the same more repeatably.",{"title":111,"body":112},"Capture two heap profiles","Add `NODE_OPTIONS=--heap-prof --heap-prof-dir=\u002Fdirectus\u002Fprofiles` to the service environment, with a folder mounted as a volume. Node only writes the profile on a clean process exit: stop the container with `docker compose stop directus` once right after startup (baseline), then a second time once memory has swollen. An out-of-memory kill ends the process without writing a profile.",{"type":39,"title":114,"body":115},"Reported workarounds, none confirmed by the Directus team","None of these leads has received official validation in the issue. Try them on a staging environment, measure before and after, and do not present them as fixes.",{"type":117,"title":118,"headers":119,"rows":123},"comparison","Leads reported for the memory problem",[120,121,122],"Lead","Where it was reported","Status and caveats",[124,128,132,136,140],[125,126,127],"`AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED`","A participant, in October 2026, with a test bench","Not confirmed by the team. According to AWS documentation, download checksum validation only happens when the caller explicitly enables it: you lose that integrity check.",[129,130,131],"Upgrade to version 12","One participant says it fixed the problem; another puts a fix at 12.3.1 or later","Not confirmed. The 12.3.1 release notes only mention updated storage driver dependencies. Major version change: read the notes and back up first.",[133,134,135],"Version 11.17.2 or later","A contributor recommends it for cleaning up streams of disconnected clients","The fix is merged and closes a different issue (26991); on issue 26206, a participant describes an improvement but growth that persists.",[137,138,139],"Scheduled redeploy through cron","A participant, as a stopgap","Hides the symptom without fixing anything, and cuts downloads in progress.",[141,142,143],"Memory limit and automatic restart","This guide's operating recommendation","Contains the damage: the container restarts cleanly instead of dragging the host down. Does not address the cause.",{"type":39,"title":145,"body":146},"What to collect for a useful bug report","The team asked for heap profiles: without them, the issue cannot move forward. Before commenting or opening a new issue, gather the items below.",{"type":43,"title":148,"items":149},"The file to attach",[150,151,152,153,154,155,156],"**Exact version** — the Directus image tag (not `latest`) and the date of the last restart.","**Storage** — driver, provider (AWS, MinIO, other) and region, without the key or secret, plus the value of `AWS_RESPONSE_CHECKSUM_VALIDATION` if it is set.","**Limits** — container memory, host RAM and restart policy.","**Load** — number and size of the files served, simultaneous downloads, presence of a CDN or proxy in front of Directus, slow or dropped clients.","**Memory curve** — total container memory (not just the process) over several days, with the `\u002Fassets` traffic alongside.","**Two heap profiles** — baseline and swollen state. The contributor who asks for them states they contain only stack traces and sampled allocation sizes, not file contents or secrets.","**How files were uploaded** — in one piece or as multipart, since a participant says the latter do not trigger the case.",{"type":78,"body":158},"Before upgrading to version 12, read the 12.3.0 release notes: it fixes storage connections that leaked when an asset request was cancelled or a transformation failed, but it also changes the behaviour of `exists()`, which now throws an error instead of returning false. With S3, a missing object can then produce a 403 response rather than a 404 if the credentials cannot list the bucket: grant `s3:ListBucket`. Back up the database and the files, then test the upgrade on a copy before touching production.",{"type":39,"title":160,"body":161},"One-click Directus deployment on ServOrbit","Directus is available directly from the ServOrbit Marketplace. Select the application when ordering your VPS: Docker comes pre-installed, the Directus container starts automatically, and your admin credentials (`admin@example.com` plus a generated password) are displayed in your ServOrbit dashboard. Access the admin interface via an SSH tunnel or by attaching a domain from your dashboard — without installing Docker or editing a Compose file by hand.","Deploy Directus on a VPS in one click","Order a ServOrbit VPS with Directus pre-installed: Docker configured, container running, admin credentials generated and shown in your dashboard. No manual configuration needed.","View Directus on the Marketplace","\u002Fapplications\u002Fcms-websites\u002Fdirectus",[167,187,204],{"id":168,"slug":169,"slugs":170,"title":174,"excerpt":175,"readTime":176,"views":177,"isPinned":19,"noindex":19,"publishedAt":178,"updatedAt":179,"category":180,"categories":181,"featuredImage":30,"bgImage":31,"posterImage":183,"relatedSolution":184},56,"postgresql-on-a-vps-a-reliable-and-controlled-database",{"fr":171,"en":169,"ar":172,"es":173},"heberger-postgresql-vps","postgresql-على-خادم-vps-قاعدة-بيانات-موثوقة-ومتحكم-بها","alojar-postgresql-en-un-vps","PostgreSQL on a VPS: reliable, controlled database","Host PostgreSQL on a VPS: production config, pgBackRest backups, streaming HA, RDS\u002FSupabase\u002FNeon comparison and OOM troubleshooting.",9,1,"2026-04-25T00:00:00+00:00","2026-10-21T15:21:37+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[182],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-postgresql-vps-poster.svg",{"categorySlug":185,"appSlug":186},"databases","postgresql-stack",{"id":188,"slug":189,"slugs":190,"title":194,"excerpt":195,"readTime":176,"views":18,"isPinned":19,"noindex":19,"publishedAt":196,"updatedAt":197,"category":198,"categories":199,"featuredImage":30,"bgImage":31,"posterImage":201,"relatedSolution":202},57,"hosting-mysql-on-a-vps",{"fr":191,"en":189,"ar":192,"es":193},"heberger-mysql-vps","استضافة-mysql-على-خادم-vps","alojar-mysql-en-un-vps","Hosting MySQL on a VPS: complete guide","Install MySQL 8.4 LTS on a VPS: prerequisites, security hardening, InnoDB performance, secure remote access, automated backups, and troubleshooting.","2026-04-24T00:00:00+00:00","2026-11-09T20:55:18+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[200],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-mysql-vps-poster.svg",{"categorySlug":185,"appSlug":203},"mysql-stack",{"id":205,"slug":206,"slugs":207,"title":211,"excerpt":212,"readTime":213,"views":18,"isPinned":19,"noindex":19,"publishedAt":214,"updatedAt":215,"category":216,"categories":217,"featuredImage":30,"bgImage":31,"posterImage":219,"relatedSolution":220},58,"hosting-redis-on-a-vps",{"fr":208,"en":206,"ar":209,"es":210},"heberger-redis-vps","استضافة-redis-على-خادم-vps","alojar-redis-en-un-vps","Hosting Redis on a VPS: the complete guide","Deploy Redis on your Cloud VPS: RAM\u002FCPU requirements, security (ACL, TLS), RDB\u002FAOF persistence, troubleshooting, and high availability.",10,"2026-04-23T00:00:00+00:00","2026-09-08T21:59:59+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[218],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-redis-vps-poster.svg",{"categorySlug":185,"appSlug":221},"redis-stack",true,1794270416608]