Skip to content

Deploying an Akkoma App

Introduction

Akkoma is a lightweight, federated social networking server that implements the ActivityPub protocol, allowing users to connect and communicate across different instances in the Fediverse. Built with Elixir and the Phoenix framework, Akkoma is a fork of Pleroma that focuses on simplicity, performance, and user privacy.

Akkoma is renowned for its:

  • Federation Support: Full ActivityPub protocol implementation for interoperability with Mastodon, Pleroma, and other Fediverse platforms
  • Lightweight: Efficient resource usage compared to other federated social networking servers
  • Privacy-Focused: Strong emphasis on user privacy and data protection
  • Customizable: Extensive theming and configuration options
  • Rich Media Support: Support for images, videos, and other media types
  • Real-Time Updates: WebSocket support for real-time notifications and updates
  • Moderation Tools: Comprehensive moderation and administration features
  • Multi-User Support: Support for multiple users and communities on a single instance
  • API Access: RESTful API for third-party applications and bots
  • Open Source: Fully open-source with active community development

Common use cases include personal social networking instances, community platforms, alternative social media hosting, privacy-focused social networks, and federated communication hubs.

This comprehensive guide walks you through deploying Akkoma on Klutch.sh using a Dockerfile, including detailed installation steps, PostgreSQL database configuration, persistent storage setup, and production-ready best practices for hosting a federated social networking instance.

Prerequisites

Before you begin, ensure you have the following:

  • A Klutch.sh account
  • A GitHub account with a repository for your Akkoma project
  • A PostgreSQL database (can be deployed separately on Klutch.sh or use an external database)
  • Docker installed locally for testing (optional but recommended)
  • Basic understanding of Elixir, Phoenix, and federated social networking concepts
  • A domain name for your instance (recommended for production and federation)

Installation and Setup

Step 1: Create Your Project Directory

First, create a new directory for your Akkoma deployment project:

Terminal window
mkdir akkoma-klutch
cd akkoma-klutch
git init

Step 2: Clone or Prepare Akkoma Source

You can either clone the official Akkoma repository or prepare your own Akkoma-based application:

Terminal window
# Option 1: Clone the official Akkoma repository
git clone https://akkoma.dev/AkkomaGang/akkoma.git -b stable
cd akkoma
# Option 2: If you have your own Akkoma fork or custom instance
# Copy your Akkoma source code to the project directory

Step 3: Create the Dockerfile

Create a Dockerfile in your project root directory. This will define your Akkoma container configuration:

FROM elixir:1.15-alpine AS builder
# Install build dependencies
RUN apk add --no-cache \
build-base \
git \
postgresql-dev \
imagemagick \
ffmpeg \
exiftool \
file-dev \
ncurses-dev
# Set working directory
WORKDIR /app
# Install hex and rebar
RUN mix local.hex --force && \
mix local.rebar --force
# Copy mix files
COPY mix.exs mix.lock* ./
COPY config config
# Install dependencies
RUN mix deps.get --only prod && \
mix deps.compile
# Copy application code
COPY . .
# Build the application
RUN mix compile && \
mix assets.deploy && \
mix phx.digest
# Production stage
FROM elixir:1.15-alpine
# Install runtime dependencies
RUN apk add --no-cache \
postgresql-client \
imagemagick \
ffmpeg \
exiftool \
file \
ncurses \
bash \
curl
# Create akkoma user
RUN addgroup -g 1000 -S akkoma && \
adduser -u 1000 -S akkoma -G akkoma
# Set working directory
WORKDIR /app
# Copy built application from builder
COPY --from=builder --chown=akkoma:akkoma /app/_build/prod/rel/akkoma ./rel
COPY --from=builder --chown=akkoma:akkoma /app/config ./config
COPY --from=builder --chown=akkoma:akkoma /app/lib ./lib
# Create directories for persistent data
RUN mkdir -p /var/lib/akkoma/uploads \
/var/lib/akkoma/static \
/var/lib/akkoma/config && \
chown -R akkoma:akkoma /var/lib/akkoma
# Switch to akkoma user
USER akkoma
# Expose port
EXPOSE 4000
# Set environment variables
ENV MIX_ENV=prod
ENV PHX_SERVER=true
ENV PORT=4000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:4000/api/v1/instance || exit 1
# Start the application
CMD ["./rel/bin/akkoma", "start"]

