Deploy Payload CMS, the code-first headless CMS built with TypeScript and React that gives developers full control over their content architecture.
Grab the automated bash script from GitHub to follow along with the video.
wget https://raw.githubusercontent.com/mhmdali94/Docker/main/cms/payload/payload-ubuntu.sh
chmod +x payload-ubuntu.sh
sudo bash payload-ubuntu.sh
The script installs Docker, pulls the Payload CMS and MongoDB images, configures environment variables including the secret key, and starts both containers. Payload will be available on port 3000 with MongoDB running internally on port 27017 for data persistence.
wget https://raw.githubusercontent.com/mhmdali94/Docker/main/cms/payload/payload-ubuntu.sh
chmod +x payload-ubuntu.sh
sudo bash payload-ubuntu.sh
Open your browser and navigate to the Payload admin panel. On first run, you will be prompted to create your first administrator user with email, username, and password.
http://<your-server-ip>:3000/admin
Collections in Payload are defined in TypeScript config files. Edit your payload.config.ts to add a Posts collection with fields for title (text), content (richText), author (relationship), and publishedAt (date). Payload automatically generates REST and GraphQL endpoints, admin UI forms, and TypeScript types for each collection. Restart the container after saving changes.
# Example collection definition in payload.config.ts
collections: [
{
slug: 'posts',
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'richText' },
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'publishedAt', type: 'date' },
],
},
]
Payload automatically exposes a REST API for every collection. Use GET to fetch documents, POST to create, PATCH to update, and DELETE to remove. For authenticated endpoints, include a Bearer token obtained from the /api/users/login endpoint. The API follows predictable URL patterns based on your collection slugs.
# Fetch all posts (public if access allows)
curl http://<your-server-ip>:3000/api/posts
# Create a post with authentication
curl -X POST http://<your-server-ip>:3000/api/posts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "My First Post", "content": {"root": {}}}'
| Port | Purpose |
|---|---|
| 3000 | Payload CMS Web UI & API |
| 27017 | MongoDB (internal) |
Payload CMS is a TypeScript-first, code-driven headless CMS built for developers. Configuration is entirely in code — no GUI-based setup needed. It provides a beautiful auto-generated admin panel, REST and GraphQL APIs, and deep TypeScript integration with your frontend, making it ideal for Next.js and modern JS apps.
Payload CMS is designed for developers who want a CMS they fully control through code rather than database GUIs. The config-as-code approach means your CMS schema is version controlled, deployable like any app, and can be reviewed in PRs — eliminating the chaos of undocumented GUI-configured CMS installations.
Payload CMS runs on port 3000 by default. In production, serve it behind a reverse proxy on port 443 with HTTPS. The MongoDB connection port 27017 must never be exposed publicly.
Alternatives include Strapi (more GUI-driven, wider adoption), Directus (wraps existing databases), Sanity (cloud-native, hosted), and Contentful (SaaS, polished). Choose Payload for maximum developer control with TypeScript-first code configuration.
Avoid Payload if your content editors need a standalone no-code CMS — the code-first approach requires a developer to add new fields or change schemas. Also avoid if you need a WordPress plugin ecosystem or WooCommerce-style e-commerce.
PrismaTechWork provides end-to-end infrastructure services — from initial deployment and security hardening to ongoing monitoring, automated backups, and dedicated support. Whether you need a single-server setup or a multi-site network, our team ensures your infrastructure is built right, secured properly, and maintained reliably.
Payload v2 uses MongoDB. Payload v3 (the latest) supports both MongoDB and PostgreSQL via database adapters, giving you flexibility. The Docker setup includes a MongoDB container automatically. PostgreSQL is recommended for relational data needs.
Yes — Payload auto-generates a clean admin panel UI from your collection and field definitions. Editors log into the admin panel and manage content via forms, rich text editors, and media uploaders without touching code. Only developers need to modify the TypeScript configuration.
In Payload v3, you can run Payload inside the same Next.js project — the CMS and frontend share one codebase. For separate deployments, use the REST API or GraphQL API. Payload provides TypeScript types for all your collections that you can import into your Next.js app for full type safety.
Yes. Payload has a richText field type that supports Lexical (the default, block-based editor) and Slate. The Lexical editor supports custom blocks, inline fields, relationship fields, and links embedded in content — enabling flexible page builder-style content structures.
Access control in Payload is defined as functions in your TypeScript config. Each collection and field can have create, read, update, and delete access functions that receive the user object and return true or false. This allows arbitrarily complex rules like allowing users to edit only their own records.
Yes. Define upload-enabled collections in Payload and it automatically generates file upload fields, stores files on disk or in cloud storage (S3), and provides image resizing. Uploaded media are served via the Payload server and can be queried and referenced by other collections.