If you've ever wanted to poke around your own data — homelab metrics, a Nextcloud database, a spreadsheet you dumped into Postgres, whatever — without writing SQL every time, Metabase is worth ten minutes of your evening. It's a self-hosted dashboard tool that lets you point-and-click your way to charts and questions, and it runs just fine on a small LXC container in Proxmox VE.

This guide walks through building a dedicated Debian 12 container, installing the Java runtime Metabase actually needs (not an old one you happen to have lying around), and getting the app running as a proper systemd service instead of a screen session you'll forget about in a week.

What You Will Learn

  • What Metabase is and where it fits next to tools like Grafana
  • How to create a Debian 12 LXC container sized correctly for a JVM app
  • How to install Eclipse Temurin's Java runtime the supported way
  • How to run Metabase as a systemd service that survives reboots
  • How to fix the errors that actually show up during setup

What Is This Feature?

Metabase is an open-source business intelligence tool. You connect it to a database — MySQL, Postgres, SQLite, even a CSV upload — and it lets you build charts, tables, and dashboards through a web UI, no SQL required (though you can drop into a SQL editor if you want to). It's written in Java and ships as a single JAR file, which is unusually easy to deal with compared to most self-hosted apps.

An LXC container, in case you're new to Proxmox, is a lightweight form of virtualization that shares the host's kernel instead of emulating a whole virtual machine. That means it boots in a couple of seconds, uses less RAM than a comparable VM, and is the default choice on Proxmox for anything that doesn't need its own kernel — which covers almost every self-hosted web app, Metabase included.

You'll also see the term JVM (Java Virtual Machine) a few times here. It's the runtime that executes Java bytecode. Metabase needs a specific, current JVM to start at all — more on that in a minute, because it's the single most common reason this install goes sideways.

Why Would You Use It?

Grafana is great at time-series metrics — CPU graphs, temperature over time, that sort of thing. Metabase is built for a different job: ad-hoc questions against relational data. "How many orders did we get last month by region?" "Which of my Sonarr downloads failed the most?" "What's the average ticket resolution time?" That's Metabase's territory.

Small business owners use it to build sales and inventory dashboards without hiring a data analyst. Developers use it to poke at an app's Postgres database during debugging. Homelab users point it at whatever database backs their self-hosted apps, just to see what's actually happening under the hood. None of that needs an enterprise BI stack — it needs a JAR file and a place to run it, which a Proxmox LXC container handles well.

Prerequisites

Before you start, make sure you have:

  • A working Proxmox VE 8.x or 9.x host with a bit of free storage
  • A Debian 12 (bookworm) LXC template downloaded, or internet access to fetch one
  • At least 2 CPU cores and 4 GB of RAM free on the host to allocate to the container — Metabase is a JVM app and it's noticeably happier with 4 GB than with 2
  • Basic comfort with the Linux command line — every command below is explained, but you should know how to get a shell open
  • Root or an account with permission to run pct commands on the Proxmox shell

You don't need a separate database server to follow along. Metabase ships with an embedded H2 database for its own configuration, and that's fine for a homelab or small-team setup. If you're planning to run this for a business with real usage, swap in Postgres later — I'll mention where that decision point is, but it's outside the scope of a beginner guide.

Step-by-Step Tutorial

1. Download the Debian 12 template