Note: This Dockerfile uses a multi-stage build to create an optimized production image. Akkoma runs on port 4000 by default, which will be your internal port in Klutch.sh. The application requires ImageMagick, FFmpeg, and ExifTool for media processing.

Step 4: Create Configuration Files

Create a production configuration file. Here’s a basic example:

config/prod.secret.exs.example:

config/prod.secret.exs.example
# Copy this to config/prod.secret.exs and fill in your values
# DO NOT commit prod.secret.exs to version control
import Config
# Database configuration
config :akkoma, Pleroma.Repo,
hostname: System.get_env("DB_HOST", "localhost"),
port: String.to_integer(System.get_env("DB_PORT", "5432")),
database: System.get_env("DB_NAME", "akkoma"),
username: System.get_env("DB_USER", "akkoma"),
password: System.get_env("DB_PASSWORD", ""),
pool_size: 10
# Instance configuration
config :akkoma, :instance,
name: System.get_env("AKKOMA_INSTANCE_NAME", "Akkoma"),
email: System.get_env("AKKOMA_EMAIL", "admin@example.com"),
description: System.get_env("AKKOMA_DESCRIPTION", "Akkoma instance"),
registrations_open: System.get_env("AKKOMA_REGISTRATIONS_OPEN", "false") == "true",
federating: System.get_env("AKKOMA_FEDERATING", "true") == "true"
# Web endpoint configuration
config :akkoma, Pleroma.Web.Endpoint,
url: [
host: System.get_env("AKKOMA_HOST", "example-app.klutch.sh"),
scheme: "https",
port: 443
],
http: [
ip: {0, 0, 0, 0},
port: String.to_integer(System.get_env("PORT", "4000"))
],
secret_key_base: System.get_env("SECRET_KEY_BASE"),
signing_salt: System.get_env("SIGNING_SALT")
# Media uploads
config :akkoma, Pleroma.Upload,
uploads: "/var/lib/akkoma/uploads"
# Static files
config :akkoma, Pleroma.Web.Endpoint,
static_url: [
host: System.get_env("AKKOMA_HOST", "example-app.klutch.sh"),
scheme: "https",
port: 443
]
# Email configuration (optional)
config :akkoma, Pleroma.Emails.Mailer,
adapter: Swoosh.Adapters.SMTP,
relay: System.get_env("SMTP_RELAY"),
username: System.get_env("SMTP_USERNAME"),
password: System.get_env("SMTP_PASSWORD"),
port: String.to_integer(System.get_env("SMTP_PORT", "587")),
ssl: System.get_env("SMTP_SSL", "true") == "true",
tls: :always,
auth: :always

Step 5: Create Environment Configuration Template

Create a .env.example file with required environment variables:

# Database Configuration
DB_HOST=your-postgresql-host
DB_PORT=5432
DB_NAME=akkoma
DB_USER=akkoma
DB_PASSWORD=your-secure-password
# Application Configuration
AKKOMA_INSTANCE_NAME=My Akkoma Instance
AKKOMA_EMAIL=admin@example.com
AKKOMA_DESCRIPTION=A federated social networking server
AKKOMA_HOST=example-app.klutch.sh
AKKOMA_REGISTRATIONS_OPEN=false
AKKOMA_FEDERATING=true
# Security
SECRET_KEY_BASE=your-secret-key-base-here
SIGNING_SALT=your-signing-salt-here
# Server Configuration
PORT=4000
MIX_ENV=prod
PHX_SERVER=true
# Email Configuration (Optional)
SMTP_RELAY=smtp.example.com
SMTP_USERNAME=your-smtp-username
SMTP_PASSWORD=your-smtp-password
SMTP_PORT=587
SMTP_SSL=true
# Timezone
TZ=UTC

