Skip to content

Conversation

ebenezerdon
Copy link
Contributor

@ebenezerdon ebenezerdon commented Jun 18, 2025

What does this PR do?

  • Structures self-hosting docs with categorisation and dedicated pages for hidden concepts where necessary
  • Updates navigation labels in the self-hosting layout
  • Adds installation and platform-specific guides for AWS, Azure, DigitalOcean, Render, etc
  • Adds self-hosting backups page/guide
  • Adds self-hosting version control page

Test Plan

  • /docs/advanced/self-hosting

Summary by CodeRabbit

  • New Features

    • Added Dockerfile/docker and dotenv (.env) code highlighting and recognition.
  • Documentation

    • Large self-hosting docs overhaul: reorganized navigation, new Quick Start, Production and Configuration workflows, many new/expanded pages for Installation, Platforms (AWS/Azure/DigitalOcean/Google Cloud/Coolify), Sites, Version Control, Functions, Security, Scaling, Rate limits, Email delivery, Error monitoring, Backups, and Updates & migrations.
  • Style

    • Whitespace and formatting cleanup in platform docs.

…nfiguration pages

- Updated navigation labels in the self-hosting layout for clarity and organization
- Moved documentation pages for configuring email, SMS, storage, TLS certificates, and environment variables
- Added installation and platform-specific guides for AWS, Azure, DigitalOcean, and more
- Improved overall structure and readability of the self-hosting documentation
…host.

Also add detailed considerations for data control and compliance requirements.
Copy link

appwrite bot commented Jun 18, 2025

appwrite.io

Project ID: 684969cb000a2f6c0a02

Sites (1)
Site Status Logs Preview QR
 website
68496a17000f03d62013
Failed Failed View Logs Preview URL QR Code

Note

Appwrite has a Discord community with over 16 000 members.

@@ -0,0 +1,167 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we refactor these 4 to be inside a "management" folder, just like how we render it?

