시스템

Docker Homepage으로 나만의 서비스 대시보드 구성하기

달빛궁전- 2026. 7. 21. 16:21

여러 서버와 사이드 프로젝트의 접속 주소를 한곳에서 관리하기 위해 Homepage를 Docker로 설치하고, Nginx Reverse Proxy와 Basic Authentication을 적용하여 외부에서도 안전하게 접근할 수 있도록 구성하였습니다.

홈 서버와 개인 프로젝트를 운영하다 보면 접속해야 할 주소가 계속 늘어납니다.

Portainer, Grafana, Proxmox VE 같은 인프라 관리 도구부터 Home Assistant, Synology NAS, n8n, Jupyter Notebook, 직접 만든 사이드 프로젝트까지 각각의 URL을 기억하거나 브라우저 즐겨찾기에서 찾는 것이 점점 불편해졌습니다.

이를 한 화면에 정리하기 위해 오픈소스 애플리케이션 대시보드인 Homepage를 설치하였습니다.

구성한 대시보드 주소:
https://home.seonggi.kr/

현재는 개인 관리 서비스가 포함되어 있어 Nginx Basic Authentication을 적용하였습니다.

Homepage란?

Homepage는 Docker와 다양한 서비스 API 연동을 지원하는 오픈소스 애플리케이션 대시보드입니다.

YAML 파일만으로 서비스, 북마크, 위젯, 레이아웃을 설정할 수 있고 다음과 같은 기능을 제공합니다.

  • Docker 컨테이너 상태 및 리소스 확인
  • 100개 이상의 서비스 위젯 연동
  • 날짜, 시간, 날씨, 검색 등의 정보 위젯
  • 서비스와 웹 북마크 그룹화
  • 테마, 색상, 레이아웃, Custom CSS/JS 설정
  • AMD64, ARM64 아키텍처 지원

공식 Docker 이미지:
https://hub.docker.com/r/gethomepage/homepage

 

gethomepage/homepage - Docker Image

A modern, fully static, fast, secure fully proxied, highly customizable application dashboard with integrations for over 100 services and translations into multiple languages. Easily configured via YAML files or through docker label discovery. Homepage bui

hub.docker.com

 

공식 문서:
https://gethomepage.dev/

 

Home - Homepage

 

gethomepage.dev

 

구성 목표

이번 구성의 목표는 다음과 같습니다.

  1. 여러 서비스의 URL을 역할별로 한 화면에 정리
  2. Docker Compose로 간단하게 배포 및 재시작
  3. 로컬 시스템의 CPU, 메모리, 디스크 사용량 표시
  4. home.seonggi.kr 도메인으로 외부 접속
  5. 외부 노출 시 인증 없이 관리 화면이 공개되지 않도록 보호

전체 흐름은 아래와 같습니다.

디렉터리 구성

Homepage 접속 흐름

Homepage 자체에는 사용자 인증 기능이 없습니다. 따라서 인터넷에서 접근할 수 있게 구성할 경우 Reverse Proxy 또는 VPN에서 인증, TLS, Host Header 검증을 적용해야 합니다.

디렉터리 구성

  • homepage-docker
    • docker-compose.yml
    • nginx.conf
    • .htpasswd
    • config
      • settings.yaml
      • services.yaml
      • widgets.yaml
      • bookmarks.yaml
      • docker.yaml
      • custom.css
      • custom.js

설정 파일은 컨테이너 외부에 두어 이미지를 업데이트하거나 컨테이너를 다시 생성해도 그대로 유지되도록 구성하였습니다.

Docker Compose 설정

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    environment:
      # CHANGE_ME: 실제 접속할 도메인과 로컬 포트를 입력
      - HOMEPAGE_ALLOWED_HOSTS=localhost,localhost:7799,127.0.0.1:7799,home.example.com,homepage
    volumes:
      - ./config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # CHANGE_ME: 리소스 위젯에서 확인할 호스트 경로
      # macOS 예시: /Users/myname:/host:ro
      # Linux 예시: /:/host:ro
      - /Users/CHANGE_ME:/host:ro
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    container_name: homepage-auth
    ports:
      # CHANGE_ME: 7799를 이미 사용 중이라면 다른 포트로 변경
      - "7799:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./.htpasswd:/etc/nginx/.htpasswd:ro
    depends_on:
      - homepage
    restart: unless-stopped

