Deploy Go App to AWS EC2 with Systemd

Complete guide to deploy and run your Go application as a systemd service

This guide walks you through deploying your Go application to an AWS EC2 instance and running it as a systemd service. Systemd ensures your application starts automatically on boot, restarts on crashes, and can be easily managed.

Prerequisites

  • AWS account with EC2 access
  • Go application ready to deploy
  • SSH access to EC2 instance
  • Basic knowledge of Linux commands
1

Launch EC2 Instance

Launch an EC2 instance using Amazon Linux 2 or Ubuntu Server. For this guide, we'll use Ubuntu.

AWS Console Steps:

  1. Go to EC2 Dashboard → Launch Instance
  2. Choose Ubuntu Server 22.04 LTS (or latest)
  3. Select instance type (t2.micro for free tier, t3.small for production)
  4. Configure security group: Open port 22 (SSH) and your app port (e.g., 8080)
  5. Launch instance and download the key pair (.pem file)

Connect to your instance:

# Set correct permissions for key file
chmod 400 your-key.pem

# SSH into the instance
ssh -i your-key.pem ubuntu@YOUR_EC2_IP_ADDRESS
2

Install Go on EC2

Install Go on your EC2 instance:

# Update package list
sudo apt update

# Install Go (Ubuntu/Debian)
sudo apt install golang-go -y

# Verify installation
go version

# Set GOPATH and GOROOT (add to ~/.bashrc or ~/.profile)
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

Note: For latest Go version, download from golang.org/dl and extract to /usr/local.

3

Transfer Your Go Application

Copy your Go application to the EC2 instance. Option 1: Using SCP (from your local machine):

# From your local machine, compress and transfer
tar -czf app.tar.gz your-go-project/
scp -i your-key.pem app.tar.gz ubuntu@YOUR_EC2_IP:/home/ubuntu/

# SSH into EC2 and extract
ssh -i your-key.pem ubuntu@YOUR_EC2_IP
cd /home/ubuntu
tar -xzf app.tar.gz
cd your-go-project

Option 2: Clone from Git (if your code is in a repository):

# On EC2 instance
cd /home/ubuntu
git clone https://github.com/yourusername/your-go-project.git
cd your-go-project
4

Build the Go Application

Build your Go application on the EC2 instance:

# Navigate to your project
cd /home/ubuntu/your-go-project

# Download dependencies
go mod download

# Build the application
go build -o myapp cmd/server/main.go

# Or build for production (optimized)
go build -ldflags="-s -w" -o myapp cmd/server/main.go

# Test if it runs
./myapp

Create a directory for your application:

# Create app directory
sudo mkdir -p /opt/myapp
sudo chown ubuntu:ubuntu /opt/myapp

# Copy binary and config files
cp myapp /opt/myapp/
cp -r configs /opt/myapp/  # if you have config files

# Make it executable
sudo chmod +x /opt/myapp/myapp
5

Create Systemd Service File

Create a systemd service file to manage your application:

# Create service file
sudo nano /etc/systemd/system/myapp.service

Add the following content (adjust paths and user as needed):

[Unit]
Description=My Go Application
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

# Environment variables (optional)
Environment="PORT=8080"
Environment="ENV=production"

# Security settings
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Key settings explained:

  • Restart=always - Automatically restart on crash
  • RestartSec=5 - Wait 5 seconds before restarting
  • StandardOutput=journal - Logs go to systemd journal
  • User=ubuntu - Run as ubuntu user (use non-root user)
6

Enable and Start the Service

Reload systemd, enable, and start your service:

# Reload systemd daemon
sudo systemctl daemon-reload

# Enable service to start on boot
sudo systemctl enable myapp

# Start the service
sudo systemctl start myapp

# Check service status
sudo systemctl status myapp

# View logs
sudo journalctl -u myapp -f

The service should now be running. Test it by accessing http://YOUR_EC2_IP:8080.

7

Common Systemd Commands

Service Management

# Start service
sudo systemctl start myapp

# Stop service
sudo systemctl stop myapp

# Restart service
sudo systemctl restart myapp

# Reload service (if supported)
sudo systemctl reload myapp

# Check status
sudo systemctl status myapp

Logs and Debugging

# View recent logs
sudo journalctl -u myapp

# Follow logs (like tail -f)
sudo journalctl -u myapp -f

# View last 100 lines
sudo journalctl -u myapp -n 100

# View logs since today
sudo journalctl -u myapp --since today
8

Security Best Practices

  • Run as non-root user: Always set User=ubuntu in the service file. Never run your app as root.
  • Firewall configuration: Only open necessary ports in EC2 security group. Use AWS Security Groups to restrict access.
  • Use environment variables: Store sensitive data (API keys, DB passwords) in environment variables, not in code.
  • Enable HTTPS: Use a reverse proxy like Nginx with Let's Encrypt certificates for HTTPS.
  • Regular updates: Keep your EC2 instance and Go application updated with security patches.

Optional: Nginx Reverse Proxy

Set up Nginx as a reverse proxy to serve your app on port 80/443 and handle SSL:

# Install Nginx
sudo apt install nginx -y

# Create Nginx config
sudo nano /etc/nginx/sites-available/myapp

# Add this configuration:
server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# Enable site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t  # Test configuration
sudo systemctl restart nginx

Troubleshooting

Service fails to start:

  • Check logs: sudo journalctl -u myapp -n 50
  • Verify binary path and permissions
  • Check if port is already in use: sudo netstat -tulpn | grep 8080

Can't access from outside:

  • Check EC2 Security Group - ensure port is open
  • Verify app is listening on 0.0.0.0, not just localhost
  • Check Ubuntu firewall: sudo ufw status

Permission denied errors:

  • Ensure user in service file has read/execute permissions
  • Check file ownership: ls -la /opt/myapp/

Quick Reference

Service File Location:

/etc/systemd/system/myapp.service

Application Directory:

/opt/myapp/

View Logs:

sudo journalctl -u myapp -f

Restart Service:

sudo systemctl restart myapp