Screenshot 2025-06-19 at 10 23 24 AM Screenshot 2025-06-19 at 10 26 37 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done

},
{
label: 'Debugging',
href: '/docs/advanced/self-hosting/debug'
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we missed adding the security doc:

Screenshot 2025-06-19 at 10 28 18 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

@ebenezerdon ebenezerdon requested a review from tessamero June 19, 2025 18:31
Remove App Platform section due to MySQL/MariaDB compatibility issues.
Keep Droplets, Kubernetes, and Marketplace options
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

♻️ Duplicate comments (9)
src/lib/utils/references.ts (1)

139-144: LGTM: docker/dockerfile/env/ini/dotenv labels added and prior feedback resolved.

Mappings are consistent with code.ts and address the earlier duplicate/gaps. Nice cleanup.

Run this quick check to ensure the new keys also exist in src/lib/utils/code.ts Language union and to prevent drift:

#!/bin/bash
set -euo pipefail

# Verify mappings exist in platformMap
for k in dockerfile docker ini env dotenv; do
  rg -nP "\\b${k}\\s*:\\s*'[^']+'" src/lib/utils/references.ts >/dev/null \
    || { echo "Missing platformMap key: ${k}"; exit 1; }
done

# Verify Language union includes the same keys
for k in dockerfile docker ini env dotenv; do
  rg -nPU "(?s)export\\s+type\\s+Language\\s*=\\s*[^;]*'${k}'" src/lib/utils/code.ts >/dev/null \
    || { echo "Missing Language union member in code.ts: '${k}'"; exit 1; }
done

echo "OK: platformMap and Language union are in sync."
src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc (2)

86-94: Don’t expose port 8080 publicly; keep it internal behind your reverse proxy.

Change 8080 to internal-only and add an explicit note. This was raised earlier and remains unresolved.

 * Custom
 * TCP
 * 8080
-* All IPv4, All IPv6
+* Internal only (reverse proxy)
+{% info title="Keep 8080 private" %}
+Do not expose port 8080 to the public internet. Terminate TLS on 443 and proxy requests internally to 8080.
+{% /info %}

177-181: Align resource minima with production scaling docs.

512Mi minimum is too low; set 2Gi as minimum to prevent OOMs under real workloads.

-   - Memory: 512Mi minimum, 2Gi recommended
+   - Memory: 2Gi minimum (increase based on workload)
src/routes/docs/advanced/self-hosting/production/updates/+page.markdoc (1)

9-9: Consistent terminology: “Docker Compose v2”.

Minor copy fix for consistency.

-As of version 0.14, Appwrite requires [Docker Compose Version 2](https://docs.docker.com/compose/install/). To upgrade Appwrite, make sure your Docker installation is updated to support Compose V2.
+As of version 0.14, Appwrite requires [Docker Compose v2](https://docs.docker.com/compose/install/). To upgrade Appwrite, make sure your Docker installation is updated to support Compose v2.
src/routes/docs/advanced/self-hosting/production/backups/+page.markdoc (2)

44-46: Add the actual stop command before volume backups.

You state to shut down but don’t show how. Add this snippet.

-Shut down Appwrite before backing up volumes to avoid data inconsistency.
+Shut down Appwrite before backing up volumes to avoid data inconsistency.
+
+```bash
+docker compose down
+```

47-56: Call out ephemeral volumes to skip in backups.

Redis/cache volumes are ephemeral and typically not worth backing up/restoring.

 - `appwrite-cache` and `appwrite-redis` - Cache data
+ - `appwrite-cache` and `appwrite-redis` - Cache data (ephemeral; generally skip in backups/restores)
src/routes/docs/advanced/self-hosting/+page.markdoc (3)

133-143: Use sentence case for card titles (consistency).

-{% cards_item href="/docs/advanced/self-hosting/configuration/sms" title="SMS Delivery" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/sms" title="SMS delivery" %}
 ...
-{% cards_item href="/docs/advanced/self-hosting/configuration/storage" title="Storage Backends" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/storage" title="Storage backends" %}
 ...
-{% cards_item href="/docs/advanced/self-hosting/configuration/functions" title="Functions Runtime" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/functions" title="Functions runtime" %}

166-170: Deep-link ops items to their docs.

-- **Log Management** - Centralize and analyze application logs
-- **Backup Strategy** - Implement regular database and file backups
-- **Update Management** - Keep Appwrite updated with the latest releases
+- **Log management** - Centralize and analyze application logs
+- **Backup strategy** - Implement regular database and file backups. See [Backups](/docs/advanced/self-hosting/production/backups).
+- **Update management** - Keep Appwrite updated with the latest releases. See [Updates](/docs/advanced/self-hosting/production/updates).

177-181: Point “Get started” to section anchors, not a single provider page.

-**Cloud Deployment** - [Choose a cloud platform](/docs/advanced/self-hosting/platforms/aws) for production hosting
+**Cloud deployment** - [Choose a cloud platform](/docs/advanced/self-hosting#cloud-platforms) for production hosting

-**One-Click Deploy** - Use a [marketplace installation](#one-click-deployments) for instant setup
+**One-click deploy** - Use a [marketplace installation](#one-click-deployments) for instant setup

-**Platform-as-a-Service** - Deploy on [Coolify](/docs/advanced/self-hosting/platforms/coolify) or similar platforms for simplified management
+**Platform-as-a-service** - [Deploy on a PaaS](#paas-platforms) for simplified management
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f9ed389 and 87ad9ec.

📒 Files selected for processing (5)
  • src/lib/utils/references.ts (1 hunks)
  • src/routes/docs/advanced/self-hosting/+page.markdoc (2 hunks)
  • src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/production/backups/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/production/updates/+page.markdoc (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: tests
  • GitHub Check: build

Comment on lines 131 to 139
{% section #setup-ssl step=2 title="Set up SSL with Let's Encrypt" %}

1. **Install Certbot** for automated SSL certificate management
2. **Configure Nginx** as a reverse proxy
3. **Obtain SSL certificates** using Certbot with the nginx plugin
4. **Enable automatic renewal** to maintain valid certificates

For detailed SSL setup instructions, see the [SSL certificates guide](/docs/advanced/self-hosting/configuration/tls-certificates).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

TLS guidance conflicts with default Traefik flow; clarify single-termination path.

Appwrite ships with Traefik for TLS. If recommending Nginx+Certbot, instruct users to disable Traefik TLS and proxy only to 8080, or alternatively keep Traefik as the TLS terminator and remove the Nginx steps. Pick one and document it to avoid double TLS and port exposure.

Would you like me to provide a minimal Nginx reverse-proxy snippet for 443→8080 and the Traefik config toggles?


🏁 Script executed:

#!/bin/bash
set -e
# Search for Traefik references in the DigitalOcean self-hosting doc
rg -n "Traefik" -C3 src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc || true
# Search for Traefik references across self-hosting docs
rg -n "Traefik" -C3 src/routes/docs/advanced/self-hosting || true
# Search across the repository for Traefik
rg -n "Traefik" -C3 . || true

Length of output: 23613


Clarify TLS termination path. Document that if users follow the Nginx + Certbot flow, they must disable Appwrite’s default Traefik ACME and expose only port 8080; otherwise remove the Nginx steps and rely on Traefik for TLS termination.

🤖 Prompt for AI Agents
In src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc
around lines 131 to 139, clarify the TLS termination path: add a note that if
users implement the Nginx + Certbot flow they must disable Appwrite's default
Traefik ACME (disable Traefik's Let's Encrypt/ACME) and only expose Appwrite's
internal HTTP port (8080) to the proxy, otherwise they should remove the
Nginx/Cerbot steps and rely on Traefik for TLS termination; update the section
to explicitly state both options and reference the TLS certificates guide for
configuration details.

ebenezerdon and others added 5 commits August 28, 2025 21:23
…page.markdoc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…page.markdoc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…page.markdoc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
….markdoc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
….markdoc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ebenezerdon ebenezerdon requested a review from stnguyen90 August 28, 2025 20:31
Copy link
Contributor

@stnguyen90 stnguyen90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of my previous comments haven't been addressed:

  1. #2117 (comment)
  2. #2117 (comment)
  3. #2117 (comment)
  4. #2117 (comment)
  5. #2117 (comment)

@ebenezerdon
Copy link
Contributor Author

@stnguyen90 I've updated the tutorials. Please let me know if there's anything else I need to do

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
src/routes/docs/advanced/self-hosting/platforms/google-cloud/+page.markdoc (1)

35-45: Cloud Run must listen on $PORT; add a short note.

Avoid hardcoding port 80 to prevent 502s. Prefer built-in Cloud SQL connectors over the Auth Proxy.

 # Cloud Run deployment {% #cloud-run %}
 
 Deploy Appwrite using Google Cloud Run for a serverless, fully managed experience with automatic scaling.
 
 {% info title="Compatibility note" %}
 Appwrite uses MariaDB by default. Running against Cloud SQL for MySQL 8.x is unsupported and may break schema or SQL dialect assumptions. Test thoroughly in a staging environment or deploy MariaDB yourself on Compute Engine instead.
 {% /info %}
 
 For detailed Cloud Run deployment instructions, follow the [general installation guide](/docs/advanced/self-hosting/installation) and adapt the Docker commands for your Cloud Run environment.
+
+{% info title="Cloud Run port and database connectivity" %}
+- Ensure your container listens on the environment variable `$PORT` (commonly 8080). Do not hardcode port 80.
+- Prefer Cloud Run's built-in Cloud SQL connectors for database access instead of running the Cloud SQL Auth Proxy inside your container.
+{% /info %}
src/routes/docs/advanced/self-hosting/+page.markdoc (2)

120-136: Fix card title casing (sentence case).

Aligns with “Email delivery”.

-{% cards_item href="/docs/advanced/self-hosting/configuration/sms" title="SMS Delivery" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/sms" title="SMS delivery" %}
 ...
-{% cards_item href="/docs/advanced/self-hosting/configuration/storage" title="Storage Backends" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/storage" title="Storage backends" %}
 ...
-{% cards_item href="/docs/advanced/self-hosting/configuration/functions" title="Functions Runtime" %}
+{% cards_item href="/docs/advanced/self-hosting/configuration/functions" title="Functions runtime" %}

156-161: Deep-link production items and use sentence case.

Improves discoverability.

-- **Health Checks** - Set up monitoring for service availability and performance
-- **Log Management** - Centralize and analyze application logs
-- **Backup Strategy** - Implement regular database and file backups
-- **Update Management** - Keep Appwrite updated with the latest releases
+- **Health checks** - Set up monitoring for service availability and performance
+- **Log management** - Centralize and analyze application logs
+- **Backup strategy** - Implement regular database and file backups. See [Backups](/docs/advanced/self-hosting/production/backups).
+- **Update management** - Keep Appwrite updated with the latest releases. See [Updates](/docs/advanced/self-hosting/production/updates).
🧹 Nitpick comments (5)
src/routes/docs/advanced/self-hosting/platforms/google-cloud/+page.markdoc (1)

13-33: App Engine row is likely misleading—clarify suitability or remove.

Appwrite is a multi-container stack; App Engine is generally not a good fit unless you decompose services. Add an explicit caveat.

 {% /table %}
 
+{% info title="App Engine considerations" %}
+Appwrite runs multiple containers (API, DB, queue, cache, etc.). Google App Engine typically isn't suitable for this topology unless you split services and manage routing yourself. Prefer Cloud Run or Compute Engine for standard deployments.
+{% /info %}
src/routes/docs/advanced/self-hosting/platforms/aws/+page.markdoc (2)

22-35: Tighten security group guidance and instance family note.

Restrict SSH, prefer HTTPS with HTTP→HTTPS redirect, and caution about burstable CPU.

 3. Configure security group to allow:
    - HTTP (80)
    - HTTPS (443)
    - SSH (22) from your IP
 4. Select your EC2 key pair
 5. Click **Launch**
 
+{% info title="Security & sizing tips" %}
+- Restrict SSH (22) to your IP and remove/disable it after initial setup.
+- Expose HTTPS (443) publicly; keep 80 only for redirect to 443.
+- t3.* are burstable; for sustained load consider M or C families (e.g., m6i, c7g) to avoid CPU credit throttling.
+{% /info %}

37-43: Add optional DNS/TLS step to complete setup.

Helps users finish with a proper domain and HTTPS.

 1. Wait for instance to launch and pass status checks
 2. Navigate to your instance's public IP address in a web browser
 3. Complete the initial Appwrite setup wizard
+4. (Optional) Point your domain (A/AAAA record) to the instance and enable HTTPS in Appwrite for automatic certificates
src/routes/docs/advanced/self-hosting/+page.markdoc (2)

13-13: Use sentence case in heading.

Consistency with the rest of the page.

-# Cloud vs Self-hosting {% #cloud-vs-self-hosting %}
+# Cloud vs self-hosting {% #cloud-vs-self-hosting %}

84-104: Optional: Add Kubernetes/GKE/AKS cards (if supported) or explicitly omit.

Many users look for K8s guidance. Either add cards or note K8s is not currently covered.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 87ad9ec and 3535012.

📒 Files selected for processing (11)
  • src/lib/utils/code.ts (2 hunks)
  • src/routes/docs/advanced/self-hosting/+layout.svelte (1 hunks)
  • src/routes/docs/advanced/self-hosting/+page.markdoc (2 hunks)
  • src/routes/docs/advanced/self-hosting/configuration/sites/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/configuration/version-control/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/platforms/aws/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/platforms/azure/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/platforms/google-cloud/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/production/backups/+page.markdoc (1 hunks)
  • src/routes/docs/advanced/self-hosting/production/updates/+page.markdoc (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/routes/docs/advanced/self-hosting/production/backups/+page.markdoc
  • src/routes/docs/advanced/self-hosting/configuration/sites/+page.markdoc
  • src/lib/utils/code.ts
  • src/routes/docs/advanced/self-hosting/configuration/version-control/+page.markdoc
  • src/routes/docs/advanced/self-hosting/platforms/digitalocean/+page.markdoc
  • src/routes/docs/advanced/self-hosting/production/updates/+page.markdoc
  • src/routes/docs/advanced/self-hosting/+layout.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: tests
  • GitHub Check: build
  • GitHub Check: format
🔇 Additional comments (1)
src/routes/docs/advanced/self-hosting/+page.markdoc (1)

1-174: Link integrity verified
All referenced internal pages exist; no broken links found.

Copy link
Contributor

@stnguyen90 stnguyen90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move forward with this, but address my additional comments in a follow-up PR.

Comment on lines 9 to 43
# Deployment options {% #deployment-options %}

Choose the deployment method that best fits your requirements:

{% table %}
* Service
* Best For
* Complexity
* Scaling
---
* **Cloud Run**
* Serverless, automatic scaling
* Low
* Automatic
---
* **Compute Engine**
* Custom configurations, full control
* Medium
* Manual
---
* **App Engine**
* Managed platform, simple deployment
* Low
* Automatic
{% /table %}

# Cloud Run deployment {% #cloud-run %}

Deploy Appwrite using Google Cloud Run for a serverless, fully managed experience with automatic scaling.

{% info title="Compatibility note" %}
Appwrite uses MariaDB by default. Running against Cloud SQL for MySQL 8.x is unsupported and may break schema or SQL dialect assumptions. Test thoroughly in a staging environment or deploy MariaDB yourself on Compute Engine instead.
{% /info %}

For detailed Cloud Run deployment instructions, follow the [general installation guide](/docs/advanced/self-hosting/installation) and adapt the Docker commands for your Cloud Run environment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about mentioning all of these that may not work.

Google Cloud Run is similar to a AWS Lambda. We should be focusing on Compute Engine as that's similar to AWS' EC2 and DO's droplets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Updated

Comment on lines 9 to 39
# Deployment options {% #deployment-options %}

Choose the Azure service that best fits your requirements:

{% table %}
* Service
* Best For
* Complexity
* Scaling
---
* **Container Apps**
* Serverless containers, microservices
* Low
* Automatic
---
* **Virtual Machines**
* Full control, custom configurations
* Medium
* Manual
---
* **App Service**
* Web apps, managed platform
* Low
* Automatic
{% /table %}

# Container Apps deployment {% #container-apps %}

Deploy Appwrite using Azure Container Apps for a serverless, fully managed container experience.

For detailed Container Apps deployment instructions, follow the [general installation guide](/docs/advanced/self-hosting/installation) and adapt the Docker commands for your Azure Container Apps environment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my comments for Google Cloud, we should focus on Azure's Virtual Machines as they're similar to AWS' EC2 and DO's droplets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated too

@ebenezerdon ebenezerdon merged commit ba1f651 into main Sep 8, 2025
3 of 5 checks passed
@ebenezerdon ebenezerdon deleted the doc-self-hosting-tutorials branch September 8, 2025 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants