Ctrl K

n8n EC2 arXiv Radar

Deploy private n8n on EC2 with Docker Compose and build a daily arXiv research digest workflow delivered by email.

Run n8n on an AWS EC2 instance as a private automation server. This setup keeps n8n bound to EC2 localhost, accesses the editor through an SSH tunnel, persists state on the server, and uses the first workflow to send a daily arXiv AI research digest by email.

Architecture

n8n runs in Docker Compose on EC2 and is not exposed publicly. The local browser reaches it through an SSH tunnel from local port 5679 to EC2 localhost port 5678.

Local browser
  |
  | SSH tunnel
  | localhost:5679 -> EC2 localhost:5678
  v
EC2 instance
  |
  | Docker Compose
  v
n8n container
  |
  | bind mount
  v
/home/ubuntu/n8n-lab/local/n8n_data
  • The EC2 security group should allow SSH from the operator IP only.
  • Do not open ports 5678, 80, or 443 for the initial private setup.
  • Use n8n for scheduling, API calls, lightweight transformation, AI calls, email delivery, and execution history.

Create the EC2 instance

SettingValue
AMIUbuntu Server LTS
Instance typet3.small
Storage20 GB gp3
Inbound security groupSSH TCP 22 from operator IP only
  • Keep the n8n editor private for the baseline setup.
  • Use a public domain, reverse proxy, TLS, and database hardening only if the private workflow later needs them.

Install Docker

Install Docker and the Compose plugin on the EC2 instance, then reconnect so the Docker group membership applies.

sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
sudo usermod -aG docker ubuntu

exit
docker --version
docker compose version

Create server files

Create the project directory and persistent n8n data folder on the EC2 instance.

mkdir -p ~/n8n-lab/local/n8n_data
cd ~/n8n-lab
/home/ubuntu/n8n-lab/
  docker-compose.yml
  .env
  local/
    n8n_data/
  • The runtime state lives in /home/ubuntu/n8n-lab/local/n8n_data.
  • That folder contains the n8n database, workflows, credential metadata, execution history, and local settings.
  • Do not commit local/n8n_data or .env to a public repository.

Create Docker Compose file

nano ~/n8n-lab/docker-compose.yml
services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n-lab
    restart: unless-stopped

    ports:
      - "127.0.0.1:${N8N_PORT:-5678}:5678"

    environment:
      - TZ=${TZ}
      - GENERIC_TIMEZONE=${TZ}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_HOST=localhost
      - N8N_PORT=5678
      - N8N_PROTOCOL=http

    volumes:
      - ./local/n8n_data:/home/node/.n8n

The port binding is intentionally local-only on the EC2 host.

127.0.0.1:5678:5678

Create environment file

openssl rand -hex 32
nano ~/n8n-lab/.env
TZ=Etc/UTC
N8N_PORT=5678
N8N_ENCRYPTION_KEY=replace-with-random-secret
  • Preserve N8N_ENCRYPTION_KEY. If it changes later, existing saved credentials may become unreadable.
  • Treat .env as a secret file.

Start n8n

cd ~/n8n-lab
docker compose up -d
docker compose ps
docker compose logs --tail=50 n8n

The logs should show that the editor is accessible at http://localhost:5678.

Open the editor

Open the SSH tunnel from the local machine and keep that SSH session running.

ssh -i /path/to/key.pem -L 5679:localhost:5678 ubuntu@EC2_PUBLIC_IP

Then open the local browser at:

http://localhost:5679

Reboot behavior

sudo systemctl is-enabled docker
  • Expected output is enabled.
  • Docker starts after EC2 reboot.
  • The n8n container restarts because Compose sets restart: unless-stopped.
  • No custom systemd service is required for this baseline setup.

If the stack is stopped with docker compose down, start it manually again.

cd ~/n8n-lab
docker compose up -d

Workflow shape

The first workflow sends a daily email digest of recent arXiv papers relevant to LLM agents, code agents, RAG, information retrieval, AI evaluation, software engineering with AI, and developer tools.

The MVP uses paper metadata and abstracts only. It does not download or summarize full PDFs.

Manual Trigger
Schedule Trigger
  |
  v
HTTP Request to arXiv
  |
  v
XML parser
  |
  v