Step 6: Create Database Initialization Script

Create a script to initialize the database schema:

scripts/init_db.sh:

#!/bin/bash
set -e
echo "Initializing Akkoma database..."
# Wait for PostgreSQL to be ready
until PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c '\q'; do
>&2 echo "PostgreSQL is unavailable - sleeping"
sleep 1
done
echo "PostgreSQL is ready"
# Create database if it doesn't exist
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres <<-EOSQL
SELECT 'CREATE DATABASE $DB_NAME'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec
EOSQL
# Run migrations
echo "Running database migrations..."
./rel/bin/akkoma eval "Akkoma.Release.migrate"
echo "Database initialization complete"

Step 7: Create .dockerignore File

Create a .dockerignore file to exclude unnecessary files from the Docker build:

.git
.gitignore
.dockerignore
.env
.env.local
*.md
docker-compose.yml
docker-compose.*.yml
Dockerfile
node_modules
_build
deps
priv/static

Step 8: Test Locally (Optional)

Before deploying to Klutch.sh, you can test your Akkoma setup locally:

Terminal window
# Build the Docker image
docker build -t my-akkoma .
# Run the container (assuming you have a PostgreSQL database running)
docker run -d \
--name akkoma-test \
-p 4000:4000 \
-e DB_HOST=host.docker.internal \
-e DB_PORT=5432 \
-e DB_NAME=akkoma \
-e DB_USER=akkoma \
-e DB_PASSWORD=password \
-e SECRET_KEY_BASE=$(openssl rand -base64 64) \
-e SIGNING_SALT=$(openssl rand -base64 32) \
-e AKKOMA_HOST=localhost \
-v $(pwd)/uploads:/var/lib/akkoma/uploads \
my-akkoma
# Check if the application is running
curl http://localhost:4000/api/v1/instance

Note: For local development with a database, you can use Docker Compose to run both Akkoma and PostgreSQL together. Docker Compose is only for local development; Klutch.sh does not support Docker Compose for deployment.

Step 9: Push to GitHub

Commit your Akkoma project files to your GitHub repository:

Terminal window
git add .
git commit -m "Initial Akkoma Docker setup for Klutch.sh"
git branch -M main
git remote add origin https://github.com/yourusername/akkoma-klutch.git
git push -u origin main

Deploying to Klutch.sh

Now that your Akkoma project is ready and pushed to GitHub, follow these steps to deploy it on Klutch.sh with persistent storage.

