Skip to content

Deploying Antville

Introduction

Antville is a pioneering open-source weblog hosting platform, affectionately known as the “Queen Mum of Weblog Hosting Systems.” Built on the Helma Object Publisher framework, Antville provides a robust, multi-user blogging environment that has powered high-traffic sites for over two decades, including antville.org and other community hosting platforms.

Deploying Antville on Klutch.sh gives you a scalable, production-ready blogging platform with automatic HTTPS, persistent storage for your content, and seamless PostgreSQL database integration. The platform supports multiple blogs per installation, user management, customizable skins, and a rich set of features for content management.

This guide walks you through deploying Antville using a custom Dockerfile on Klutch.sh, setting up a PostgreSQL database, configuring persistent storage, and best practices for running this Java-based application in production.


What You’ll Learn

  • How to deploy Antville with Helma Object Publisher using a Dockerfile on Klutch.sh
  • Setting up PostgreSQL as the database backend
  • Configuring persistent storage for content and media files
  • Setting up environment variables for database connectivity and SMTP
  • Best practices for production deployment and performance

Prerequisites

Before you begin, ensure you have:

  • A Klutch.sh account
  • A GitHub repository (can be a new empty repo)
  • Basic familiarity with Docker and Java applications
  • (Optional) SMTP server credentials for email notifications

Understanding Antville Architecture

Antville consists of several key components:

  • Helma Object Publisher: A Java-based application server using Rhino (server-side JavaScript) with an embedded Jetty web server
  • Application Layer: JavaScript-based application code running on Helma, handling blog logic, user management, and content rendering
  • Database: PostgreSQL (recommended) or MySQL/MariaDB for storing blog posts, users, comments, and metadata
  • Storage: File-based storage for images, media uploads, and configuration

The application runs on port 8080 by default via the embedded Jetty server, making it straightforward to deploy on Klutch.sh.


Step 1: Set Up PostgreSQL Database

Antville requires a database for storing blog content, user accounts, and metadata. We recommend PostgreSQL for best performance.

Option A: Deploy PostgreSQL on Klutch.sh (Recommended)

    1. Log in to Klutch.sh and navigate to the dashboard.

    2. Create a new project (if you don’t have one) or select an existing project.

    3. Create a PostgreSQL TCP app:

      • Click “New App”
      • Select “TCP” as the traffic type
      • Connect a GitHub repository containing a PostgreSQL Dockerfile, or use the official image
    4. Create a Dockerfile for PostgreSQL in a separate repository:

    FROM postgres:16-alpine
    # Set default environment variables
    ENV POSTGRES_DB=antville
    ENV POSTGRES_USER=antville
    # Expose PostgreSQL port
    EXPOSE 5432
    1. Configure a persistent volume for data:

      • Mount Path: /var/lib/postgresql/data
      • Size: 10 GB (adjust based on expected content volume)
    2. Set environment variables:

    Terminal window
    POSTGRES_PASSWORD=your-secure-password
    1. Deploy the PostgreSQL app. Note the app URL for connecting Antville (e.g., postgres-app.klutch.sh:8000).

Option B: Use an External PostgreSQL Service

You can also use managed PostgreSQL services like:

If using an external service, note the connection details (host, port, database, username, password) for later configuration.