위 예제에서 사용자가 변경해야 하는 값은 다음과 같습니다.

  • home.example.com: Homepage에 사용할 실제 도메인
  • 7799: 호스트에서 사용할 포트. 다른 서비스와 중복되면 변경
  • /Users/CHANGE_ME: 리소스 사용량을 확인할 호스트 경로
  • container_name: 기존 컨테이너 이름과 중복되지 않도록 필요 시 변경
  • ./config: Homepage YAML 설정 파일을 저장할 로컬 디렉터리

도메인을 사용하지 않고 내부에서만 접속한다면 HOMEPAGE_ALLOWED_HOSTS에 실제로 사용하는 IP와 포트를 입력합니다.

environment:
  # 내부 IP가 192.168.0.10인 경우
  - HOMEPAGE_ALLOWED_HOSTS=192.168.0.10,192.168.0.10:7799,localhost:7799,homepage

Homepage의 3000번 포트를 호스트에 직접 공개하지 않고, Nginx 컨테이너를 통해서만 접근하도록 하였습니다.

/var/run/docker.sock은 Docker 연동에 필요하며 읽기 전용(:ro)으로 마운트하였습니다. 호스트 디스크 사용량을 표시하기 위한 경로도 읽기 전용으로 연결하였습니다.

Docker Socket은 Docker 데몬에 접근할 수 있는 민감한 리소스입니다. 필요한 경우에만 마운트하고, 외부에 공개되는 서비스와 권한 범위를 최소화하는 것이 좋습니다.

 

Nginx Basic Authentication 설정

Homepage는 자체 로그인 기능을 제공하지 않으므로 Nginx에서 Basic Authentication을 적용하였습니다.