Deployment Steps

    1. Log in to Klutch.sh

      Navigate to klutch.sh/app and sign in to your account.

    2. Create a New Project

      Go to Create Project and give your project a meaningful name (e.g., “Akkoma Social Network”).

    3. Create a New App

      Navigate to Create App and configure the following settings:

    4. Select Your Repository

      • Choose GitHub as your Git source
      • Select the repository containing your Dockerfile
      • Choose the branch you want to deploy (usually main or master)

      Klutch.sh will automatically detect the Dockerfile in your repository root and use it for deployment.

    5. Configure Traffic Type

      • Traffic Type: Select HTTP (Akkoma is a web application)
      • Internal Port: Set to 4000 (the port your Akkoma container listens on, as defined in your Dockerfile)
    6. Set Environment Variables

      Add the following environment variables for your Akkoma configuration:

      Database Configuration:

      • DB_HOST: Your database host (if using a Klutch.sh PostgreSQL app, use the app URL like example-db.klutch.sh)
      • DB_PORT: Database port (for Klutch.sh TCP apps, use 8000 externally, but the internal port in your database app should be 5432 for PostgreSQL)
      • DB_NAME: Your database name (e.g., akkoma)
      • DB_USER: Database username
      • DB_PASSWORD: Database password

      Application Configuration:

      • AKKOMA_INSTANCE_NAME: Your instance name (e.g., My Akkoma Instance)
      • AKKOMA_EMAIL: Admin email address
      • AKKOMA_DESCRIPTION: Instance description
      • AKKOMA_HOST: Your Klutch.sh app URL (e.g., example-app.klutch.sh)
      • AKKOMA_REGISTRATIONS_OPEN: Set to true or false to control user registrations
      • AKKOMA_FEDERATING: Set to true to enable federation with other instances

      Security:

      • SECRET_KEY_BASE: Generate using openssl rand -base64 64 (a long random string)
      • SIGNING_SALT: Generate using openssl rand -base64 32 (a random string)

      Server Configuration:

      • PORT: Set to 4000 (matches the internal port)
      • MIX_ENV: Set to production
      • PHX_SERVER: Set to true

      Optional - Email Configuration:

      • SMTP_RELAY: Your SMTP server hostname
      • SMTP_USERNAME: SMTP username
      • SMTP_PASSWORD: SMTP password
      • SMTP_PORT: SMTP port (typically 587 or 465)
      • SMTP_SSL: Set to true or false

      Timezone:

      • TZ: Your timezone (e.g., UTC or America/New_York)
    7. Attach Persistent Volumes

      Akkoma requires persistent storage for several directories to ensure data persists across deployments:

      Uploads Volume:

      • Mount Path: /var/lib/akkoma/uploads
      • Size: Start with 20GB minimum (50GB+ recommended for production with media uploads)

      This volume stores:

      • User-uploaded images and media files
      • Avatar images
      • Background images
      • Other user-generated content

      Static Files Volume (Optional):

      • Mount Path: /var/lib/akkoma/static
      • Size: 5GB (for static assets and compiled frontend files)

      Config Volume (Optional):

      • Mount Path: /var/lib/akkoma/config
      • Size: 1GB (for configuration files and secrets)

      Note: For production instances with active users, allocate sufficient storage for media uploads. You can increase volume sizes later if needed.

    8. Configure Additional Settings

      • Region: Select the region closest to your users for optimal performance
      • Compute Resources: Akkoma can be resource-intensive; allocate at least:
        • CPU: 2+ cores recommended
        • Memory: 2GB minimum (4GB+ recommended for production workloads)
      • Instances: Start with 1 instance (you can scale horizontally later if needed)
    9. Deploy Your Application

      Click “Create” to start the deployment. Klutch.sh will:

      • Automatically detect your Dockerfile in the repository root
      • Build the Docker image
      • Attach the persistent volume(s)
      • Start your Akkoma container
      • Assign a URL for external access

      Note: The first deployment may take several minutes as it builds the Docker image, compiles the Elixir application, and installs dependencies.

    10. Initialize Database

      After deployment, you’ll need to initialize your Akkoma database. Connect to your PostgreSQL database and run the database migrations. You can do this by executing commands in your container or using a database migration tool.

    11. Create Admin User

      Once the database is initialized, create your first admin user. You can do this through the web interface after accessing your instance, or by using the Akkoma CLI commands if available in your deployment.

    12. Access Your Application

      Once deployment is complete, you’ll receive a URL like example-app.klutch.sh. Visit this URL to access your Akkoma instance and complete the setup.


Sample Code: Getting Started with Akkoma

Here are some examples to help you interact with your Akkoma instance:

Example 1: JavaScript Client - Fetching Instance Information