Step 2: Prepare Your GitHub Repository

    1. Create a new GitHub repository for your Antville deployment.

    2. Create a Dockerfile in the root of your repository:

    FROM eclipse-temurin:17-jdk-alpine AS builder
    # Install build dependencies
    RUN apk add --no-cache bash curl git rsync nodejs npm
    # Set working directory
    WORKDIR /build
    # Clone Helma Object Publisher
    RUN git clone --depth 1 https://github.com/antville/helma.git
    # Build Helma
    WORKDIR /build/helma
    RUN chmod +x gradlew && \
    ./gradlew install
    # Download Antville
    WORKDIR /build
    RUN curl -L https://github.com/antville/antville/archive/refs/heads/main.tar.gz | tar xz && \
    mv antville-main antville
    # Download PostgreSQL JDBC driver
    RUN curl -L -o /build/helma/build/install/helma/lib/ext/postgresql.jar \
    https://jdbc.postgresql.org/download/postgresql-42.7.1.jar
    # Production stage
    FROM eclipse-temurin:17-jre-alpine
    # Install runtime dependencies
    RUN apk add --no-cache bash
    # Create helma user
    RUN addgroup -S helma && adduser -S helma -G helma
    # Set working directory
    WORKDIR /helma
    # Copy Helma installation from builder
    COPY --from=builder /build/helma/build/install/helma /helma
    # Copy Antville application
    COPY --from=builder /build/antville /helma/apps/antville
    # Create necessary directories
    RUN mkdir -p /helma/apps/antville/static \
    && mkdir -p /helma/db \
    && mkdir -p /helma/log
    # Copy configuration files
    COPY apps.properties /helma/apps.properties
    COPY server.properties /helma/server.properties
    COPY db.properties /helma/apps/antville/code/db.properties
    # Set permissions
    RUN chown -R helma:helma /helma
    # Switch to non-root user
    USER helma
    # Expose Helma port
    EXPOSE 8080
    # Start Helma
    CMD ["./bin/helma"]
    1. Create the apps.properties file:
    # Antville application configuration
    antville
    antville.mountpoint = /
    antville.repository.0 = apps/antville/code/
    antville.repository.1 = modules/jala/code/
    antville.static = apps/antville/static
    antville.staticMountpoint = /static
    antville.staticIndex = index.html
    1. Create the server.properties file:
    # Helma server configuration
    # HTTP port
    http.port = 8080
    # SMTP server for email notifications (configure via environment variable)
    smtp = ${SMTP_HOST}
    # Country setting
    country = US
    # Language setting
    language = en
    # Logging
    logdir = log
    loglevel = info
    1. Create the db.properties file:
    # PostgreSQL database configuration
    antville.url = jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
    antville.driver = org.postgresql.Driver
    antville.user = ${DB_USER}
    antville.password = ${DB_PASSWORD}
    # Connection pool settings
    antville.maxActive = 50
    antville.maxIdle = 10
    antville.minIdle = 5
    antville.maxWait = 10000
    1. Create a startup script start.sh:
    #!/bin/bash
    set -e
    # Substitute environment variables in configuration files
    envsubst < /helma/server.properties.template > /helma/server.properties
    envsubst < /helma/apps/antville/code/db.properties.template > /helma/apps/antville/code/db.properties
    # Initialize database if needed
    if [ "$INIT_DATABASE" = "true" ]; then
    echo "Initializing Antville database..."
    PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f /helma/apps/antville/db/postgre.sql
    fi
    # Start Helma
    exec ./bin/helma
    1. Update the Dockerfile to use the startup script:
    FROM eclipse-temurin:17-jdk-alpine AS builder
    # Install build dependencies
    RUN apk add --no-cache bash curl git rsync nodejs npm
    # Set working directory
    WORKDIR /build
    # Clone Helma Object Publisher
    RUN git clone --depth 1 https://github.com/antville/helma.git
    # Build Helma
    WORKDIR /build/helma
    RUN chmod +x gradlew && \
    ./gradlew install
    # Download Antville
    WORKDIR /build
    RUN curl -L https://github.com/antville/antville/archive/refs/heads/main.tar.gz | tar xz && \
    mv antville-main antville
    # Download PostgreSQL JDBC driver
    RUN curl -L -o /build/helma/build/install/helma/lib/ext/postgresql.jar \
    https://jdbc.postgresql.org/download/postgresql-42.7.1.jar
    # Production stage
    FROM eclipse-temurin:17-jre-alpine
    # Install runtime dependencies
    RUN apk add --no-cache bash gettext postgresql-client
    # Create helma user
    RUN addgroup -S helma && adduser -S helma -G helma
    # Set working directory
    WORKDIR /helma
    # Copy Helma installation from builder
    COPY --from=builder /build/helma/build/install/helma /helma
    # Copy Antville application
    COPY --from=builder /build/antville /helma/apps/antville
    # Create necessary directories
    RUN mkdir -p /helma/apps/antville/static \
    && mkdir -p /helma/db \
    && mkdir -p /helma/log
    # Copy configuration templates
    COPY apps.properties /helma/apps.properties
    COPY server.properties /helma/server.properties.template
    COPY db.properties /helma/apps/antville/code/db.properties.template
    COPY start.sh /helma/start.sh
    # Set permissions
    RUN chmod +x /helma/start.sh && \
    chown -R helma:helma /helma
    # Switch to non-root user
    USER helma
    # Expose Helma port
    EXPOSE 8080
    # Health check
    HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD wget --quiet --tries=1 --spider http://localhost:8080/ || exit 1
    # Start Helma using the startup script
    CMD ["/helma/start.sh"]
    1. (Optional) Create a .dockerignore file:
    .git
    .github
    *.md
    .env
    .env.local
    node_modules
    1. Commit and push your changes to GitHub:
    Terminal window
    git add .
    git commit -m "Add Antville deployment configuration for Klutch.sh"
    git push origin main