server {
    listen 80;
    server_name localhost;

    location / {
        auth_basic "Dashboard Login Required";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_pass http://homepage:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

인증 파일은 htpasswd 명령으로 생성합니다.

htpasswd -c .htpasswd CHANGE_ME_USERNAME

CHANGE_ME_USERNAME에는 대시보드에 로그인할 사용자명을 입력합니다. 명령 실행 후 표시되는 프롬프트에서 비밀번호를 입력하면 됩니다.

비밀번호는 Compose 파일이나 Nginx 설정에 직접 기록하지 않고 .htpasswd 파일로 분리하였습니다. 해당 파일은 Git 저장소에 업로드하지 않도록 .gitignore에도 추가하는 것이 좋습니다.

Homepage 기본 설정

config/settings.yaml에서 제목과 테마를 설정합니다.

title: CHANGE_ME_DASHBOARD_TITLE  # 화면 상단에 표시할 제목
theme: dark
color: zinc
cardBlur: sm

어두운 테마와 zinc 색상을 사용하여 서비스 카드가 한눈에 들어오도록 구성하였습니다.
실제 구성 화면은 아래와 같습니다.

서비스 그룹 구성

config/services.yaml에서 접속할 서비스를 역할별로 분류하였습니다.

  • 로컬 웹 서비스: 직접 만든 웹 서비스와 사이드 프로젝트
  • 개발 및 자동화: n8n, AI Migration, Jupyter Notebook 등
  • 시스템 관리 및 모니터링: Portainer, Grafana, Proxmox VE, Nginx Proxy Manager, Netdata 등
  • 네트워크 및 홈 서버: Synology NAS, Home Assistant, Router Web 등

설정 형식은 아래와 같습니다.

- 시스템 관리 및 모니터링:
    - Portainer:
        icon: portainer
        href: https://CHANGE_ME_PORTAINER_URL
        description: 컨테이너 관리
    - Proxmox VE:
        icon: proxmox
        href: https://CHANGE_ME_PROXMOX_URL
        description: 가상화 시스템 하이퍼바이저

href에는 각 사용자가 운영하는 서비스의 실제 URL을 입력합니다. 공개 도메인이 없다면 http://192.168.0.10:9000과 같은 내부 IP 주소도 사용할 수 있습니다.

서비스 아이콘은 Homepage에서 지원하는 이름을 사용합니다. 아이콘을 찾을 수 없으면 우선 icon 항목을 생략하고 정상적으로 카드가 표시되는지 확인하는 것이 좋습니다.

서비스를 그룹으로 나누니 즐겨찾기 목록보다 찾기 쉽고, 새 서비스가 추가되어도 YAML 항목 하나만 추가하면 됩니다.

시스템 리소스 위젯 설정

날짜와 시간, 호스트의 CPU, 메모리, 디스크 사용량을 상단에서 확인하도록 설정하였습니다.

- datetime:
    format:
      dateStyle: short
      timeStyle: short
    hourCycle: h23

- resources:
    cpu: true
    memory: true
    disk: /host  # Compose에서 마운트한 컨테이너 내부 경로
    expanded: true

호스트 디스크는 Compose에서 호스트 경로:/host:ro로 연결한 경로를 기준으로 표시합니다. disk에는 호스트의 원래 경로가 아니라 컨테이너 내부 마운트 경로인 /host를 입력합니다.

실행

설정 파일을 작성한 후 다음 명령으로 실행합니다.

docker compose up -d

컨테이너 상태와 로그를 확인합니다.

docker compose ps
docker compose logs -f homepage
docker compose logs -f nginx

로컬에서는 아래 주소로 접속합니다.

http://localhost:7799

외부 Reverse Proxy에서는 home.seonggi.kr 요청을 이 주소로 전달하고 HTTPS 인증서를 적용하였습니다.

사용자 환경에서는 아래 항목을 자신의 값으로 설정하면 됩니다.

  • 도메인: home.example.com → 실제 사용할 도메인
  • Forward Host 또는 IP: Homepage를 설치한 서버의 IP
  • Forward Port: Compose에서 Nginx에 연결한 포트. 예제에서는 7799
  • SSL: 실제 도메인 인증서 적용
  • WebSocket: 사용하는 Reverse Proxy 제품에서 지원한다면 활성화

설치 중 발생한 문제

Host validation failed

외부 도메인과 로컬 포트로 접속하는 과정에서 다음 오류가 발생하였습니다.

Host validation failed for: home.seonggi.kr
Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.

Homepage는 허용되지 않은 Host Header 요청을 차단합니다. Compose의 HOMEPAGE_ALLOWED_HOSTS에 실제 접속에 사용하는 호스트와 포트를 추가하여 해결하였습니다.

environment:
  - HOMEPAGE_ALLOWED_HOSTS=localhost,localhost:7799,127.0.0.1,127.0.0.1:7799,home.seonggi.kr,homepage

설정 변경 후 컨테이너를 다시 생성합니다.

docker compose up -d --force-recreate

HOMEPAGE_ALLOWED_HOSTS는 인증 기능이 아니라 Host Header 검증 기능입니다. 외부 접근 보호를 위해서는 별도로 Basic Authentication, SSO 또는 VPN을 구성해야 합니다.

보안 구성 시 확인할 점

  • Homepage의 3000번 포트를 외부에 직접 공개하지 않음
  • Reverse Proxy에서 HTTPS 적용
  • Nginx Basic Authentication 또는 별도의 SSO 적용
  • 실제 사용하는 도메인만 HOMEPAGE_ALLOWED_HOSTS에 등록
  • Docker Socket과 호스트 볼륨은 읽기 전용으로 마운트
  • .htpasswd와 API Key가 포함된 설정 파일은 Git에 업로드하지 않음
  • 관리자 서비스 URL이 노출되는 범위를 최소화

현재 https://home.seonggi.kr/에 인증 없이 접근하면 401 Authorization Required가 반환되는 것을 확인할 수 있습니다.

정리

서비스가 몇 개 없을 때는 브라우저 즐겨찾기만으로도 충분했지만, 홈 서버와 사이드 프로젝트가 늘어나면서 하나의 시작 화면이 필요해졌습니다.

Homepage를 사용하면 YAML 파일만으로 서비스 주소를 역할별로 정리할 수 있고, Docker 및 시스템 리소스 정보도 함께 확인할 수 있습니다. Docker Compose로 구성하여 업데이트와 재배포도 단순해졌습니다.

다만 Homepage 자체에는 인증 기능이 없으므로 외부에서 접근하도록 구성할 때는 Reverse Proxy의 HTTPS와 인증 설정을 반드시 함께 적용해야 합니다.

앞으로 서비스 상태 위젯과 API 연동을 추가하여 단순한 링크 모음이 아니라 홈랩 전체의 상태를 한눈에 확인할 수 있는 대시보드로 확장해볼 예정입니다.

참고