From the Proxmox shell (or the node's Shell button in the web UI), refresh the template list and grab Debian 12 if you don't already have it:

pveam update
pveam available --section system | grep debian-12
pveam download local debian-12-standard_12.7-1_amd64.tar.zst

The exact filename changes as Debian point releases roll out, so copy whatever version the pveam available command actually lists rather than typing the one above blind.

2. Create the container

pct create 210 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
  --hostname metabase \
  --cores 2 \
  --memory 4096 \
  --swap 512 \
  --rootfs local-lvm:8 \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
  --unprivileged 1 \
  --features nesting=1

Adjust the VMID (210), storage names, and bridge to match your own setup — if you're not sure what storage you have, run pvesm status first. An unprivileged container is the right default for a web app like this; there's no reason to give it root-equivalent access to the host.

3. Start it and open a console

pct start 210
pct enter 210

pct enter drops you straight into a root shell inside the container without needing SSH keys set up first, which is convenient for a fresh build.

4. Update the base system

apt update && apt full-upgrade -y
apt install -y curl gnupg ca-certificates

A brand-new Debian template is usually a few weeks or months out of date depending on when the image was built, so don't skip the upgrade — you want current TLS certificates before you start pulling packages from a third-party repository in the next step.

5. Install a Java 25 runtime from Eclipse Temurin

This is the step people skip and then wonder why Metabase won't start. Metabase recommends Java 25 from Eclipse Temurin specifically, and older JREs aren't supported. Debian 12's own repositories only ship Java 17, so you need Adoptium's repo:

wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null
echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print $2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
apt update
apt install -y temurin-25-jre

Confirm it worked:

java -version

You should see something referencing OpenJDK 25 and Temurin in the output. If you see 17 instead, the JRE you just installed didn't win the fight over your PATH — check with update-alternatives --config java.

6. Create a dedicated system user

Running Metabase as root works, but it's a bad habit. Give it its own unprivileged account:

useradd -r -m -d /opt/metabase -s /usr/sbin/nologin metabase

7. Download the Metabase JAR

cd /opt/metabase
wget https://downloads.metabase.com/latest/metabase.jar
chown -R metabase:metabase /opt/metabase

That's the whole app — one file, a bit under 200 MB. No installer, no dependency hell beyond the JRE you already sorted out.

8. Create a systemd service

Running java -jar metabase.jar directly works for testing, but it dies the moment you close your terminal. Create /etc/systemd/system/metabase.service:

[Unit]
Description=Metabase
After=network.target

[Service]
Type=simple
User=metabase
WorkingDirectory=/opt/metabase
ExecStart=/usr/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar /opt/metabase/metabase.jar
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Then enable and start it:

systemctl daemon-reload
systemctl enable --now metabase

9. Watch it come up

journalctl -u metabase -f

First boot is the slowest one — give it 30 to 90 seconds on modest hardware while it initializes its internal H2 database and Jetty web server. You're looking for a line that says something like Metabase Initialization COMPLETE.

10. Finish setup in the browser

Once it's up, open http://<container-ip>:3000/setup from another machine on your network. You'll create an admin account, optionally connect a database (or skip that and add one later from the admin panel), and land on an empty dashboard, ready to go.

Commands Explained

CommandWhat it does
pveam downloadDownloads a container template from the configured Proxmox template repository onto local storage
pct createBuilds a new LXC container from a template with the CPU, memory, network, and storage settings you specify
pct enterOpens an interactive root shell inside a running container, without needing SSH
useradd -rCreates a system account (no login shell, no password) meant to run a service rather than a human user
update-alternatives --config javaLets you choose which installed Java version /usr/bin/java actually points to when more than one is present
systemctl enable --nowEnables a service to start on boot and starts it immediately in the same command
journalctl -u metabase -fTails the live systemd logs for the metabase service, so you can watch startup or catch an error as it happens

Common Errors

"Unsupported major.minor version" or the service exits instantly. This is almost always the wrong Java version. Run java -version and confirm it reports Temurin 25, not the Debian-packaged 17. Fix it with update-alternatives --config java if both are installed.

The container has no IP address. If you set ip=dhcp and your network doesn't have a DHCP server reachable from the bridge, the container comes up with nothing. Either configure a static IP in the pct create command with something like ip=192.168.1.50/24,gw=192.168.1.1, or check that vmbr0 is actually bridged to a NIC that reaches your router.

Port 3000 refuses connections from other machines. Metabase binds to all interfaces by default, so this is usually a firewall issue rather than a Metabase one. Check pve-firewall settings on the container and datacenter level if you've enabled the Proxmox firewall, and confirm nothing on your router is blocking that subnet.

Out of memory / the container feels sluggish under load. 4 GB is comfortable for one or two users poking around. If you add more data sources and more concurrent dashboard viewers, bump --memory up via pct set 210 --memory 8192 and reboot the container.

Troubleshooting

Start with the logs — journalctl -u metabase -n 100 --no-pager shows the last hundred lines without following live, which is easier to read through than a scrolling feed. Most startup failures show a Java stack trace right at the point where things went wrong, and the exception name usually tells you what to search for.

If Metabase starts but the web UI hangs on a blank page, check that you're hitting the right port and that nothing else in the container is already bound to 3000 with ss -tlnp. It's rare, but if you experimented with running the JAR manually earlier and forgot to kill that process, you'll get a port conflict with the systemd-managed instance.

If the container itself won't start at all, check the host side with pct status 210 and cat /var/log/pve/tasks/active — an unprivileged container occasionally fails to start after a Proxmox kernel update if nesting or storage permissions got reset. Re-running the pct set command with the same feature flags usually clears it.

Best Practices

Snapshot the container right after the first successful login, before you start connecting real data sources. It costs you thirty seconds and saves you from redoing this whole install if a database connection you add later corrupts the app's internal H2 store.

Don't expose port 3000 directly to the internet. If you want remote access, put it behind a reverse proxy with TLS — Nginx Proxy Manager or Caddy both work fine — and consider putting it behind a VPN like WireGuard or Tailscale instead if it's only ever going to be you and a couple of coworkers looking at it.

Move off the embedded H2 database once more than one or two people rely on this. It's fine for evaluation and small personal use, but H2 doesn't handle concurrent writes as gracefully as a real database, and Metabase's own docs are honest about that. Point MB_DB_TYPE at a Postgres instance when you're ready — that's an environment variable you set before starting the service, not a UI toggle.

Back up /opt/metabase along with your regular container backup schedule. If you're using the embedded database, that directory is the entire application state — questions, dashboards, saved connections, everything.

Frequently Asked Questions

Do I need Docker to run Metabase on Proxmox?

No. The JAR-plus-systemd approach in this guide avoids Docker entirely, which keeps the container lighter. If you'd rather use Docker, Metabase publishes an official image, but you'd need to install Docker inside the LXC container first, which adds overhead this guide intentionally skips.

Can I run Metabase in a VM instead of an LXC container?

Sure, and if you're passing through specific hardware or want stronger isolation, that's a reasonable call. For a single web app with no special hardware needs, though, an LXC container uses less RAM and starts faster, which is why it's the better default here.

How much RAM does Metabase actually need?

2 GB will technically boot it. 4 GB is where it stops feeling tight for a couple of users and a handful of connected databases. If you're running dashboards with heavy queries against a large dataset, plan for more.

Why Java 25 specifically?

Metabase's own compatibility documentation states that recent releases require it and that older JRE versions aren't supported. Trying to run it on Java 17 or 21 will typically fail outright rather than run with reduced functionality.

Is the free version good enough, or do I need Metabase Pro?

The open-source edition covers everything in this guide — dashboards, questions, alerts, and connecting to most common databases. Pro adds things like SSO, more granular permissions, and audit logs, which matter for larger teams but aren't necessary for a homelab or small business setup.

Conclusion

You've now got a dedicated, isolated container running a real BI tool, started the right way with systemd instead of a terminal you have to keep open. From here, the next move is usually connecting it to whatever database already backs one of your other self-hosted apps and building your first dashboard — that's genuinely the fun part, and it's a lot less intimidating once the install itself is out of the way.

If you outgrow the embedded database or want this reachable outside your LAN, come back to the Best Practices section above before you open anything up — a few minutes of reverse proxy setup now saves a headache later.