Sequin on AWS User Guide
Overview
This image runs Sequin, the open source change data capture platform for PostgreSQL. Sequin reads a database's write ahead log through a logical replication slot and turns every insert, update and delete into an ordered stream of change events, which it delivers to the destination of your choice.
Because Sequin reads the replication log rather than polling tables, it captures every change without adding query load to the source database, and without requiring any application code to publish events. Change events can be delivered to Kafka, Amazon SQS, Amazon SNS, Amazon Kinesis, NATS, RabbitMQ, Redis Streams, GCP Pub/Sub, Azure Event Hubs, Elasticsearch, Typesense, Meilisearch, HTTP webhooks, and a pull based API.
The image runs three pinned upstream containers on a private container network: the Sequin server itself, which is an Elixir application built on the Phoenix framework and which serves the web console; a PostgreSQL instance that holds both Sequin's own metadata and the bundled demonstration source database; and a Redis instance that provides Sequin's internal queue and also acts as the demonstration sink destination. Neither datastore is published to a host port. The Sequin console binds to 127.0.0.1:7376 and is reached only through an nginx front door that terminates TLS on port 443.
Rather than handing you an empty console, this image ships a complete working pipeline. A demonstration source database is created on first boot with a captured table, a publication and a pre created logical replication slot, and a sink streams every insert, update and delete from that table into a Redis stream. You can write a row and read the captured change event back within seconds, then follow the same pattern to point Sequin at your own database.
Every secret is generated on the first boot of each deployed instance, so two instances launched from the same Amazon Machine Image never share a credential. Upstream Sequin provisions a well known default administrator and allows open self registration; both are disabled in this image.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network and port 443 for the Sequin web console
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Sequin. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that opens port 22 from your management network and port 443 for the web console. Leave the root volume at the default size or larger; the image also attaches a dedicated data volume described in Step 8.
Select Launch instance. First boot initialisation takes a few minutes after the instance state becomes Running and the status checks pass, while the image generates its secrets, creates the demonstration source database and starts the change data capture pipeline.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Sequin Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22 and 443 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=sequin}]'
When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name from the EC2 console or with aws ec2 describe-instances.
Step 3: Connect to Your Instance
Connect over SSH using your key pair and the login user for your operating system variant.
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i /path/to/your-key.pem ubuntu@<public-ip>
Step 4: Confirm the Stack Is Running
Four services make up the appliance. Docker runs the three pinned containers, a first boot service generates the per instance secrets, the Sequin service brings the containers up, and nginx terminates TLS in front of the console.
systemctl is-active docker.service sequin.service nginx.service
Each line should read active. The unauthenticated health endpoint confirms the Sequin server itself is answering through the nginx front door. It is deliberately open so that a load balancer can probe it without a credential.
curl -sk -o /dev/null -w 'health endpoint: HTTP %{http_code}\n' -m 20 https://127.0.0.1/health
Confirm the listening ports. The console is published on 443, port 80 redirects to it, and the Sequin application port 7376 is bound to the loopback interface only, so it is not reachable from outside the instance.
ss -tln | grep -E ':(80|443|7376) ' | sort
The bundled PostgreSQL and Redis are on the private container network and are deliberately not published to any host port, which you can confirm by their absence from that list.
Step 5: Retrieve Your Per Instance Credentials
Every credential is generated on the first boot of your instance and written to a root only file. Read it with:
sudo cat /root/sequin-credentials.txt
The file contains the console URL, an HTTP Basic credential that gates the console at the nginx layer, the Sequin administrator login, a management API token, and the passwords for the bundled datastores. You can confirm which keys are present without revealing any values:
sudo awk -F= '/^[A-Z_]+=/ {print $1}' /root/sequin-credentials.txt | sort
The console is protected by two independent credentials: the HTTP Basic credential enforced by nginx, and then Sequin's own login. Both are unique to your instance.
Step 6: Sign In to the Web Console
Browse to https://<public-ip>/. The image generates a self signed TLS certificate on first boot carrying your instance's own address, so your browser will warn once about the certificate; accept it to continue, or install your own certificate as described in Step 10.
Your browser first prompts for the HTTP Basic credential. Supply CONSOLE_USER and CONSOLE_PASSWORD from the credentials file. You are then presented with the Sequin sign in page, where you use ADMIN_EMAIL and ADMIN_PASSWORD from the same file.

After signing in you land on the Sinks view. The bundled demonstration pipeline, demo-redis-stream, is already running and reporting healthy against the demo-source database.

Step 7: Watch Real Change Events Being Captured
Select the demo-redis-stream sink to open its overview. Sequin runs six health checks covering the replication slot, the source connection and the sink destination, and reports how many messages it has processed, how many are pending and how many are failing.

The Messages tab lists the individual change events Sequin has captured and delivered, with the source table, the primary key of the changed row, the delivery count and the commit time.

The Databases view shows the connected PostgreSQL source, its health, and how many sink consumers are reading from it.

