Back to Article List

Grafana default port 3000 and how to change it

Grafana default port 3000 and how to change it

If Grafana won't start and the journal says the address is already in use, you're in the common case for this article. Something else on the box reached the Grafana port before Grafana did, and on a machine that has ever run a Node or React dev server that something is usually still running. Moving Grafana off 3000 is one config key on a package install. Docker is the part that needs more thought, because two different ports are in play there.

Where the default port 3000 comes from

The value is set in conf/defaults.ini under the [server] section:

[server]
http_port = 3000

The configuration reference describes it as "The port to bind to, defaults to 3000." Grafana also binds all interfaces by default, because http_addr is empty and an empty value means 0.0.0.0.

Why 3000 in particular is a bit of trivia. The number came out of the Rails and later Node worlds as a convention for a development port, high enough to need no root and short enough to type, and a lot of tools inherited it without anyone deciding anything. That is also why it collides so often. Every dev server on the machine picked the same number for the same reason.

Change the port in grafana.ini

Edit /etc/grafana/grafana.ini if you followed the standard route for installing Grafana on an Ubuntu VPS, or conf/custom.ini on a tarball install. Find the [server] section and set the port:

[server]
http_port = 8080

Delete the leading semicolon if there is one. Every setting in the shipped file is commented out, and a semicolon at the start of an INI line makes Grafana ignore it entirely.

sudo systemctl restart grafana-server
ss -tlnp | grep 8080

The service name keeps its hyphen even though the CLI commands dropped theirs, so systemctl restart grafana-server is correct on current releases.

Change the port with the GF_SERVER_HTTP_PORT environment variable

Any Grafana setting can be supplied as GF_<SECTION>_<KEY>, uppercased. For the port that's GF_SERVER_HTTP_PORT. Environment variables sit above the config file in Grafana's precedence order, so this wins over whatever grafana.ini says.

On a systemd install, put it in a drop-in and leave the packaged unit alone:

sudo systemctl edit grafana-server.service
[Service]
Environment="GF_SERVER_HTTP_PORT=8080"

Then sudo systemctl daemon-reload && sudo systemctl restart grafana-server.

Change the port in Docker

Two ports, and they are independent of each other. The container port is what Grafana binds inside its own network namespace. The host port is what you map that to from outside.

docker run -d --name=grafana -p 8080:3000 grafana/grafana

That leaves Grafana on 3000 inside the container and publishes it as 8080 on the host. Nothing about Grafana's config changes, and root_url is the only thing that needs to know about the new number. This is what you want almost every time.

The other option changes the port Grafana itself binds:

docker run -d --name=grafana -e GF_SERVER_HTTP_PORT=8080 -p 8080:8080 grafana/grafana

Note both halves of -p changed. Set the environment variable but leave -p 3000:3000 in place and you get a container that starts fine, publishes a port nothing is listening on and answers connection refused. In compose form:

services:
  grafana:
    image: grafana/grafana
    ports:
      - "8080:3000"

Remap on the host and leave the inside alone. The Grafana Docker Compose guide goes through the rest of that file. Volumes and provisioning are the two parts to read before you commit to a layout.

http_addr, protocol, domain and root_url

Four [server] keys travel together, and getting them wrong produces symptoms that look nothing like a port problem.

KeyWhat it does
http_addrThe interface to listen on. Empty means all interfaces. Set 127.0.0.1 to accept only local connections.
protocolhttp, https, h2, socket or socket_h2. Set https only if Grafana terminates TLS itself.
domainThe hostname Grafana is reached on. Used as part of root_url.
root_urlThe full public URL Grafana believes it lives at.

Binding to loopback is the move once nginx or Caddy is in front:

[server]
http_addr = 127.0.0.1
http_port = 3000

Now the only way in is through the proxy, no matter what the firewall does. Confirm it with ss -tlnp, where the listen address should read 127.0.0.1:3000 rather than *:3000.

root_url matters because Grafana builds redirects, OAuth callbacks and share links from it rather than from the incoming Host header. Behind a proxy on a real hostname:

[server]
domain = grafana.example.com
root_url = https://grafana.example.com/

