Applications AWS

KitchenOwl on AWS User Guide

| Product: KitchenOwl

Overview

This guide covers the deployment and configuration of KitchenOwl on AWS using the cloudimg AWS Marketplace AMI. KitchenOwl is an open source app for managing a household's food. Several people share the same shopping list and items check off in real time as anyone shops, so the list stays current whoever is at the store. You keep a collection of recipes, add their ingredients to the list in one tap, and plan meals across the week on a calendar. It also tracks grocery expenses so a household can split the cost. A clean Flutter web app fronts everything and the same account works from the mobile apps.

The cloudimg image ships the free and open source, AGPL-3.0 licensed KitchenOwl, run the officially supported way as the upstream all in one container pinned by image digest and captured into the instance, so it starts in seconds. Because KitchenOwl's upstream token signing secret is a well known fixed value, nothing here ships with a known secret: a unique JWT signing secret is generated for each instance on first boot, before the app is reachable, and a per instance admin account with a random password is seeded once the app is healthy. Open self sign up is disabled and onboarding closes as soon as the administrator exists. Backed by 24/7 cloudimg support.

KitchenOwl is a trademark of its respective owner. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by the KitchenOwl project. It ships the free and open source AGPL-3.0 licensed self hosted software, unmodified.

What is included:

  • KitchenOwl v0.7.9 (the AGPL-3.0 licensed all in one container: Flask/uWSGI API plus the built Flutter web app), pinned by image digest
  • A SQLite application database, created empty on first boot and stored on a Docker volume that lives on a dedicated EBS data volume mounted at /var/lib/docker
  • Docker Engine with the app published to the loopback interface only, fronted by nginx on port 80 with WebSocket upgrade for realtime shopping list sync
  • kitchenowl.service, kitchenowl-firstboot.service, kitchenowl-postboot.service and nginx.service as systemd units, enabled and active on boot
  • A unique JWT signing secret and a per instance admin account with a random password generated per instance on first boot, never baked into the image
  • No default login, no shipped secret, open self sign up disabled and an empty database on first boot
  • Ubuntu 24.04 LTS base with latest security patches applied at build time
  • cloud-init for seamless SSH key injection on first boot
  • 24/7 cloudimg support with guaranteed 24 hour response SLA

Prerequisites

  • An active AWS account and a subscription to the KitchenOwl listing on AWS Marketplace
  • An EC2 key pair, and a VPC and subnet in your target region
  • A security group that allows 22/tcp from your management network and 80/tcp for the web app from the networks that use it

Recommended instance type: m5.large (2 vCPU, 8 GB RAM) is a sensible starting point for a household. For larger households or many concurrent users use m5.xlarge or larger. KitchenOwl is CPU only and needs no GPU.

Step 1: Launch the instance from the AWS Marketplace

Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for KitchenOwl. Select the cloudimg listing and choose Select, then Continue on the subscription summary.

Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that opens port 22 from your management network and port 80 for the web app. Leave the root volume at the default size or larger; the KitchenOwl data lives on its own dedicated data volume.

Select Launch instance. First boot initialisation takes a few seconds after the instance state becomes Running and the status checks pass, while the per instance token signing secret and administrator account are generated.

Step 2: Launch the instance from the AWS CLI

The following block launches an instance from the cloudimg KitchenOwl Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, <security-group-id> with a security group as described above, and <your-mgmt-cidr> with the network you administer from.

aws ec2 authorize-security-group-ingress --group-id <security-group-id> \
  --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id <security-group-id> \
  --protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 run-instances \
  --image-id <ami-id> \
  --instance-type m5.large \
  --key-name <key-name> \
  --subnet-id <subnet-id> \
  --security-group-ids <security-group-id> \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kitchenowl}]'

Step 3: Connect to your instance

Connect over SSH using your key pair and the login user for your operating system variant.

OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i <key-name>.pem ubuntu@<public-ip>

Step 4: Confirm the services are running

The app runs as one all in one container under kitchenowl.service, fronted by nginx. The container is published to 127.0.0.1:8080 only; nginx on :80 is the single public front door. Confirm the services are active and see the container:

sudo systemctl is-active docker kitchenowl nginx
sudo docker compose -f /etc/kitchenowl/compose.yaml ps

You will see the services report active and the container running. KitchenOwl is bound only to the loopback interface; nginx on :80 proxies / to it and passes through WebSocket upgrades so the shopping list syncs in real time.

