Fo
Applications Azure

Foodsoft on Ubuntu 24.04 on Azure User Guide

| Product: Foodsoft 4.9.2 on Ubuntu 24.04 LTS on Azure

Overview

Foodsoft is an open source web application for running a nonprofit food cooperative or buying group. Members browse supplier catalogues and place orders together as a group, and the coop settles who ordered what and what each member owes. It keeps supplier and article lists, opens and closes ordering rounds, tallies each order group's totals, tracks member and working-group balances and financial transactions, and organises the shared tasks that keep a coop running. The cloudimg image installs Foodsoft 4.9.2 as the official upstream Docker stack and runs it behind nginx as a systemd service, so a complete food-coop management system is online within minutes of launch.

What is included:

  • Foodsoft 4.9.2 (AGPL-3.0) deployed from the official upstream Docker image foodcoops/foodsoft:4.9.2, pinned so the image never silently upgrades at build time
  • Docker Engine (Docker CE) + the Docker Compose plugin, installed from the official Docker package repository
  • The Foodsoft Compose stack: the app Rails web application (Puma on container port 3000), the worker Resque background worker (emails and order finalisation), a cron scheduled-task runner, db (MariaDB 11.4) and redis (Redis 7.2, the Resque queue)
  • A system nginx reverse proxy on port 80 forwarding to the Rails app on 127.0.0.1:3000, plus an unauthenticated static /cloudimg-health endpoint
  • A per-VM administrator password created at first boot, with a fresh Rails SECRET_KEY_BASE and a fresh database password rotated per instance - the upstream default admin login is rotated away before the web app is ever reachable
  • The database and Redis bind to the internal Docker network only; nothing but nginx on port 80 is published on the public interface
  • Three systemd units: nginx.service, foodsoft.service (a oneshot wrapper around docker compose up -d) and foodsoft-firstboot.service
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key, and a VNet plus subnet. Standard_B2s (2 vCPU / 4 GB RAM) is the recommended size. NSG inbound rules: allow 22/tcp from your management CIDR for SSH and 80/tcp from the CIDR that needs the Foodsoft web app (add 443/tcp if you enable HTTPS).

Step 1: Connect over SSH

Replace <vm-ip> with the public IP of your VM. The default login user is azureuser.

ssh azureuser@<vm-ip>

Step 2: Confirm the services are active

sudo systemctl is-active docker.service nginx.service foodsoft.service foodsoft-firstboot.service
cd /opt/foodsoft && sudo docker compose ps --format "table {{.Name}}\t{{.Status}}"

You should see active printed for each systemd unit, and the five Compose containers - foodsoft-app, foodsoft-worker, foodsoft-cron, foodsoft-db and foodsoft-redis - all in the Up state.

Docker, nginx and Foodsoft systemd services reporting active and the five Compose containers running

Step 3: Confirm only port 80 is public

The nginx reverse proxy serves an unauthenticated static /cloudimg-health endpoint on port 80, and the Foodsoft login page answers on /f/login. The Rails app listens on loopback only, and the database and Redis are not published to any host port at all.

curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1/f/login
curl -s http://127.0.0.1/cloudimg-health
sudo ss -tlnH | awk '{print $4}' | sort -u

/f/login returns 200, /cloudimg-health returns OK, and the listening sockets show only :80 (nginx) and :22 (SSH) on the public interface, with the Rails app on 127.0.0.1:3000. MariaDB and Redis do not appear - they are reachable only on the internal Docker network.

The login endpoint returns 200, the health check returns OK, and only port 80 and SSH are public

Step 4: Read the per-VM admin credentials

A unique administrator password is generated for your instance on its first boot and written to a root-only file, along with a fresh Rails secret key base and database password.

sudo cat /root/foodsoft-credentials.txt

This file lists FOODSOFT_URL (where to sign in), FOODSOFT_LOGIN_URL, FOODSOFT_ADMIN_USER (admin) and FOODSOFT_ADMIN_PASSWORD. Store the password somewhere safe.

The per-VM Foodsoft admin credentials file

Step 5: Confirm the default login has been rotated away