Step 3: Create Your App on Klutch.sh

    1. Log in to Klutch.sh and navigate to the dashboard.

    2. Create a new project (if you don’t have one already) by clicking “New Project” and providing a project name.

    3. Create a new app within your project by clicking “New App”.

    4. Connect your GitHub repository by selecting it from the list of available repositories.

    5. Configure the build settings:

      • Klutch.sh will automatically detect the Dockerfile in your repository root
      • The build will use this Dockerfile automatically
    6. Set the internal port to 8080 (Helma’s default port). This is the port that traffic will be routed to within the container.

    7. Select HTTP traffic for the app’s traffic type.


Step 4: Configure Persistent Storage

Antville stores uploaded images, media files, and logs in the filesystem. Configure persistent storage to retain these across deployments.

    1. In your app settings, navigate to the “Volumes” section.

    2. Add a persistent volume for static files:

      • Mount Path: /helma/apps/antville/static
      • Size: 10 GB (adjust based on expected media uploads)
    3. Add another persistent volume for logs (optional but recommended):

      • Mount Path: /helma/log
      • Size: 1 GB
    4. Save the volume configuration.

The /helma/apps/antville/static directory contains:

  • Uploaded images and media files
  • User avatars
  • Custom theme assets
  • Site-specific static content

For more details on managing persistent storage, see the Volumes Guide.


Step 5: Configure Environment Variables

Configure the necessary environment variables for database connectivity, SMTP, and application settings.

    1. In your app settings, navigate to the “Environment Variables” section.

    2. Add database connection variables:

    Terminal window
    # PostgreSQL Database Configuration
    DB_HOST=postgres-app.klutch.sh
    DB_PORT=8000
    DB_NAME=antville
    DB_USER=antville
    DB_PASSWORD=your-secure-database-password

    If using a Klutch.sh-hosted PostgreSQL TCP app, use your app’s hostname and port 8000.

    1. Add SMTP configuration (for email notifications):
    Terminal window
    # SMTP Configuration
    SMTP_HOST=smtp.example.com

    For production email delivery, consider using services like:

    1. Add initialization flag (for first deployment only):
    Terminal window
    # Set to 'true' only for the first deployment to initialize the database
    INIT_DATABASE=true

    Important: After the initial deployment, remove or set INIT_DATABASE=false to prevent database reinitialization.

    1. Mark sensitive values as secrets in the Klutch.sh UI to prevent them from appearing in logs.

Step 6: Initialize the Database

Before deploying Antville, you need to initialize the database schema. You have two options:

Option A: Automatic Initialization (via INIT_DATABASE)

    1. Set INIT_DATABASE=true in your environment variables
    2. Deploy the application
    3. After successful deployment, set INIT_DATABASE=false or remove the variable
    4. Redeploy to apply the change

Option B: Manual Initialization

    1. Connect to your PostgreSQL database using a client tool or terminal:
    Terminal window
    psql -h postgres-app.klutch.sh -p 8000 -U antville -d antville
    1. Download and run the schema script from the Antville repository:
    -- Run the PostgreSQL schema script
    -- Download from: https://github.com/antville/antville/blob/main/db/postgre.sql
    1. The script creates:
      • All necessary tables (users, sites, stories, comments, etc.)
      • Default indexes for performance
      • Initial user account with password ‘antville’

Step 7: Deploy Your Application

    1. Review your configuration to ensure all settings are correct:

      • Dockerfile is detected
      • Internal port is set to 8080
      • Persistent volumes are configured
      • Environment variables are set
      • Traffic type is set to HTTP
    2. Click “Deploy” to start the build and deployment process.

    3. Monitor the build logs to ensure the deployment completes successfully. The build typically takes 5-10 minutes due to Java compilation.

    4. Wait for the deployment to complete. Once done, you’ll see your app URL (e.g., https://example-app.klutch.sh).


Step 8: Initial Setup and Configuration

    1. Access your Antville instance by navigating to your app URL (e.g., https://example-app.klutch.sh).

    2. Create your first user account:

      • The first user created automatically receives administrator privileges
      • Choose a strong password
      • This account will manage the entire Antville installation
    3. Configure your site:

      • Set up site preferences
      • Choose a default skin/theme
      • Configure site metadata
    4. Create your first blog:

      • Navigate to site management
      • Create a new blog (also called “site” in Antville)
      • Customize the blog settings and appearance
    5. Start publishing:

      • Create your first story/blog post
      • Upload images
      • Manage comments

Getting Started: Sample Code

Accessing Antville via API

Antville exposes its functionality through a JavaScript-based API. Here are some common operations:

Creating a Story Programmatically

// Helma server-side JavaScript example
var story = new Story();
story.title = "My First Post";
story.text = "Welcome to my new blog powered by Antville!";
story.status = "public";
story.creator = session.user;
story.save();

Fetching Recent Stories

// Get the 10 most recent stories
var stories = res.handlers.site.stories.list(0, 10);
for each (var story in stories) {
res.write(story.title + "<br>");
}

Custom Skin Development

Antville uses a skin-based templating system. Create custom themes by modifying skin files:

<!-- Example main.skin file -->
<!DOCTYPE html>
<html>
<head>
<title><% response.title %></title>
<link rel="stylesheet" href="<% site.staticUrl %>style.css">
</head>
<body>
<header>
<h1><% site.title %></h1>
<nav><% site.navigation %></nav>
</header>
<main>
<% response.body %>
</main>
<footer>
<p>Powered by Antville</p>
</footer>
</body>
</html>

Managing Users

// Create a new user
var user = new User();
user.name = "newuser";
user.email = "user@example.com";
user.hash = User.prototype.hashPassword("securepassword");
user.save();
// Grant membership to a site
var membership = new Membership();
membership.user = user;
membership.site = res.handlers.site;
membership.role = "contributor";
membership.save();

Advanced Configuration

Custom Dockerfile with MySQL Support

If you prefer MySQL/MariaDB instead of PostgreSQL, modify the Dockerfile:

FROM eclipse-temurin:17-jdk-alpine AS builder
# Install build dependencies
RUN apk add --no-cache bash curl git rsync nodejs npm
WORKDIR /build
# Clone and build Helma
RUN git clone --depth 1 https://github.com/antville/helma.git
WORKDIR /build/helma
RUN chmod +x gradlew && ./gradlew install
# Download Antville
WORKDIR /build
RUN curl -L https://github.com/antville/antville/archive/refs/heads/main.tar.gz | tar xz && \
mv antville-main antville
# Download MySQL JDBC driver
RUN curl -L -o /build/helma/build/install/helma/lib/ext/mysql-connector.jar \
https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.2.0/mysql-connector-j-8.2.0.jar
# Production stage
FROM eclipse-temurin:17-jre-alpine
RUN apk add --no-cache bash gettext mysql-client
RUN addgroup -S helma && adduser -S helma -G helma
WORKDIR /helma
COPY --from=builder /build/helma/build/install/helma /helma
COPY --from=builder /build/antville /helma/apps/antville
RUN mkdir -p /helma/apps/antville/static \
&& mkdir -p /helma/db \
&& mkdir -p /helma/log
COPY apps.properties /helma/apps.properties
COPY server.properties /helma/server.properties.template
COPY db-mysql.properties /helma/apps/antville/code/db.properties.template
COPY start.sh /helma/start.sh
RUN chmod +x /helma/start.sh && \
chown -R helma:helma /helma
USER helma
EXPOSE 8080
CMD ["/helma/start.sh"]

Create db-mysql.properties:

# MySQL database configuration
antville.url = jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
antville.driver = com.mysql.cj.jdbc.Driver
antville.user = ${DB_USER}
antville.password = ${DB_PASSWORD}
# Connection pool settings
antville.maxActive = 50
antville.maxIdle = 10
antville.minIdle = 5
antville.maxWait = 10000

Update apps.properties for MySQL compatibility:

# Antville application configuration with MySQL
antville
antville.mountpoint = /
antville.repository.0 = apps/antville/code/
antville.repository.1 = apps/antville/db/my.compat/
antville.repository.2 = modules/jala/code/
antville.static = apps/antville/static
antville.staticMountpoint = /static
antville.staticIndex = index.html

Performance Tuning

Optimize Helma for production workloads by adjusting server.properties:

# HTTP configuration
http.port = 8080
http.maxConnections = 200
http.keepAlive = true
# Thread pool settings
minThreads = 10
maxThreads = 100
# Cache configuration
cachesize = 1000
# Session configuration
sessionTimeout = 60
# Logging
logdir = log
loglevel = warn
# SMTP
smtp = ${SMTP_HOST}

JVM Memory Settings

For larger installations, add JVM options by modifying the startup script:

#!/bin/bash
set -e
# JVM memory settings
export JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC"
# Substitute environment variables
envsubst < /helma/server.properties.template > /helma/server.properties
envsubst < /helma/apps/antville/code/db.properties.template > /helma/apps/antville/code/db.properties
# Start Helma with optimized settings
exec ./bin/helma $JAVA_OPTS

Production Best Practices

Security

  • Change default credentials: Update the default ‘antville’ database password immediately
  • Use HTTPS only: Klutch.sh provides automatic HTTPS for all apps
  • Implement strong passwords: Require strong passwords for all user accounts
  • Regular updates: Keep Helma and Antville updated to the latest versions
  • Secure environment variables: Mark database credentials and secrets as protected

Performance

  • Database indexing: Ensure proper indexes are created (included in schema scripts)
  • Connection pooling: Configure appropriate pool sizes based on traffic
  • Static file caching: Leverage Klutch.sh CDN for static assets
  • Monitor memory usage: Adjust JVM heap size based on actual usage

Backups

  • Database backups: Regularly backup your PostgreSQL database
  • File backups: Backup the /helma/apps/antville/static directory
  • Configuration backups: Keep copies of your configuration files
Terminal window
# Example PostgreSQL backup command
pg_dump -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME > antville_backup.sql

Monitoring

  • Application logs: Monitor /helma/log for errors and warnings
  • Database performance: Track query performance and connection usage
  • Resource utilization: Monitor CPU and memory through Klutch.sh dashboard

Troubleshooting

Application Won’t Start

Issue: Container starts but application doesn’t respond

Solutions:

  • Verify port 8080 is correctly configured
  • Check database connectivity with environment variables
  • Review startup logs for Java exceptions
  • Ensure JDBC driver is properly installed

Database Connection Errors

Issue: Cannot connect to PostgreSQL

Solutions:

  • Verify database hostname and port (use 8000 for Klutch.sh TCP apps)
  • Check database credentials are correct
  • Ensure PostgreSQL is running and accessible
  • Test connection manually with psql
Terminal window
psql -h postgres-app.klutch.sh -p 8000 -U antville -d antville -c "SELECT 1"

Out of Memory Errors

Issue: Application crashes with OutOfMemoryError

Solutions:

  • Increase JVM heap size in startup script
  • Scale up the instance size in Klutch.sh
  • Review for memory leaks in custom code
  • Reduce cache sizes if necessary

Images Not Loading

Issue: Uploaded images return 404 errors

Solutions:

  • Verify persistent volume is mounted to /helma/apps/antville/static
  • Check file permissions in the static directory
  • Ensure staticMountpoint is configured in apps.properties
  • Review the static URL configuration

Slow Performance

Issue: Pages load slowly

Solutions:

  • Enable database query logging to identify slow queries
  • Increase connection pool size
  • Add database indexes for frequently queried fields
  • Consider caching strategies for heavily accessed content

Scaling Considerations

Vertical Scaling

For increased traffic, scale up your instance:

  • Increase CPU and memory allocation
  • Expand database resources
  • Increase storage volume size

Database Optimization

-- Add indexes for common queries
CREATE INDEX idx_story_created ON story(created);
CREATE INDEX idx_story_site ON story(site_id);
CREATE INDEX idx_comment_story ON comment(story_id);
CREATE INDEX idx_user_email ON "user"(email);

Static Asset Optimization

  • Use CDN for serving static assets
  • Compress images before upload
  • Enable browser caching headers

Local Development with Docker Compose

For local testing before deploying to Klutch.sh, use Docker Compose:

version: '3.8'
services:
antville:
build: .
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=antville
- DB_USER=antville
- DB_PASSWORD=devpassword
- SMTP_HOST=mailhog
- INIT_DATABASE=true
volumes:
- antville_static:/helma/apps/antville/static
depends_on:
- postgres
- mailhog
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_DB=antville
- POSTGRES_USER=antville
- POSTGRES_PASSWORD=devpassword
volumes:
- postgres_data:/var/lib/postgresql/data
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
volumes:
antville_static:
postgres_data:

Run locally with:

Terminal window
docker-compose up -d

Access Antville at http://localhost:8080 and MailHog at http://localhost:8025 for email testing.

Note: Docker Compose is for local development only. Deploy to Klutch.sh using the Dockerfile approach described in this guide.


Updating Antville

To update to a newer version of Antville:

    1. Update the Dockerfile to pull the latest Antville release:
    # In the builder stage, use a specific release tag
    RUN curl -L https://github.com/antville/antville/archive/refs/tags/v1.6.tar.gz | tar xz && \
    mv antville-1.6 antville
    1. Commit and push the changes:
    Terminal window
    git add Dockerfile
    git commit -m "Update Antville to version 1.6"
    git push origin main
    1. Redeploy through the Klutch.sh dashboard.

    2. Verify the update by checking the application logs and testing functionality.


Resources


Conclusion

You now have a fully functional Antville deployment running on Klutch.sh with PostgreSQL database integration and persistent storage. This classic weblog hosting platform provides:

  • Multi-user blogging capabilities
  • Customizable skins and themes
  • Image and media management
  • Comment system
  • User management and permissions
  • Automatic HTTPS and scalable infrastructure

Antville’s proven architecture, which has powered high-traffic sites for over two decades, combined with Klutch.sh’s modern deployment infrastructure, gives you a reliable and maintainable blogging platform.

For community support and discussions, visit the Antville community or explore the GitHub repositories for both Antville and Helma.