Code node: normalize paper metadata
  |
  v
Code node: prepare AI prompt
  |
  v
AI model node
  |
  v
Code node: extract plain-text digest
  |
  v
Send Email node
  • Keep Manual Trigger for testing.
  • Use Schedule Trigger for daily automation.

Fetch arXiv papers

Use an HTTP Request node to fetch recent papers from selected arXiv categories.

https://export.arxiv.org/api/query?search_query=cat:cs.AI+OR+cat:cs.CL+OR+cat:cs.LG+OR+cat:cs.IR+OR+cat:cs.SE&sortBy=submittedDate&sortOrder=descending&max_results=5
CategoryUse
cs.AIArtificial intelligence
cs.CLComputational linguistics and language models
cs.LGMachine learning
cs.IRInformation retrieval
cs.SESoftware engineering
  • Potential future additions include stat.ML and selected q-fin categories.
  • Keep max_results small until the digest quality and email formatting are stable.

Normalize metadata

After parsing the arXiv XML response, normalize each paper into the compact fields the AI node needs.

FieldPurpose
arxiv_idStable paper identifier
titlePaper title
authorsAuthor list
abstractPrimary summary input
arxiv_urlAbstract page link
pdf_urlPDF link for manual follow-up
categoriesarXiv category labels
publishedSubmission date

Prepare AI digest

Send a compact list of normalized papers to the AI model. Ask it to select the top relevant papers for the target interests and return plain text for cleaner email rendering.

Daily arXiv Digest - YYYY-MM-DD

1. Paper title
Why relevant: one sentence
Summary: two sentences
Link: URL

2. Paper title
Why relevant: one sentence
Summary: two sentences
Link: URL

3. Paper title
Why relevant: one sentence
Summary: two sentences
Link: URL

Send email

Use the n8n Send Email node with SMTP credentials. For Gmail, use an app password instead of the normal account password.

Gmail SMTP settingValue
Hostsmtp.gmail.com
Port465
Secure/SSLtrue
User<gmail-address>
Password<16-character-app-password>
Email fieldValue
From<sender-email>
To<recipient-email>
SubjectDaily arXiv Radar
BodyAI-generated plain-text digest
  • Do not commit or share SMTP credentials.
  • Use the full Gmail address as the SMTP username.
  • Use the app password without spaces.

Create Gmail app password

Gmail SMTP requires 2-Step Verification and an app password.

https://myaccount.google.com/
https://myaccount.google.com/apppasswords
  • Open Google Account settings.
  • Go to Security.
  • Enable or confirm 2-Step Verification.
  • Open App passwords.
  • Create a new app password with a label such as n8n SMTP.
  • Use the displayed 16-character value in n8n SMTP credentials.
  • If the app password is exposed, delete it in Google Account settings and create a new one.

Operate n8n

TaskCommand
Startcd ~/n8n-lab && docker compose up -d
Stopcd ~/n8n-lab && docker compose down
Follow logscd ~/n8n-lab && docker compose logs -f n8n
Check containerdocker ps
Open tunnelssh -i /path/to/key.pem -L 5679:localhost:5678 ubuntu@EC2_PUBLIC_IP

The expected Docker port binding is 127.0.0.1:5678->5678/tcp.

Back up n8n

Back up the Compose file, env file, and persistent data directory. The encryption key is the most important value because saved n8n credentials may not be recoverable without it.

/home/ubuntu/n8n-lab/.env
/home/ubuntu/n8n-lab/docker-compose.yml
/home/ubuntu/n8n-lab/local/n8n_data/
cd ~
tar -czf n8n-lab-backup-$(date +%Y%m%d).tar.gz n8n-lab
scp -i /path/to/key.pem ubuntu@EC2_PUBLIC_IP:/home/ubuntu/n8n-lab-backup-YYYYMMDD.tar.gz .

Keep the MVP simple

  • Keep n8n private and use SSH tunneling for editor access.
  • Avoid a public domain, reverse proxy, TLS setup, PostgreSQL, full PDF parsing, deduplication database, and external workflow repository until the radar proves useful.
  • Later additions can include PostgreSQL, paper deduplication, sent digest history, manual feedback, saved paper archive, Notion or Markdown export, Telegram delivery, and full-PDF processing for selected papers.