Is InvokeAI the right tool for a shared studio?
Yes, if your team wants a polished canvas, galleries and boards rather than wiring node graphs. Out of the box it is a one-person app: with multiuser off, config_default.py says it runs under a built-in system account that holds admin rights. Switch multi-user mode on and the administrator guide gives you sign-in, a gallery per person, logins that last a day (a week with “Remember me”), and a Model Manager only administrators can change.
Per that guide, single sign-on (OAuth2 and OpenID Connect) is only planned, and there is no way to give people different models and no audit log yet. If your team prefers node graphs, our ComfyUI workload guide is the better fit.
How much card do your models need?
Pick the model family first, then the card. InvokeAI's hardware page gives minimums like these for Windows and Linux as rough guidelines, and the second number matters too: it is the server's own memory.
| If your team uses | Card memory, at least | Server memory, at least |
|---|---|---|
| SD1.5 at 512x512 | 4 GB | 8 GB |
| SDXL at 1024x1024 | 8 GB | 16 GB |
| FLUX.1 at 1024x1024 | 10 GB | 32 GB |
| Z-Image Turbo at 1024x1024 | 8 GB (Q4_K; 16 GB for Q8 or BF16) | 16 GB |
| Krea-2 at 1024x1024 | 24 GB (FP8 from 16 GB) | 32 GB |
Watch the card's age as well as its memory. The image used below (v6.14.2) runs torch 2.7.1 built for CUDA 12.8, and PyTorch's build script for 2.7 (build_cuda.sh) targets only sm_75 and newer in those builds. So none of the older cards on our list will generate with it, even though InvokeAI's table lists 10xx cards for SD1.5: not the GTX 1080 Ti, 1080, 1070 Ti, 1070 or 1070M, the Tesla V100, P100, P40, P4, M60 or M6, the Quadro P6000, P5000, M3000M, K3100M or 3000M, nor the TITAN V. Choose an RTX 20xx, T4, Quadro RTX or anything newer.
Our advice is to buy for the heaviest model anybody will reach for, and to add server memory for a second card, since the YAML settings page notes that cards holding different models push RAM use up.
What happens when everyone presses Invoke at once
With one card, pictures are made one job at a time, and InvokeAI decides whose turn it is. The default, round_robin, rotates between people, so a colleague's big batch does not lock you out; FIFO serves strictly in arrival order instead.
Version 6.14.0 brought support for several GPUs: with the default generation_devices: auto, each card works on its own job in parallel, turns still shared fairly. The guide's FAQ still lists it as something for later; the release notes and settings reference are newer. Two cards in one server are quoted for you rather than picked in the configurator; our multi-GPU page explains the options.
The server that fits
With our GPU servers the card is never shared. It sits in a physical machine only your account rents and goes straight to your operating system, so the driver and CUDA release are your pick and nothing time-slices the card. The rest of the box comes too, every core and every disk, with root access and its own HPE iLO or Dell iDRAC, which lets you fix a driver update gone wrong from the screen even when the network is down.
Models are big downloads, but the port is unmetered, so they never show on your invoice. When you can start depends on the card: about 30 minutes once the order is approved if a machine already carries it; 4 to 24 hours when we fit a card we hold; 5 to 10 working days when one has to be bought in; and 10 to 15 working days for a current-generation accelerator on allocation. There is no contract. Pick the location nearest your team. InvokeAI's Docker README limits GPU speed-ups to x86_64, so skip the ARM servers.
Up and running in an evening
Before you start, install Ubuntu, NVIDIA's driver, Docker (Engine 28 at minimum), plus NVIDIA's Container Toolkit (per NVIDIA's guide). You need a Turing-or-newer card and, as our own rule, nvidia-smi showing CUDA 12.8 or above. Paste the block as a user with sudo rights. It switches the firewall on for SSH only, confirms your Docker version, tests the card with NVIDIA's sample container, writes the compose file the first time only, confirms the file still has the 127.0.0.1 port, the multi-user switch, a version-numbered image and the card reservation, and starts InvokeAI. Wait for INVOKE-UP. One catch is that the OpenSSH rule only covers port 22; if your SSH runs elsewhere, open that port before pasting.
S=/srv/invokeai
sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw && sudo ufw allow OpenSSH && sudo ufw --force enable \
&& ver=$(sudo docker version -f '{{.Server.Version}}') && [ "${ver%%.*}" -ge 28 ] \
&& sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi && sudo mkdir -p $S/root \
&& { [ -e $S/compose.yaml ] || sudo tee $S/compose.yaml >/dev/null <<'EOF'
services:
invokeai:
image: ghcr.io/invoke-ai/invokeai:v6.14.2-cuda
container_name: invokeai
restart: unless-stopped
environment:
INVOKEAI_MULTIUSER: "true"
INVOKEAI_STRICT_PASSWORD_CHECKING: "true"
ports:
- "127.0.0.1:9090:9090"
volumes:
- /srv/invokeai/root:/invokeai
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
EOF
} && grep -q '"127.0.0.1:9090:9090"' $S/compose.yaml && grep -q 'INVOKEAI_MULTIUSER: "true"' $S/compose.yaml \
&& grep -q 'invokeai:v[0-9]' $S/compose.yaml && grep -q 'capabilities: \[gpu\]' $S/compose.yaml \
&& sudo docker compose -f $S/compose.yaml up -d && echo INVOKE-UP \
|| echo "STOP - a check failed, or an existing compose.yaml lacks the 127.0.0.1 port, multi-user line, pinned tag or GPU line"
Why v6.14.2-cuda and not latest? The project's build-container.yml gives latest to builds of its main development branch, currently the v7.0 alphas. A release tag stays put until you move it.
How this compares with the official docker-compose.yml, change by change: the service is invokeai instead of invokeai-cuda, the name to give docker compose exec; release tag instead of latest; build section removed; the .env file, the HF_HOME setting and its separate volume dropped (the entrypoint then keeps that cache under /invokeai); the INVOKEAI_PORT, HOST_INVOKEAI_ROOT and INVOKEAI_ROOT variables removed, as the image already sets 9090 and /invokeai; port limited to 127.0.0.1; the long bind entry with create_host_path swapped for a plain fixed path; tty and stdin_open removed; all GPUs rather than one; the YAML anchor and the CPU-only and AMD variants deleted; and a fixed container_name, restart: unless-stopped and the two multi-user settings added as INVOKEAI_ variables, which works for any option.
127.0.0.1 matters because a published port written without an address is opened by Docker on every address, and traffic to it never meets ufw's IPv4 rules (nor its IPv6 rules once IPv6 is on inside Docker). From Engine 28, publishing on 127.0.0.1 means only the server itself can connect, hence the version test.
Letting your team in safely
Make yourself the administrator first, privately. Until an admin exists, the sign-up call in InvokeAI's auth.py accepts the first person who uses it.
- Open a tunnel from your computer through your personal SSH account with
ssh -N -L 8080:127.0.0.1:9090 you@server-ip. Port 9090 on the server is all InvokeAI needs. - Visit
http://localhost:8080and fill in the Administrator Setup form. Your email becomes your username. Strict checking is on, so the password needs eight or more characters and must mix capitals, small letters and digits. - Install your models in the Model Manager, then invite people from the web interface, or run
sudo docker exec -ti --user 1000 invokeai invoke-useraddand answer its questions. Putting--passwordon that command line also works, but then the password shows up inpsand your shell history.
Now open it to the office. The guide recommends HTTPS through a reverse proxy and restricting who can connect. On Ubuntu 24.04 or newer, Caddy comes from the normal archive and fetches the certificate itself. First create DNS for the hostname pointing at this server, using only an A record unless you also add a ufw rule on 443 for your office's IPv6 prefix. The block will not run until both example values are replaced and /api/v1/auth/status reports an administrator in multi-user mode. Port 80 opens to all for the certificate; 443 only to your office. Caddy runs on the server itself, so ufw covers it on IPv4 and IPv6.
SITE=studio.example.com; OFFICE=198.51.100.7 # change both first
[ "$SITE" != studio.example.com ] && [ "$OFFICE" != 198.51.100.7 ] \
&& curl -s http://127.0.0.1:9090/api/v1/auth/status | grep -q '"setup_required":false,"multiuser_enabled":true' \
&& sudo apt-get update && sudo apt-get install -y caddy \
&& printf '%s {\n\treverse_proxy 127.0.0.1:9090\n}\n' "$SITE" | sudo tee /etc/caddy/Caddyfile >/dev/null \
&& sudo ufw allow 80/tcp && sudo ufw allow from "$OFFICE" to any port 443 proto tcp \
&& sudo systemctl reload caddy && echo HTTPS-UP \
|| echo "STOP - check the two values and that InvokeAI answers on 127.0.0.1:9090 in multi-user mode with an admin, then read the apt, ufw and caddy lines above"
The guide also advises rate-limiting the login address, /api/v1/auth/login. For people on changing home addresses, a private network works better; our WireGuard workload guide shows how.
Keeping your images safe
Backups are yours to make and to copy off the server. The administrator guide says a full backup holds databases, models, outputs and invokeai.yaml; packing the root folder with compose.yaml catches all of it, with InvokeAI paused so the database is consistent. Models make up most of the size. Paste the top line again in any new terminal, then run one part at a time. An archive only counts once A finds the database in it and leaves a .ok file beside it; only then does A delete older archives, so the three most recent verified ones stay. Should A stop after printing SAVED, your new archive is fine and only the tidy-up of old ones went wrong; if SAVED never appeared, the unfinished archive has been thrown away. For B, set Z to the archive you want back. Send archives off the server with rsync -a, without --delete.
S=/srv/invokeai; K=/var/backups/invokeai; R=$S/root; Y=$S/compose.yaml; DC="sudo docker compose -f $Y"
# A) backup, then keep 3
F=$K/invokeai-$(date +%F-%H%M%S).tar.gz; sudo install -d -m 700 $K && $DC stop \
&& sudo tar -czf $F -C $S compose.yaml root && LS=$(sudo tar -tzf $F) \
&& grep -qx root/databases/invokeai.db <<< "$LS" && sudo touch $F.ok && echo SAVED $F \
&& sudo sh -c "ls -1t $K/*.ok | tail -n +4 | while read o; do rm -f \"\$o\" \"\${o%.ok}\"; done" \
|| { sudo test -e $F.ok || sudo rm -f $F; echo "STOP - read above; the archive stays only if SAVED appeared"; }; $DC start
# B) restore (or undo an update) - set Z
Z=$K/invokeai-DATE.tar.gz; sudo test -e "$Z.ok" && ! sudo test -e $R.previous \
&& ! sudo test -e $Y.previous && LS=$(sudo tar -tzf "$Z") && grep -qx root/databases/invokeai.db <<< "$LS" \
&& sudo mkdir -p $S && { [ ! -e $Y ] || $DC down; } && { sudo docker rm -f invokeai 2>/dev/null; true; } \
&& { [ ! -e $Y ] || sudo mv $Y $Y.previous; } && { [ ! -e $R ] || sudo mv $R $R.previous; } \
&& sudo tar -xzf "$Z" -C $S && $DC up -d && echo RESTORED \
|| echo "STOP - check Z, Z.ok, .previous; none = nothing moved, else they hold the data"
# C) undo B - set UNDO=yes
UNDO=no; [ $UNDO != yes ] || { sudo test -d $R.previous/databases && sudo test -f $Y.previous \
&& { $DC down; true; } && sudo rm -rf $R $Y && sudo mv $R.previous $R && sudo mv $Y.previous $Y \
&& $DC up -d && echo ROLLED-BACK || echo "STOP - undo halted, both .previous copies must exist"; }
To move to a newer release, run A, set TAG to a published -cuda tag and run `TAG=vX.Y.Z-cuda; [ "$TAG" != vX.Y.Z-cuda ] && sudo find $K -mmin -60 -name '*.ok' | grep -q . && sudo docker image pull ghcr.io/invoke-ai/invokeai:$TAG && sudo sed -i "s#/invokeai:v.*#/invokeai:$TAG#" $Y && grep -q "invokeai:$TAG\$" $Y && $DC up -d && echo UPDATED || echo "STOP - update halted". It wants a SAVED backup under an hour old and downloads while you work. If the release disappoints, B with that archive brings back your data and the older tag. Moving to a fresh server? Run the setup block, paste the top line, then create the backup folder (sudo install -d -m 700 $K does it) and use sudo to place the archive and its .ok` file there before running B. C takes a restore back, even a half-finished one, without touching anything inside the half-restored folder. Delete the .previous copies when you are happy, because B refuses while they exist.
When you might not need one
If you are the only person making a handful of images a week, a monthly GPU server is more than you need. And for a public site where strangers sign up, note InvokeAI's own guide says it has not been through a rigorous security audit. On licences, in our general reading and not legal advice: InvokeAI is Apache 2.0, so anyone passing copies on must ship the licence text with them, preserve the copyright and attribution notices (plus a NOTICE file, should a release ever include one) and flag the files they modified; every model you install has its own licence, which governs how your team can use the pictures.
Questions people ask
- Will two designers' jobs run side by side on one card?
- No, one card makes one picture job at a time; both of you can queue, and round-robin takes turns between you. To truly run jobs side by side you need a second card, which InvokeAI uses through
generation_devicessince 6.14.0. - Is single-user mode fine if only I use it?
- Yes, as long as you reach it through an SSH tunnel. Single-user mode has no sign-in at all, so whoever can open the page is treated as the administrator. The moment a second person or a public address is involved, switch on multi-user mode.
- InvokeAI is ignoring my GPU. What should I check?
- Start with the card's generation, because this image has no kernels for anything older than Turing. Then whether Docker handed the card over:
sudo docker compose -f /srv/invokeai/compose.yaml exec invokeai nvidia-smishould list it, or look at the Container Toolkit and thedeploysection. Also checkdeviceis not pinned tocpu. - Can I use an AMD card instead?
- Only on Linux, according to InvokeAI's hardware page, which also mentions occasional bumps with PyTorch on ROCm. The project builds
-rocmimages, and the official compose file includes a service for ROCm. The steps on this page are for NVIDIA cards.