You can prove the whole path end to end from the shell. The image ships a verifier that writes a uniquely marked row into the demonstration source table, waits for that exact change to arrive at the sink, repeats the exercise for an update, and then writes to a table that is deliberately excluded from the publication to confirm it is not forwarded. It exercises the per instance credentials without ever printing them.
sudo /usr/local/sbin/sequin-roundtrip.sh
The negative control matters: it demonstrates that the pipeline filters on the PostgreSQL publication rather than forwarding every write in the database.
You can also inspect the replication slot directly. An active state of t means Sequin currently holds a walsender streaming changes from the source.
sudo docker compose --env-file /etc/sequin/sequin.env -f /etc/sequin/compose.yaml exec -T sequin_postgres psql -qtAX -U sequin -d sequin_demo -c "select slot_name, plugin, active from pg_replication_slots;"
Step 8: The Dedicated Data Volume
Docker's data root at /var/lib/docker is a separate EBS volume, mounted by filesystem identifier so that it survives reboots and reattachment reliably. Every container image layer, the PostgreSQL data directory and write ahead log, the replication slot state and the Redis append only file live on it.
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/docker
Because capture state is on its own disk, you can grow it independently of the root volume: modify the EBS volume in the EC2 console, then extend the filesystem on the instance with resize2fs. The fstab entry uses the filesystem UUID, so no change is needed after resizing.
Step 9: Connect Sequin to Your Own Database
The demonstration pipeline shows the shape of a working setup; the next step is to point Sequin at your own PostgreSQL database. Your source database must have wal_level set to logical, and Sequin needs a role with the REPLICATION attribute.
On your source database, create a publication covering the tables you want captured, and a logical replication slot for Sequin to read from:
CREATE PUBLICATION my_publication FOR TABLE public.orders, public.customers;
SELECT pg_create_logical_replication_slot('my_slot', 'pgoutput');
Setting REPLICA IDENTITY FULL on a captured table makes update and delete events carry the complete previous row, which downstream consumers usually want:
ALTER TABLE public.orders REPLICA IDENTITY FULL;
In the console, choose Databases, then Connect Database, and supply the host, port, database name, and the credentials for your replication role, along with the slot and publication names you created. Once the database reports healthy, choose Sinks, then Create Sink, pick your destination type, select the tables and the actions (insert, update, delete) you want forwarded, and supply the destination's connection details.
If your source database is Amazon RDS or Aurora PostgreSQL, set the rds.logical_replication parameter to 1 in the parameter group and reboot the instance before creating the slot. Make sure the instance's security group allows Sequin to reach the database port.
Sequin can also be configured declaratively in YAML and applied with its CLI, which is the approach this image uses internally to provision the demonstration pipeline. The upstream configuration reference documents the full schema.
Step 10: Use Your Own TLS Certificate
The image generates a self signed certificate on first boot so that the console is never served in plain text. For production use, replace it with a certificate issued for a hostname you control. Place the certificate and private key on the instance, point /etc/nginx/sites-available/sequin at them by editing the ssl_certificate and ssl_certificate_key directives, validate the configuration with sudo nginx -t, and reload nginx.
If you terminate TLS at an Application Load Balancer instead, forward to port 443 on the instance and keep the security group restricted to the load balancer.
Step 11: The Management API
Sequin exposes a management API authenticated by the bearer token stored as API_TOKEN in your credentials file. It is exempt from the nginx HTTP Basic layer, because HTTP Basic and bearer authentication both use the Authorization header and cannot coexist on one path; Sequin authenticates it itself and rejects an absent or incorrect token.
curl -k -H "Authorization: Bearer <your-api-token>" https://<public-ip>/api/sinks
The round trip verifier in Step 7 already proves this path works on your instance, including that a wrong token is rejected.
Step 12: Backup and Maintenance
The state that matters is Sequin's own metadata database, which holds your database connections, sinks and pipeline definitions. It lives in a Docker named volume on the dedicated data disk. The most straightforward backup is an EBS snapshot of that data volume, which you can schedule with Amazon Data Lifecycle Manager. For a logical backup, run pg_dump against the sequin database inside the PostgreSQL container.
Note that a logical replication slot retains write ahead log segments on the source database until the consumer reads them. If Sequin is stopped for a long period while its slot still exists, WAL will accumulate on your source database. Monitor replication lag on your source, and drop slots you no longer need.
To review recent service activity:
sudo journalctl -u sequin.service --no-pager --since '30 min ago' | tail -n 20
Operating system updates are applied with apt. After a reboot the stack restarts automatically: the containers are configured to restart, and the systemd units are enabled.
Troubleshooting
The browser warns about the certificate. Expected on first use: the certificate is self signed and generated for your instance's address on first boot. Accept it, or install your own certificate as in Step 10.
The console asks for a password twice. By design. The first prompt is the nginx HTTP Basic credential (CONSOLE_USER and CONSOLE_PASSWORD), the second is Sequin's own sign in page (ADMIN_EMAIL and ADMIN_PASSWORD). Both are in the credentials file.
A sink shows as unhealthy. Open the sink and read its health checks; they identify which component is failing. The most common causes are that the destination is unreachable from the instance, that the destination credentials are wrong, or that the replication slot on the source has been dropped.
Change events are not arriving. Confirm that the source table is included in the publication, and that the replication slot shows active as t in the query in Step 7. A slot that exists but is never active usually means Sequin cannot authenticate to the source database, or the source role lacks the REPLICATION attribute.
First boot appears to take a long time. The first boot runs database migrations against a brand new database and starts three containers. Allow a few minutes after the status checks pass before the console answers.
Support
This image is published by cloudimg with 24/7 technical support by email and chat, covering deployment, connecting Sequin to your own PostgreSQL database, configuring sinks and destinations, replication slot and publication management, TLS termination and upgrades.
Sequin is open source software licensed under the MIT License. cloudimg is not affiliated with or endorsed by Sequin Labs, Inc. The Sequin name is used nominatively to identify the software shipped in this image. All product and company names are trademarks or registered trademarks of their respective holders.