Step 5: Read the per instance credentials

A unique JWT signing secret was generated for this instance on the first boot, before the app was reachable, and a per instance admin account with a random password was seeded once the app was healthy and written to a root only file. Read it:

sudo cat /root/kitchenowl-credentials.txt

The file (mode 0600 root:root) holds ADMIN_USERNAME and ADMIN_PASSWORD (the account you sign in to the web app with) and WEB_URL. None of these ship in the image; every value is unique to this instance, so no two instances share a credential and there is no default login to change.

Step 6: Verify the security model

The web app and the health endpoint are reachable without authentication, but every protected API endpoint requires a bearer token, and open self sign up is disabled. Confirm that the web app loads, that an unauthenticated request to a protected endpoint is rejected with 401, and that the per instance admin credential authenticates a real call:

ADMIN_USERNAME=$(sudo grep '^ADMIN_USERNAME=' /root/kitchenowl-credentials.txt | cut -d= -f2-)
ADMIN_PASSWORD=$(sudo grep '^ADMIN_PASSWORD=' /root/kitchenowl-credentials.txt | cut -d= -f2-)
HEALTH=/api/health/8M4F88S8ooi4sMbLBfkkV7ctWwgibW6V
curl -s -o /dev/null -w 'web UI       (no auth):   %{http_code}\n' http://localhost/
curl -s -o /dev/null -w 'health       (no auth):   %{http_code}\n' "http://localhost$HEALTH"
curl -s -o /dev/null -w 'GET /api/user (no token): %{http_code}\n' -H 'Accept: application/json' http://localhost/api/user
TOKEN=$(curl -s -X POST http://localhost/api/auth \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d "{\"username\":\"$ADMIN_USERNAME\",\"password\":\"$ADMIN_PASSWORD\",\"device\":\"guide\"}" | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')
curl -s -o /dev/null -w 'GET /api/user (token):    %{http_code}\n' \
  -H "Authorization: Bearer $TOKEN" -H 'Accept: application/json' http://localhost/api/user

The web app returns 200, the health endpoint returns 200, the protected user endpoint is rejected with 401 for no token, and the same call with the per instance admin token returns 200. This is the security model: the API is gated by a bearer token you obtain by signing in, and there is no open registration.

The same round trip is bundled as a single script on the image, which the build and smoke tests run to prove the credential works end to end. It signs in, creates a household, adds a shopping list item and reads it back:

sudo /usr/local/sbin/kitchenowl-roundtrip.sh

Step 7: Open the web app and sign in

Browse to http://<public-ip>/ to reach the KitchenOwl web app. Sign in with the ADMIN_USERNAME and ADMIN_PASSWORD from Step 5.

The KitchenOwl sign in page with a Welcome back heading and Username and Password fields and a Login button

Step 8: Use the shared shopping list

After signing in, open a household to reach its shopping list. Add items by typing in the search box and tapping to add, and check them off as you shop. Every member of the household sees the same list and it syncs in real time, so whoever is at the store always has the current list. Items can be grouped by category and sorted alphabetically or by how often you buy them.

The KitchenOwl shopping list showing ten grocery items as cards, Bananas, Chicken breast, Coffee beans, Eggs, Milk, Olive oil, Parmesan, Sourdough bread, Spinach and Tomatoes, with a search box and the shopping list, recipes, meal planner and household navigation

Step 9: Keep a recipe collection

Open Recipes to store your household's recipes with their ingredients, steps, cook time and yield. From a recipe you can add all of its ingredients to the shopping list in one tap, and you can import recipes from a URL. Use the search box to find a recipe instantly.

The KitchenOwl recipes page showing a Tomato Basil Pasta recipe in the list, with a search box and an add button

A recipe opens to show its ingredients, preparation and cook time and the number it serves. From here you can add its ingredients to the shopping list or add the recipe to the meal planner.

The KitchenOwl recipe detail for Tomato Basil Pasta showing a twenty five minute total time, ten minute prep and fifteen minute cook, a description, a yield of four and the ingredients basil, garlic, olive oil, parmesan, spaghetti and tomatoes, with an add to meal plan button

Step 10: Plan meals for the week

Open Meal planner to plan which recipes you will cook on which days. Add a recipe to a day and KitchenOwl can add its missing ingredients to the shopping list for you, so the weekly shop follows the plan.

The KitchenOwl meal planner showing the Your planned meals heading with Tomato Basil Pasta scheduled on Monday and a Discover recipes button

Step 11: Add household members

Open self sign up is disabled on this image, so new members are added by the administrator rather than by anyone who reaches the URL. Sign in as the admin, open Settings, and create accounts for your household members, or generate an invite. To enable open registration instead (anyone can create their own account), edit /etc/kitchenowl/compose.yaml, set OPEN_REGISTRATION to "true", and restart the app:

sudo systemctl restart kitchenowl

Step 12: Call the API from your own machine

Every feature of the web app is backed by the REST API, which you can call directly. Obtain a token by signing in, then call a protected endpoint with the instance address:

TOKEN=$(curl -s -X POST http://<public-ip>/api/auth \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"username":"<ADMIN_USERNAME>","password":"<ADMIN_PASSWORD>","device":"cli"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')
curl -s -H "Authorization: Bearer $TOKEN" -H 'Accept: application/json' \
  "http://<public-ip>/api/household"

The login returns a short lived access token (15 minutes) plus a refresh token; a long lived token for automation can be minted with POST /api/auth/llt. The API is documented at http://<public-ip>/api/openapi.

Step 13: Server components

Component Version / Detail
Application KitchenOwl v0.7.9 all in one (Flask/uWSGI API + Flutter web UI), pinned by image digest
Front door nginx on :80 proxying / to the app with WebSocket upgrade
Application database SQLite at /data/database.db (created empty on first boot, on a Docker volume)
Data volume dedicated EBS volume mounted at /var/lib/docker, carrying the image and the database
Orchestration Docker Compose under kitchenowl.service
JWT signing secret per instance, generated first boot into /etc/kitchenowl/kitchenowl.env
Admin account per instance random password, seeded first boot into /root/kitchenowl-credentials.txt
Registration open self sign up disabled (OPEN_REGISTRATION=false)
Operating system Ubuntu 24.04 LTS (patched at build)
License AGPL-3.0 (KitchenOwl)

Step 14: Managing the service

sudo systemctl status kitchenowl --no-pager | head -12
sudo docker compose -f /etc/kitchenowl/compose.yaml logs --tail 40 kitchenowl

Restart the app with sudo systemctl restart kitchenowl, follow the logs live with sudo docker compose -f /etc/kitchenowl/compose.yaml logs -f kitchenowl, and view configuration in /etc/kitchenowl/kitchenowl.env and /etc/kitchenowl/compose.yaml. After changing the environment file, restart the service to apply it.

Step 15: Use your own domain and HTTPS (production)

The image serves the web app over plain HTTP on port 80, which is convenient behind a load balancer or private network. For production you should terminate TLS in front of the instance so credentials travel encrypted:

  • Front the instance with an Application Load Balancer with an ACM certificate, or a CDN, and forward to nginx on port 80.
  • Or install your own certificate: add a TLS server block to /etc/nginx/sites-available/kitchenowl referencing your certificate and key, open 443/tcp on the security group, then sudo systemctl reload nginx.
  • If you serve the app from a custom domain, set FRONT_URL in /etc/kitchenowl/kitchenowl.env to that URL and restart the app so realtime sync uses the right origin. The app reads its URL at first boot from the resolved public address, so use an Elastic IP or set the address before first boot.

Step 16: Security recommendations

  • Restrict the security group. Allow TCP 80 (and 22 for admin) only from the networks that use the app.
  • Terminate TLS in front of the app (Step 15) so the admin password and tokens are encrypted in transit.
  • Rotate the seeded admin password. Sign in and change it in Settings.
  • Keep registration closed. Open self sign up is disabled by default; leave it that way and add members as the administrator unless you specifically want open registration.
  • Keep the app private. KitchenOwl is bound to loopback and fronted by nginx; keep it that way and never expose the container port directly.
  • Keep the OS patched. Unattended security upgrades remain enabled on the running instance.

Step 17: Support and Licensing

KitchenOwl is distributed under the GNU Affero General Public License v3.0 (AGPL-3.0). This cloudimg image bundles the unmodified official open source release; cloudimg provides the packaging, the nginx front door, the per instance secret and admin generation, the dedicated data volume, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA. KitchenOwl is an independent open source project and this image is not affiliated with or endorsed by it.

Deploy on AWS

Launch KitchenOwl from the AWS Marketplace and follow this guide to a working household grocery, recipe and meal planning app in minutes.