On a subpath you need one more key, because Grafana has to strip the prefix from its own routes:

[server]
root_url = https://example.com/grafana/
serve_from_sub_path = true

Leave serve_from_sub_path off with a subpath root_url and the page loads its HTML but 404s every CSS and JS file, which a user experiences as a blank white screen. The common Grafana errors guide files that symptom under the blank screen heading, since almost nobody arrives at it thinking about ports. Set both keys together and it doesn't come up.

Run Grafana on a port below 1024

Putting Grafana straight on 80 or 443 is not a one-line change. The service runs as the unprivileged grafana user, and the packaged unit ships with CapabilityBoundingSet= set to nothing at all, which strips every capability including the one that permits binding low ports.

Grafana documents the override. Create it with sudo systemctl edit grafana-server.service and add:

[Service]
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
PrivateUsers=false

All three lines are needed. The start and restart documentation notes that a private user cannot hold process capabilities on the host's user namespace, so CAP_NET_BIND_SERVICE has no effect while PrivateUsers is on. Reload and restart afterwards.

Why all three are needed together is something I have never fully worked out. On a plain Debian box with a hand-written unit, AmbientCapabilities on its own is enough to bind 80. With the packaged Grafana unit it isn't, and I've read that unit more than once without finding the directive that cancels it out.

I'd skip all of that anyway. Put nginx on 443 and keep Grafana on 3000 bound to loopback. Certificate renewal and HTTP to HTTPS redirects then come free from a thing that already does them well, with somewhere to hang rate limiting when you need it. The capability override earns its place when Grafana is genuinely the only service on the box and you want one fewer moving part.

Find what else is holding port 3000

When Grafana refuses to start with an address-already-in-use error, find the owner:

sudo ss -tlnp | grep 3000

The users:(("name",pid=NNNN,...)) field at the end names the process. On developer boxes it's usually a Node app or a stray container, and docker ps --format '{{.Names}}\t{{.Ports}}' confirms the container case. Then move one of the two. If it's a container you started and forgot about, docker stop is quicker than moving anything.

Allow or block port 3000 in ufw

A default Grafana bind means the login page is reachable from anywhere the moment the service starts. Restrict it to your own address while you're setting up:

sudo ufw allow from YOUR_IP to any port 3000 proto tcp
sudo ufw status numbered

Once a reverse proxy is in place, drop the rule and let 443 be the only open port:

sudo ufw delete allow 3000/tcp

Combining that with http_addr = 127.0.0.1 gives you two independent barriers, so a mistyped firewall rule later doesn't quietly expose the login page. On a fresh install that page still has the well-known Grafana default login behind it, which is the whole reason to bother. Do the loopback bind first, because it holds even with ufw switched off.

Other default ports in a Grafana stack

Half the port questions in a monitoring stack turn out to be about Grafana's neighbours. These are the defaults you'll be reconciling.

ServiceDefault portConfig key
Grafana3000[server] http_port
Prometheus9090--web.listen-address
Alertmanager9093--web.listen-address
Node Exporter9100--web.listen-address
Loki3100server.http_listen_port
Promtail9080server.http_listen_port

Loki on 3100 sitting next to Grafana on 3000 is the pairing that gets fat-fingered most, and the error it produces is a data source that saves without complaint and returns nothing. When you wire Prometheus in, the URL Grafana needs is the Prometheus address on 9090, and the Prometheus data source and dashboard setup walks through that connection. After any port change, run ss -tlnp | grep grafana and read the listen address back before you go near the nginx config. If you're putting the whole stack together, start from the complete Grafana guide.

Your idea deserves better hosting

24/7 support 30-day money-back guarantee Cancel anytime
Ciclo de Pagamento

VPS.S1

$5.99 Save  17 %
$4.99 por mês
  • 2 vCPU AMD EPYC
  • 2 GB RAMMEMÓRIA
  • 30 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos

VPS.S3

$14.99 Save  33 %
$9.99 por mês
  • 4 vCPU AMD EPYC
  • 6 GB RAMMEMÓRIA
  • 70 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O

EPYC VPS.P1

