API Self-Hosted v3 – AWS EKS Deployment Guide (S3 Storage)
Complete guide for deploying Draftable API Self-Hosted v3 on AWS Elastic Kubernetes Service (EKS) with S3 storage backend.
This guide provides step-by-step instructions for deploying Draftable API Self-Hosted v3 on AWS EKS with S3 storage.
AWS Only: Kubernetes deployment of Draftable API Self-Hosted v3 is currently supported on AWS EKS only. Azure AKS is not officially supported — while it is technically possible to use an NFS shared volume (e.g. Azure NetApp Files) with FILE_STORAGE_TYPE=local, Draftable does not test or optimise against NFS and cannot provide support for NFS-related issues. See FILE_STORAGE_TYPE for details.
S3 Storage Only: This guide covers S3-based deployments. EFS storage configurations are not covered in this documentation and are not recommended for Draftable deployments.
Critical Data Loss Risk: The stateful components (PostgreSQL, Redis, RabbitMQ) included in this guide use Kubernetes PersistentVolumeClaims for storage. However, if pods are restarted, rescheduled, or the cluster is rebuilt, you may lose all your data including the database, cached sessions, and queued messages.For production deployments, you must use managed AWS services for stateful components.
Component
Kubernetes (Dev/Test Only)
Production Requirement
PostgreSQL
10-postgresql.yaml
Amazon RDS for PostgreSQL
Redis
12-redis.yaml
Amazon ElastiCache for Redis
RabbitMQ
11-rabbitmq.yaml
Amazon MQ for RabbitMQ
Why managed services?
Kubernetes frequently tears down and recreates containers—excellent for stateless services but dangerous for stateful workloads
Pod restarts, node failures, or cluster updates can result in permanent data loss
Managed services provide automated backups, high availability, and data persistence guarantees
Redis persistence is especially critical. Redis stores the activated license and custom fonts. If Redis data is lost, all users will be locked out until the license is reactivated by re-running the web-init job. Always use persistent storage for Redis — or preferably, a managed Redis service with persistence enabled.
Critical: The Compare service does NOT support IRSA (IAM Roles for Service Accounts). It requires explicit AWS credentials.
Component
Service Account
S3 Authentication Method
Web
draftable-s3-sa
IRSA (IAM Roles for Service Accounts)
Celery Worker
draftable-s3-sa
IRSA
Celery Beat
draftable-s3-sa
IRSA
Compare
default
Explicit AWS credentials (required!)
The Compare service (.NET application) is missing the AWSSDK.SecurityToken assembly required for AssumeRoleWithWebIdentity. Attempting to use IRSA will result in:
Assembly AWSSDK.SecurityToken could not be found or loaded.This assembly must be available at runtime to use Amazon.Runtime.AssumeRoleAWSCredentials.
Recommendation: Instead of creating a dedicated IAM user for EKS access, grant access to your existing administrator role (e.g., SSO Administrator). This allows you to use your regular admin credentials with kubectl and view resources in the AWS Console.
All Kubernetes manifests are available in our GitHub repository:
Kubernetes Manifests for EKS + S3
Complete set of deployment manifests
Templated Files: All YAML manifests are deliberately templated and incomplete. You must replace placeholder values (marked with YOUR_* or REPLACE_*) with your own configuration before applying them to your cluster.
Critical S3 Configuration: The FILE_STORAGE_TYPE must be set to s3. Without this, the application uses local filesystem storage regardless of other S3 settings.
Converter Health Probes: The 25-converter.yaml manifest must use TCP socket probes (not HTTP). The JODConverter API returns 404 on all health endpoints, and LibreOffice takes 60-90 seconds to start. Using HTTP probes will cause the pod to enter CrashLoopBackOff with hundreds of restarts. See Troubleshooting for details.
kubectl apply -f 21-web.yamlkubectl apply -f 22-celery-worker.yamlkubectl apply -f 23-celery-beat.yamlkubectl apply -f 24-compare.yamlkubectl apply -f 25-converter.yaml# Wait for web podskubectl wait --for=condition=ready pod -l app=web -n draftable --timeout=300s
Converter startup time: The converter pod may take 90-120 seconds to become ready. During startup, you may see “Office process died with exit code 81” in the logs—this is normal while LibreOffice initializes.
Verify aws-s3-credentials secret exists with AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
kubectl get deployment compare -n draftable -o jsonpath='{.spec.template.spec.serviceAccountName}'# Should output: defaultkubectl get secret aws-s3-credentials -n draftable# Should exist
Cause: ALB health checks use the pod’s internal IP address, not the domain name.Solution: Ensure ALLOWED_HOSTS: "*" is set in the ConfigMap (already configured in the provided manifests).
REDIS_PORT Parse Error (invalid literal for int())
Cause: Kubernetes auto-creates REDIS_PORT=tcp://ip:port when a service is named redis.Solution: The Redis service is named redis-svc in our manifests to avoid this conflict. Ensure you’re using the provided manifests.
Do NOT use httpGet probes for the converter. The JODConverter REST API returns 404 on /, /health, and /actuator/health endpoints, causing probe failures and endless restart loops.
Why TCP probes work: TCP probes simply verify port 8080 is listening, which it is once Tomcat starts—even while LibreOffice is still initializing.Note: During normal startup, you will see “Office process died with exit code 81” messages in the logs. This is expected behavior while LibreOffice initializes.
Amazon MQ must use the RabbitMQ engine. Amazon MQ for ActiveMQ is not compatible with Draftable (it uses AMQP 1.0; Draftable requires AMQP 0-9-1), and AWS SQS is not supported. See supported message brokers. If your RabbitMQ or Redis uses a private or internal CA, see Using a private or internal CA.