// Frontend JavaScript example for Akkoma API
async function getInstanceInfo() {
try {
const response = await fetch('https://example-app.klutch.sh/api/v1/instance', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const instanceInfo = await response.json();
console.log('Instance Info:', instanceInfo);
return instanceInfo;
} catch (error) {
console.error('Error fetching instance info:', error);
throw error;
}
}
// Display instance information
async function displayInstanceInfo() {
const info = await getInstanceInfo();
document.getElementById('instance-name').textContent = info.title;
document.getElementById('instance-description').textContent = info.description;
document.getElementById('instance-version').textContent = info.version;
}

Example 2: Fetching Public Timeline

async function getPublicTimeline() {
try {
const response = await fetch('https://example-app.klutch.sh/api/v1/timelines/public?limit=20', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const posts = await response.json();
console.log('Public Timeline:', posts);
return posts;
} catch (error) {
console.error('Error fetching timeline:', error);
throw error;
}
}
// Display timeline posts
async function displayTimeline() {
const posts = await getPublicTimeline();
const container = document.getElementById('timeline-container');
posts.forEach(post => {
const postElement = document.createElement('div');
postElement.className = 'post';
postElement.innerHTML = `
<div class="post-author">@${post.account.acct}</div>
<div class="post-content">${post.content}</div>
<div class="post-date">${new Date(post.created_at).toLocaleString()}</div>
`;
container.appendChild(postElement);
});
}

Example 3: Authenticated API Request

async function getAuthenticatedTimeline(accessToken) {
try {
const response = await fetch('https://example-app.klutch.sh/api/v1/timelines/home', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const posts = await response.json();
return posts;
} catch (error) {
console.error('Error fetching home timeline:', error);
throw error;
}
}

Example 4: Python Client Example

import requests
import json
class AkkomaClient:
def __init__(self, base_url, access_token=None):
self.base_url = base_url
self.access_token = access_token
self.headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
if access_token:
self.headers['Authorization'] = f'Bearer {access_token}'
def get_instance_info(self):
"""Get instance information"""
response = requests.get(
f'{self.base_url}/api/v1/instance',
headers=self.headers
)
response.raise_for_status()
return response.json()
def get_public_timeline(self, limit=20):
"""Get public timeline"""
response = requests.get(
f'{self.base_url}/api/v1/timelines/public',
headers=self.headers,
params={'limit': limit}
)
response.raise_for_status()
return response.json()
def get_home_timeline(self, limit=20):
"""Get home timeline (requires authentication)"""
if not self.access_token:
raise ValueError("Access token required for home timeline")
response = requests.get(
f'{self.base_url}/api/v1/timelines/home',
headers=self.headers,
params={'limit': limit}
)
response.raise_for_status()
return response.json()
# Example usage
client = AkkomaClient('https://example-app.klutch.sh')
# Get instance info
info = client.get_instance_info()
print(f"Instance: {info['title']}")
print(f"Version: {info['version']}")
# Get public timeline
timeline = client.get_public_timeline(limit=10)
print(f"Found {len(timeline)} posts in public timeline")

Production Best Practices

Security Recommendations

  • Enable HTTPS: Always use HTTPS in production (Klutch.sh provides TLS certificates)
  • Secure Environment Variables: Store all sensitive credentials as environment variables in Klutch.sh
  • Strong Secrets: Generate strong SECRET_KEY_BASE and SIGNING_SALT values using secure random generators
  • Database Security: Use strong database passwords and enable SSL connections
  • Registration Control: Carefully manage AKKOMA_REGISTRATIONS_OPEN to prevent spam
  • Rate Limiting: Configure rate limiting to prevent abuse
  • Content Security Policy: Implement CSP headers for additional security
  • Regular Updates: Keep Akkoma and dependencies updated with security patches
  • Backup Strategy: Regularly backup your database and uploads volume
  • Moderation: Set up proper moderation tools and policies for your instance

Performance Optimization

  • Database Optimization: Regularly optimize PostgreSQL database with VACUUM and ANALYZE
  • Media Processing: Optimize ImageMagick and FFmpeg settings for your workload
  • Caching: Implement caching strategies for frequently accessed data
  • CDN Integration: Consider using a CDN for static assets and media files
  • Connection Pooling: Configure appropriate database connection pool sizes
  • Resource Monitoring: Monitor CPU, memory, and storage usage
  • Media Storage: Consider external object storage for media files at scale

Federation Best Practices

  • Instance Reputation: Maintain a good reputation in the Fediverse by following community guidelines
  • Content Moderation: Implement effective content moderation policies
  • Block Lists: Consider using community block lists to protect your users
  • Rate Limiting: Implement rate limiting to prevent abuse
  • Documentation: Provide clear documentation for your instance rules and policies
  • Community Guidelines: Establish and enforce community guidelines

Monitoring and Maintenance

Monitor your Akkoma application for:

  • Application Logs: Check logs in Klutch.sh dashboard for errors
  • Database Performance: Monitor query performance and slow queries
  • Storage Usage: Monitor persistent volume usage and plan for growth
  • Response Times: Track API response times
  • Error Rates: Monitor 4xx and 5xx error rates
  • Resource Usage: Track CPU and memory usage in Klutch.sh dashboard
  • Federation Health: Monitor federation activity and connection status

Regular maintenance tasks:

  • Backup Database: Regularly backup your PostgreSQL database
  • Backup Media Files: Backup uploaded media files from the persistent volume
  • Update Dependencies: Keep Elixir dependencies updated
  • Review Logs: Review application and error logs regularly
  • Security Audits: Perform regular security audits
  • Database Maintenance: Regularly run database maintenance tasks

Troubleshooting

Application Not Loading

  • Verify the app’s Traffic Type is HTTP
  • Check that the internal port is set to 4000 and matches your Dockerfile
  • Review build and runtime logs in the Klutch.sh dashboard
  • Ensure the Elixir application starts correctly (check the CMD in Dockerfile)
  • Verify all required environment variables are set

Database Connection Issues

  • Verify database environment variables are set correctly
  • For Klutch.sh PostgreSQL apps, use the app URL as the host and port 8000 externally
  • Check that the database is accessible from your Akkoma app
  • Verify database credentials and permissions
  • Ensure the database schema has been initialized with migrations

Media Upload Issues

  • Ensure persistent volume is mounted at /var/lib/akkoma/uploads
  • Check file permissions on the uploads directory
  • Verify ImageMagick, FFmpeg, and ExifTool are installed and working
  • Ensure sufficient disk space in the persistent volume
  • Check media processing configuration

Federation Issues

  • Verify AKKOMA_FEDERATING is set to true
  • Check that your instance URL is correctly configured
  • Ensure your domain DNS is properly configured
  • Verify ActivityPub endpoints are accessible
  • Check federation logs for connection errors

Performance Issues

  • Review database query performance and add indexes if needed
  • Check resource allocation in Klutch.sh (CPU and memory)
  • Monitor database connection pool usage
  • Review application logs for slow operations
  • Consider implementing caching for frequently accessed data
  • Optimize media processing settings

Data Not Persisting

  • Ensure persistent volumes are correctly mounted
  • Check file permissions on persistent volumes
  • Verify the application is writing to the correct directories
  • Ensure sufficient disk space in persistent volumes


Conclusion

Deploying Akkoma to Klutch.sh with a Dockerfile provides a scalable, reliable federated social networking solution with persistent storage, automatic deployments, and production-ready configuration. By following this guide, you’ve set up a high-performance Akkoma instance with proper data persistence, security configurations, and the ability to participate in the Fediverse.

Akkoma’s lightweight architecture, privacy-focused design, and comprehensive federation support make it an excellent choice for hosting your own social networking instance. Your application is now ready to connect with users across the Fediverse, share content, and build communities while maintaining control over your data and infrastructure.

Remember to follow the production best practices outlined in this guide, regularly monitor your application performance, and adjust resources as your user base grows. With proper configuration, monitoring, and maintenance, Akkoma on Klutch.sh will provide a reliable, secure foundation for your federated social networking needs.