$8.99 Save  22 %
$6.99 por mês
  • 2 vCPU AMD EPYC
  • 4 GB RAMMEMÓRIA
  • 40 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

EPYC VPS.P2

$16.99 Save  24 %
$12.99 por mês
  • 2 vCPU AMD EPYC
  • 8 GB RAMMEMÓRIA
  • 80 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

EPYC VPS.P4

$29.99 Save  23 %
$22.99 por mês
  • 4 vCPU AMD EPYC
  • 16 GB RAMMEMÓRIA
  • 160 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

EPYC VPS.P5

$39.99 Save  25 %
$29.99 por mês
  • 8 vCPU AMD EPYC
  • 16 GB RAMMEMÓRIA
  • 180 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

EPYC VPS.P6

$59.99 Save  25 %
$44.99 por mês
  • 8 vCPU AMD EPYC
  • 32 GB RAMMEMÓRIA
  • 200 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

EPYC VPS.P7

$69.99 Save  29 %
$49.99 por mês
  • 16 vCPU AMD EPYC
  • 32 GB RAMMEMÓRIA
  • 240 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

Genoa VPS.G2

$24.99 Save  20 %
$19.99 por mês
  • 2 vCPUAMD EPYC Genoa 4ª geração 9xx4 com 3,25 GHz ou similar, na arquitetura Zen 4. AMD EPYC G4
  • 4 GB DDR5MEMÓRIA
  • 50 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

Genoa VPS.G4

$44.99 Save  22 %
$34.99 por mês
  • 4 vCPUProcessador AMD EPYC com núcleos vCPU dedicados, em hardware de servidor empresarial. AMD EPYC G4
  • 8 GB DDR5MEMÓRIA
  • 100 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

Genoa VPS.G6

$89.99 Save  22 %
$69.99 por mês
  • 8 vCPUProcessador AMD EPYC com núcleos vCPU dedicados, em hardware de servidor empresarial. AMD EPYC G4
  • 16 GB DDR5MEMÓRIA
  • 200 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

Genoa VPS.G7

$159.99 Save  22 %
$124.99 por mês
  • 8 vCPUProcessador AMD EPYC com núcleos vCPU dedicados, em hardware de servidor empresarial. AMD EPYC G4
  • 32 GB DDR5MEMÓRIA
  • 250 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6O suporte a IPv6 está indisponível no momento na França, Finlândia ou Países Baixos. incluídos
  • Backup automático grátisInclui um espaço de backup que você pode configurar para diário, semanal ou mensal.

AMD Ryzen VPS.R1

$16.99 Save  18 %
$13.99 por mês
  • 1 CPU dedicada AMD Ryzen 9 7950X com 4,5 GHz ou similar, na arquitetura Zen 4. vCPU
  • 4 GB DDR5MEMÓRIA
  • 50 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6 incluídos O suporte a IPv6 está indisponível no momento na França, Finlândia ou nos Países Baixos.
  • Backup automático incluso

AMD Ryzen VPS.R2

$29.99 Save  17 %
$24.99 por mês
  • 2 CPUs dedicadas AMD Ryzen 9 7950X com 4,5 GHz ou similar, na arquitetura Zen 4. vCPU
  • 8 GB DDR5MEMÓRIA
  • 100 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6 incluídos O suporte a IPv6 está indisponível no momento na França, Finlândia ou nos Países Baixos.
  • Backup automático incluso

AMD Ryzen VPS.R4

$109.99 Save  18 %
$89.99 por mês
  • 8 CPUs dedicadas AMD Ryzen 9 7950X com 4,5 GHz ou similar, na arquitetura Zen 4. vCPU
  • 32 GB DDR5MEMÓRIA
  • 400 GB NVMeDISCO
  • Banda ilimitada
  • IPv4 & IPv6 incluídos O suporte a IPv6 está indisponível no momento na França, Finlândia ou nos Países Baixos.
  • Backup automático incluso

FAQ

Can I run two Grafana instances on the same server?

Yes, as long as each has its own port and its own data directory. On a package install that means a copied unit file with a different CONF_FILE and DATA_DIR in its environment file. Containers make it easier. Each one gets its own namespace and you only pick different host ports.