# Glance seeds your config from a branch head, binds 8080 with no login, and caches per widget

> Glance is a single-binary Go dashboard that puts RSS, weather, market prices, container status and server stats on configurable pages. The mechanics behind the good first run are worth knowing: the recommended install pulls a tarball from another repository's main branch, the manual compose file publishes port 8080 with no authentication documented, the container's entrypoint hardcodes the config path, and cache and collapse behaviour are set per widget.

**glanceapp/glance** — A self-hosted dashboard that puts all your feeds in one place. You should then be able to run the executable and access the dashboard by visiting in your browser.

- Repository: https://github.com/glanceapp/glance
- Stars: 37,266 · Forks: 1,470
- Language: Go
- License: AGPL-3.0
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/glanceapp-glance

## The recommended install downloads a tarball from a branch head

The first installation route, which the README marks as recommended, does not download a release. It creates a directory and unpacks a tarball from the main branch of a separate template repository:

```bash
mkdir glance && cd glance && curl -sL https://github.com/glanceapp/docker-compose-template/archive/refs/heads/main.tar.gz | tar -xzf - --strip-components 2
```

That is a pleasant one-liner and it has a consequence worth naming. refs/heads/main is a branch, not a tag, so the files that land in your glance directory are whatever that branch holds at the moment you run the command, and they can change under you later. The second route has the same property, since it fetches the starting config with wget from refs/heads/main as well.

What you get is four things to edit. docker-compose.yml holds the port, the volumes and the container settings. config/home.yml holds the widgets and the layout of the home page. config/glance.yml is where the theme and any extra pages go. Two more are listed separately as optional: .env, for environment variables that become available inside the configuration files, and assets/user.css for custom CSS.

Then it is one command:

```bash
docker compose up -d
```

and if something does not come up, the README's own diagnostic step is docker compose logs.

## The manual compose file publishes 8080 and the README documents no login

The second route is the whole deployment in one file:

```yaml
services:
  glance:
    container_name: glance
    image: glanceapp/glance
    restart: unless-stopped
    volumes:
      - ./config:/app/config
    ports:
      - 8080:8080
```

Five keys, and one of them is the problem to think about. The port mapping publishes the dashboard on the host, and there is no authentication block, no environment variable for a password, no user list and no reverse proxy in the file. The README's configuration documentation, which is where the layout and every widget option is described, does not introduce a login or a user model, and the feature list has no entry for one.

So a Glance deployment is open to anyone who can reach that port. For a dashboard of feeds, weather and market prices that is often fine on a private network and wrong on anything else. The usual answer is a reverse proxy in front with your own authentication, which means Glance itself never sees the credentials and never stores a session. That is a reasonable arrangement, but it is an arrangement you assemble, not one the project provides.

The other detail in the file is the volume. Only ./config is mounted, so the dashboard's state lives entirely in the YAML you write. Nothing else is persisted, which makes a Glance install trivial to back up and trivial to lose.

## Cache, collapse and limit are set per widget, not per dashboard

The example configuration in the README is the fastest way to understand the model, because every setting in it is local to the thing it configures:

```yaml
pages:
  - name: Home
    columns:
      - size: small
        widgets:
          - type: calendar
            first-day-of-week: monday

          - type: rss
            limit: 10
            collapse-after: 3
            cache: 12h
            feeds:
              - url: https://selfh.st/rss/
                title: selfh.st
                limit: 4
              - url: https://ciechanow.ski/atom.xml
              - url: https://www.joshwcomeau.com/rss.xml
                title: Josh Comeau
              - url: https://samwho.dev/rss.xml
              - url: https://ishadeed.com/feed
```

The structure is pages, then columns, then widgets, then feeds. Three separate counters sit at three different levels: limit: 10 for the widget, limit: 4 for one feed inside it, and collapse-after: 3 for how many entries stay expanded before the rest fold away. cache: 12h is the widget's own refresh interval, and the calendar widget takes a first-day-of-week of monday.

That is the mechanism behind the one-second claim in the feature list. Pages that are cached load from what the binary already has, and the ones that are not depend on how many feeds are being fetched at once. A slow source is fixed in that one widget's block, and a widget you do not care about being current is fixed by giving it a long cache. Set the cache before you start tuning anything else.

## Ad-blocking DNS is the most common cause of a broken Glance page

The README has a common issues section and its first entry is not a Glance bug. Requests timing out, it says, is most often caused by Pi-Hole, AdGuard Home or another ad-blocking DNS service, because those have a fairly low rate limit by default, and depending on how many widgets you have on a single page that limit can very easily be exceeded. The fix given is to increase the rate limit in the DNS service's own settings.

That is worth internalising before you debug anything else. Glance fetches every feed on a page at once, so a dashboard with several RSS widgets multiplied by several feeds each is a burst of DNS lookups, and a resolver that is tuned to block ads is tuned for a different traffic shape. The symptom you will see is a page that hangs and then renders, which looks like a slow server and is not one.

The same section also flags a rarer case: if you are using Podman, a timeout can appear in some cases. The README's text on that is cut off in the copy available here, so the cause and the remedy are not something you can read in this repository, and Podman users should expect to read the docs site or the issue tracker for it.

Underneath all of this is a fair performance claim with a caveat attached: the feature list says uncached pages usually load within about a second, depending on internet speed and the number of widgets. Read that as a property of a page with a handful of widgets, not of every page you can build.

## The image entrypoint hardcodes the config path inside the container

The Dockerfile is ten lines and the last one carries the whole configuration contract:

```dockerfile
FROM golang:1.27.1-alpine3.24.1 AS builder

WORKDIR /app
COPY . /app
RUN CGO_ENABLED=0 go build .

FROM alpine:3.24.1

WORKDIR /app
COPY --from=builder /app/glance .

EXPOSE 8080/tcp
ENTRYPOINT ["/app/glance", "--config", "/app/config/glance.yml"]
```

CGO_ENABLED=0 produces a static binary, so the runtime stage is plain Alpine with one file in it and no shared library tree to manage. EXPOSE 8080 matches the port in the compose file. The entrypoint is the detail: the config path is an argument, not an environment variable, and it points at /app/config/glance.yml inside the container.

That is why the compose file mounts ./config to /app/config, and it fixes the name too. If you mount your configuration somewhere else, or rename glance.yml, the image will not find it unless you override the command or entrypoint in your compose file. The container image is not configured to read a config path from the environment, so a deployment that wants /etc/glance/glance.yml has to say so explicitly.

The binary route has the opposite default. The README says that when you run the binary it looks for a glance.yml in the directory the binary is placed in, and that a different path needs the --config option, for example /opt/glance/glance --config /etc/glance.yml. Two defaults, one in the image and one in the binary, and they disagree about where the file lives.

## Nine direct Go dependencies and no frontend build step

The claim in the feature list is few dependencies, low memory usage and minimal vanilla JavaScript, and go.mod is where you can check it. There are nine direct requirements: fsnotify for watching files, gofeed for parsing feeds, utls from refraction-networking, gopsutil for the server stats widget, gjson for reading JSON, the golang.org/x crypto, net and text modules, and gopkg.in/yaml.v3. The indirect list is short as well, and two entries in it explain behaviour you would otherwise wonder about: brotli, which is how compressed feed responses get decoded, and the plan9stats, wmi and go-ole modules, which are how server statistics are read on different platforms.

There is no package.json in the repository, so the interface ships as the binary's own output. That is what keeps a single build under 20MB across operating systems and architectures, and it is why the container is the same size as the executable.

The releases are produced with GoReleaser, given the .goreleaser.yaml at the top level and a separate Dockerfile.goreleaser for the published image, which is why the downloads are per-platform archives. The README names the Windows file explicitly, saying that on a 64-bit system the one you want is most likely called glance-windows-amd64.zip. Precompiled binaries cover Linux, Windows and macOS on x86, x86_64, ARM and ARM64.

The Windows instructions also differ in a way that matters. The executable goes in a folder of choice, glance.yml goes in the same folder, and --config is not mentioned for that platform. On Windows the configuration is next to the binary, full stop.

## Fifteen months between 0.8.4 and 0.8.5, and a Nix package on the unstable channel

The release record is irregular in a way that should shape your upgrade planning. v0.8.4 was tagged 2025-06-10, v0.8.5 on 2026-05-30, and v0.8.6 on 2026-09-03. Fifteen months, then three months. The repository's last push was on 2026-09-05, two days after the v0.8.6 tag, so the tree is barely ahead of the newest release and the project is not archived.

There is no fixed cadence to plan against here, which means a Glance upgrade is a decision you make when you read the release notes, not a monthly chore. For a dashboard, that is a reasonable trade, and it is also the argument for pinning a version rather than tracking a container tag that can move under you.

The third-party channels add a second variable. The README lists a Proxmox VE Helper Script, a NixOS package, Hostinger and Coolify under a heading that says the following 3rd party channels, so the count in the prose is one short of the list. The NixOS package is the interesting one, because the link points at the unstable channel, which means the version you get is the one nixpkgs-unstable has picked up rather than the one Glance tagged. On Nix, upgrade timing belongs to the channel.

So there are three upgrade clocks in this project: Glance's own tags, the template repository's main branch that seeds your config directory, and whatever channel a distribution package tracks. Only the first one is a release.

## Conclusion

Adopt Glance if you want a read-only dashboard on a machine you already run, configured from one YAML file per page, and you are willing to put your own access control in front of it. Do not adopt it expecting authentication or multi-user state, because nothing in the configuration documentation describes a login or a user model, and the shipped compose file publishes the port directly. Verify first by pinning the docker-compose-template to a commit rather than its main branch, and by reading which widgets you actually need against the DNS rate limit described in the common issues section.

## FAQ

### How do I install the Glance dashboard?

The recommended route creates a directory and unpacks a template tarball from the docker-compose-template repository, then you edit docker-compose.yml, config/home.yml and config/glance.yml and run docker compose up -d. The manual route is a compose file with image glanceapp/glance, a ./config volume and 8080:8080, plus a downloaded config/glance.yml.

### How do I install Glance from a binary?

Precompiled binaries are published for Linux, Windows and macOS on x86, x86_64, ARM and ARM64. On Linux the binary looks for a glance.yml in the directory it sits in, and a different path needs the --config option, for example /opt/glance/glance --config /etc/glance.yml.

### How do I use the Glance app?

Configuration is YAML: pages contain columns, columns contain widgets, and each widget has its own options. The shipped example sets limit, collapse-after and a cache of 12h on an RSS widget, and a per-feed limit below it, and the widget list covers RSS, subreddit posts, Hacker News, weather, YouTube, Twitch, market prices, Docker container status and server stats.

### How do I use Glance for widgets and pages?

You add as many pages and tabs as you need, size the columns, choose a widget type per block, and set the options for that widget, including multiple styles where a widget offers them and custom CSS through assets/user.css. Themes are separate, documented in docs/themes.md, and preconfigured pages in docs/preconfigured-pages.md.

## Sources

- [Official README](https://github.com/glanceapp/glance#readme)
- [Project repository](https://github.com/glanceapp/glance)
- [Release notes](https://github.com/glanceapp/glance/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/glanceapp-glance