Foodsoft's upstream seed creates an initial admin user with the well-known password secret. On this image, first boot rotates that password to your per-VM value before the web app is ever exposed, so the default login is dead.

cd /opt/foodsoft
sudo docker exec foodsoft-app bundle exec rails runner \
  'puts User.authenticate("admin","secret") ? "DEFAULT STILL LIVE" : "default admin/secret REJECTED"'

The output is default admin/secret REJECTED, confirming the seeded default credential no longer works.

Proof that the upstream default admin/secret login is rejected

Step 6: Sign in to Foodsoft

Open http://<vm-ip>/ in your browser. Foodsoft redirects you to the foodcoop login page at /f/login. Enter the user admin and the FOODSOFT_ADMIN_PASSWORD from Step 4, then click Login.

You can also verify the credentials from the command line - it prints LOGIN_OK when the per-VM password authenticates:

PASS=$(sudo grep '^FOODSOFT_ADMIN_PASSWORD=' /root/foodsoft-credentials.txt | cut -d= -f2-)
cd /opt/foodsoft
sudo docker exec -e RT_PASS="$PASS" foodsoft-app bundle exec rails runner \
  'puts User.authenticate("admin", ENV["RT_PASS"]) ? "LOGIN_OK" : "LOGIN_FAIL"'

The Foodsoft login page

Step 7: Explore the dashboard

After signing in you land on the Foodsoft dashboard - it shows the current ordering rounds, your order group's balance and engagement, and quick links to members, orders, products and finances.

The Foodsoft dashboard after signing in

Step 8: Manage your suppliers

Open Articles -> Suppliers/articles to manage the suppliers your coop buys from. Each supplier holds its own article catalogue, stock and deliveries. Use Create new supplier to add your own.

The Foodsoft supplier management page

Step 9: Build your article catalogue

Open a supplier to manage its article catalogue - names, categories, units, net prices, VAT and deposit. You can add articles one at a time, upload a spreadsheet, or open a new ordering round for the coop directly from here.

The Foodsoft article catalogue for a supplier

From here the day-to-day flow is: open an order for a supplier, let members place their orders during the ordering window, close the order, and balance it in the finance area so each order group's account is charged its share.

Managing the stack

The Foodsoft stack is wrapped by the foodsoft.service systemd unit, which runs docker compose up -d from /opt/foodsoft.

sudo systemctl status foodsoft.service --no-pager

To inspect the application logs, tail the app or worker container:

cd /opt/foodsoft
sudo docker compose logs --tail 50 app

To restart the whole stack after a configuration change, run sudo systemctl restart foodsoft.service.

Configuring email

Out of the box no SMTP server is configured, so Foodsoft does not send email (invites, password resets and order notifications are silently held back rather than failing). To enable email, add your SMTP settings to /opt/foodsoft/.env and restart the stack. Set SMTP_ADDRESS, and as needed SMTP_PORT, SMTP_DOMAIN, SMTP_USER_NAME, SMTP_PASSWORD and SMTP_ENABLE_STARTTLS_AUTO=true, then run sudo systemctl restart foodsoft.service.

Enabling HTTPS

The image serves plain HTTP on port 80. For any public deployment, put TLS in front with your own domain. Point a DNS A record at the VM public IP, then install a certificate with certbot's nginx plugin. Outline:

  • Install certbot and the nginx plugin from the Ubuntu repositories.
  • Run certbot against your-domain.example to obtain and install a certificate into the nginx site.
  • Reload nginx.

Use your own registered domain in place of any example placeholder.

Maintenance

The OS receives unattended security updates. To update Foodsoft itself, edit the pinned image tag in /opt/foodsoft/docker-compose.yml, then from /opt/foodsoft run sudo docker compose pull, apply any database migrations with sudo docker compose run --rm app bundle exec rake db:migrate, and run sudo systemctl restart foodsoft.service. Always back up the foodsoft_db_data Docker volume before a major version upgrade.

Support

Backed by 24/7 cloudimg support. Foodsoft is developed by the foodcoops community and licensed under the AGPL-3.0. This image is provided by cloudimg and is not affiliated with or endorsed by the Foodsoft project.