├── .github ├── assets │ └── logo.png └── workflows │ └── deploy.yml ├── .gitignore ├── Caddyfile ├── LICENSE ├── README.md ├── config ├── homer │ └── config.yml └── prometheus │ └── config.yml ├── docker-compose.yml ├── example.env └── install.sh /.github/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NuroDev/jarvis/fef837a463410bb3893d9ff0315fa6467b008295/.github/assets/logo.png -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 Deploy 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: .env 12 | run: cp example.env .env 13 | - name: Deploy 14 | run: docker-compose up -d 15 | - name: Check 16 | run: docker ps -a 17 | - name: Logs 18 | run: docker-compose logs 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files 2 | .DS_store 3 | .env 4 | 5 | # Directories 6 | config/ 7 | data/ 8 | 9 | # Include config files 10 | !config/homer/config.yml 11 | !config/prometheus/config.yml 12 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | { 2 | # email me@email.com 3 | # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory 4 | } 5 | 6 | {$DOMAIN} { 7 | reverse_proxy homer:8080 8 | } 9 | 10 | cadvisor.{$DOMAIN} { 11 | reverse_proxy cadvisor:8080 12 | } 13 | 14 | monitoring.{$DOMAIN} { 15 | reverse_proxy grafana:3000 16 | } 17 | 18 | node_exporter.{$DOMAIN} { 19 | reverse_proxy node_exporter:9100 20 | } 21 | 22 | request.{$DOMAIN} { 23 | reverse_proxy overseerr:5055 24 | } 25 | 26 | tautulli.{$DOMAIN} { 27 | reverse_proxy tautulli:8181 28 | } 29 | 30 | prometheus.{$DOMAIN} { 31 | reverse_proxy prometheus:9090 32 | } 33 | 34 | watch.{$DOMAIN} { 35 | reverse_proxy plex:32400 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 N U R O ™ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | [![License](https://img.shields.io/badge/-mit-blue.svg?longCache=true&style=for-the-badge)](https://github.com/nurodev/jarvis/blob/master/LICENSE) 5 | [![Build](https://img.shields.io/github/workflow/status/nurodev/jarvis/%F0%9F%9A%80%20Deploy?label=%20&logo=github&logoColor=white&style=for-the-badge)](https://github.com/NuroDev/jarvis/actions?query=workflow%3A%22%F0%9F%9A%80+Deploy%22) 6 | [![Gitmoji](https://img.shields.io/badge/-%20%F0%9F%98%9C-FFDD67.svg?longCache=true&style=for-the-badge)](https://gitmoji.carloscuesta.me/) 7 |
8 | 9 | Jarvis is a simple and easy to setup media stack that can be deployed on any unix based system that has Docker installed within a few minutes and offer a near feature complete self-hosted media system: 10 | 11 | - [Cadvisor](https://github.com/google/cadvisor) - Docker metrics 12 | - [Grafana](https://grafana.com/) - Monitoring Dashboard 13 | - [Homer](https://github.com/bastienwirtz/homer) - Home dashboard 14 | - [Node Exporter](https://github.com/prometheus/node_exporter) - System metrics 15 | - [Overseerr](https://overseerr.dev) - Content requesting 16 | - [Plex](https://www.plex.tv/) - Content streaming 17 | - [Prometheus](https://prometheus.io/) - Metrics Database 18 | - [Tautulli](https://tautulli.com/) - Plex Metrics 19 | 20 | ## 📋 Requirements 21 | These are the required libraries/packages to run this stack: 22 | - [Docker](https://docker.com) 23 | - [Docker Compose](https://docs.docker.com/compose/) 24 | 25 | ## 🚀 Usage 26 | ```shell 27 | curl -sSL https://jarvis.nuro.dev | sh 28 | ``` 29 | 30 | ## 🔧 Configure 31 | For the most part, once the stack has been setup and deployed there are 2 key configuration steps that needs to be done. 32 | 33 | 34 |
35 | 🏡 Homer 36 | 37 | The first step is to modify the Homer config file. This can be found under `config/homer/config.yml`. 38 | 39 | In here you can modify your home dashboard with whatever links or customization you like. A number of service links have already been provided, however there is one key configration requirement and that is to modify the URL's set for each service to be the domain of your choice. 40 | 41 |
42 | 43 |
44 | 📫 Email (Optional) 45 | 46 | To generate a certificate from Let's Encrypt, an email address is required. As such in the `Caddyfile` a placeholder `email` global variable has been provided but commented out. Uncomment the variable by removing the `#` and entering your email address. 47 | 48 | You can also optionally modify the `acme_ca` URL, which specifies the URL to the ACME CA's directory. However it is recommended to leave this to the default Let's Encrypt production endpoint unless you require the use of the Let's Encrypt [staging or development endpoints](https://letsencrypt.org/docs/staging-environment/). 49 | 50 |
51 | 52 | ## 🔑 Access 53 | | Container | Description | URL | 54 | | ------------------|:--------------------------:|:--------------------------------:| 55 | | Cadvisor | Docker Metrics | `cadvisor.ip_address` | 56 | | Grafana | Monitoring Dashboard | `monitoring.ip_address` | 57 | | Homer | Home Dashboard | `ip_address` | 58 | | Node Exporter | System Metrics | `node_exporter.ip_address` | 59 | | Overseerr | Content Requesting | `request.ip_address` | 60 | | Plex | Content Streaming | `watch.ip_address` | 61 | | Prometheus | Metrics Database | `prometheus.ip_address` | 62 | | Tautulli | Plex Metrics | `tautulli.ip_address` | 63 | 64 | ## ✅ Optional 65 | 66 | There are some work-in-progress optional branches that trade some services for alternatives. 67 | 68 | The most recent of such branches has been the [`jellyfin`](https://github.com/NuroDev/jarvis/tree/jellyfin) branch which replaces the `plex` and `tautulli` services with [Jellyfin](https://jellyfin.org/) which is a completely self-hosted media server, compared to Plex which still requires on services hosted by Plex themselves. 69 | 70 | To get started using the [`jellyfin`](https://github.com/NuroDev/jarvis/tree/jellyfin) branch, use the following command in place of the one above: 71 | ```shell 72 | curl -sSL https://jarvis.nuro.dev/jellyfin | sh 73 | ``` 74 | Or check the [`jellyfin`](https://github.com/NuroDev/jarvis/tree/jellyfin) branch for more details. 75 | 76 | ## 📋 TODO 77 | 78 | - [x] Add GitHub Actions CI for testing. 79 | - [ ] Fix Homer service URL's so they're based on the `DOMAIN` environment vairable. 80 | - [ ] Add `basicauth` to some metric endpoints via the [Caddy Module](https://caddyserver.com/docs/caddyfile/directives/basicauth). 81 | - [ ] Add Caddy prometheus metrics using [Caddy module](https://github.com/hairyhenderson/caddyprom) (Requires custom Caddy image build). 82 | - [ ] Provide custom pre-made Grafana dashboard. 83 | - [ ] Add [Varken](https://github.com/Boerderij/Varken) data aggregator container. 84 | -------------------------------------------------------------------------------- /config/homer/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Homepage configuration 3 | # See # https://github.com/bastienwirtz/homer/blob/master/docs/configuration.md for complete guide 4 | # See https://fontawesome.com/icons for icons options 5 | 6 | subtitle: "Jarvis" 7 | 8 | header: false 9 | footer: false 10 | 11 | columns: "auto" 12 | connectivityCheck: true 13 | 14 | theme: default 15 | 16 | # TODO: Disabling links remove themeing options 17 | links: 18 | - name: "GitHub" 19 | icon: "fab fa-github" 20 | url: "https://github.com/" 21 | 22 | services: 23 | - name: "Application" 24 | icon: "fa fa-cloud" 25 | items: 26 | - name: "Plex" 27 | subtitle: "Watch content" 28 | icon: "fa fa-play-circle" 29 | url: "https://watch.localhost/" 30 | 31 | - name: "Ombi" 32 | subtitle: "Content requesting" 33 | icon: "fa fa-tasks" 34 | url: "https://request.localhost/" 35 | 36 | - name: "Monitoring" 37 | subtitle: "Grafana monitoring dashboard" 38 | icon: "fa fa-chart-bar" 39 | url: "https://monitoring.localhost/" 40 | 41 | - name: "Metrics" 42 | icon: "fa fa-chart-bar" 43 | items: 44 | - name: "Cadvisor" 45 | subtitle: "Docker container metrics" 46 | icon: "fa fa-docker" 47 | url: "https://cadvisor.localhost/" 48 | 49 | - name: "Node Exporter" 50 | subtitle: "System metrics" 51 | icon: "fa fa-server" 52 | url: "https://node_exporter.localhost/" 53 | 54 | - name: "Prometheus" 55 | subtitle: "Metrics Database" 56 | icon: "fa fa-database" 57 | url: "https://prometheus.localhost/" 58 | 59 | - name: "Tautulli" 60 | subtitle: "Plex metrics" 61 | icon: "fa fa-chart-pie" 62 | url: "https://tautulli.localhost/" 63 | -------------------------------------------------------------------------------- /config/prometheus/config.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 30s 3 | scrape_timeout: 10s 4 | evaluation_interval: 5s 5 | scrape_configs: 6 | - job_name: cadvisor 7 | scheme: http 8 | static_configs: 9 | - targets: 10 | - cadvisor:8080 11 | 12 | - job_name: node_exporter 13 | scheme: http 14 | static_configs: 15 | - targets: 16 | - node_exporter:9100 17 | 18 | - job_name: prometheus 19 | scheme: http 20 | static_configs: 21 | - targets: 22 | - prometheus:9090 23 | 24 | - job_name: grafana 25 | scheme: http 26 | static_configs: 27 | - targets: 28 | - grafana:3000 29 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | networks: 4 | jarvis: 5 | external: false 6 | 7 | services: 8 | caddy: 9 | image: caddy:latest 10 | container_name: caddy 11 | restart: unless-stopped 12 | hostname: caddy 13 | networks: 14 | - jarvis 15 | ports: 16 | - 80:80 17 | - 443:443 18 | environment: 19 | - DOMAIN 20 | volumes: 21 | - ./Caddyfile:/etc/caddy/Caddyfile:ro 22 | - $CONFIG_DIR:/config 23 | - $DATA_DIR:/data 24 | 25 | cadvisor: 26 | image: google/cadvisor:latest 27 | container_name: cadvisor 28 | restart: unless-stopped 29 | hostname: cadvisor 30 | networks: 31 | - jarvis 32 | ports: 33 | - 8080:8080 34 | volumes: 35 | - /:/rootfs:ro 36 | - /var/run:/var/run:rw 37 | - /sys:/sys:ro 38 | - /var/lib/docker:/var/lib/docker:ro 39 | - /cgroup:/cgroup:ro 40 | 41 | grafana: 42 | image: grafana/grafana:latest 43 | container_name: grafana 44 | restart: unless-stopped 45 | user: root 46 | hostname: grafana 47 | networks: 48 | - jarvis 49 | ports: 50 | - 3000:3000 51 | depends_on: 52 | - cadvisor 53 | - node_exporter 54 | - prometheus 55 | environment: 56 | - GF_SECURITY_ADMIN_USER 57 | - GF_SECURITY_ADMIN_PASSWORD 58 | - GF_USERS_ALLOW_SIGN_UP 59 | volumes: 60 | - $CONFIG_DIR/grafana:/var/lib/grafana 61 | - $CONFIG_DIR/grafana/provisioning:/etc/grafana/provisioning 62 | 63 | homer: 64 | image: b4bz/homer:latest 65 | container_name: homer 66 | restart: unless-stopped 67 | hostname: homer 68 | networks: 69 | - jarvis 70 | volumes: 71 | - $CONFIG_DIR/homer/:/www/assets 72 | 73 | node_exporter: 74 | image: prom/node-exporter:latest 75 | container_name: node_exporter 76 | restart: unless-stopped 77 | hostname: node_exporter 78 | networks: 79 | - jarvis 80 | ports: 81 | - 9100:9100 82 | command: 83 | - '--path.procfs=/host/proc' 84 | - '--path.rootfs=/rootfs' 85 | - '--path.sysfs=/host/sys' 86 | - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)' 87 | volumes: 88 | - /proc:/host/proc:ro 89 | - /sys:/host/sys:ro 90 | - /:/rootfs:ro 91 | 92 | overseerr: 93 | image: sctx/overseerr:latest 94 | container_name: overseerr 95 | restart: unless-stopped 96 | hostname: overseerr 97 | networks: 98 | - jarvis 99 | ports: 100 | - 5055:5055 101 | depends_on: 102 | - plex 103 | environment: 104 | - TZ=Europe/London 105 | - LOG_LEVEL=info 106 | volumes: 107 | - $CONFIG_DIR/overseerr:/app/config/ 108 | 109 | plex: 110 | image: plexinc/pms-docker:latest 111 | container_name: plex 112 | restart: unless-stopped 113 | hostname: plex 114 | networks: 115 | - jarvis 116 | ports: 117 | - 1900:1900/udp 118 | - 3005:3005/tcp 119 | - 32400:32400/tcp 120 | - 32410:32410/udp 121 | - 32412:32412/udp 122 | - 32413:32413/udp 123 | - 32414:32414/udp 124 | - 32469:32469/tcp 125 | - 8324:8324/tcp 126 | environment: 127 | - ADVERTISE_IP="http://$DOMAIN:32400" 128 | - VERSION=latest 129 | volumes: 130 | - $CONFIG_DIR/plex:/config 131 | - $DATA_DIR/media:/data 132 | - $DATA_DIR/transcode:/transcode 133 | 134 | prometheus: 135 | image: prom/prometheus:latest 136 | container_name: prometheus 137 | restart: unless-stopped 138 | hostname: prometheus 139 | user: root 140 | networks: 141 | - jarvis 142 | ports: 143 | - 9090:9090 144 | depends_on: 145 | - cadvisor 146 | command: 147 | - '--config.file=/etc/prometheus/prometheus.yml' 148 | - '--storage.tsdb.path=/prometheus' 149 | - '--storage.tsdb.retention.time=200h' 150 | - '--web.console.libraries=/etc/prometheus/console_libraries' 151 | - '--web.console.templates=/etc/prometheus/consoles' 152 | - '--web.enable-lifecycle' 153 | volumes: 154 | - $CONFIG_DIR/prometheus/config.yml:/etc/prometheus/prometheus.yml 155 | - $CONFIG_DIR/prometheus/:/prometheus 156 | 157 | tautulli: 158 | image: linuxserver/tautulli:latest 159 | container_name: tautulli 160 | restart: unless-stopped 161 | hostname: tautulli 162 | networks: 163 | - jarvis 164 | ports: 165 | - 8181:8181 166 | depends_on: 167 | - plex 168 | environment: 169 | - TZ=Europe/London 170 | volumes: 171 | - $CONFIG_DIR/tautulli:/config 172 | - $CONFIG_DIR/plex/Library/Application Support/Plex Media Server/Logs/:/logs 173 | 174 | watchtower: 175 | image: containrrr/watchtower:latest 176 | container_name: watchtower 177 | restart: unless-stopped 178 | networks: 179 | - jarvis 180 | volumes: 181 | - /var/run/docker.sock:/var/run/docker.sock 182 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | # Directories 2 | CONFIG_DIR=./config/ 3 | DATA_DIR=./data/ 4 | 5 | # Network 6 | DOMAIN=localhost 7 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set +e 4 | 5 | echo " 6 | ╔═══════════════════════════════════════════════════════════════════════╗ 7 | ║ ╔═════════════════════════════════════════════════════════════════╗ ║ 8 | ║ ║ ║ ║ 9 | ║ ║ ██╗ █████╗ ██████╗ ██╗ ██╗██╗███████╗ ║ ║ 10 | ║ ║ ██║██╔══██╗██╔══██╗██║ ██║██║██╔════╝ ║ ║ 11 | ║ ║ ██║███████║██████╔╝██║ ██║██║███████╗ ║ ║ 12 | ║ ║ ██ ██║██╔══██║██╔══██╗╚██╗ ██╔╝██║╚════██║ ║ ║ 13 | ║ ║ ╚█████╔╝██║ ██║██║ ██║ ╚████╔╝ ██║███████║ ║ ║ 14 | ║ ║ ╚════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚═╝╚══════╝ ║ ║ 15 | ║ ║ ║ ║ 16 | ║ ╚═════════════════════════════════════════════════════════════════╝ ║ 17 | ╚═══════════════════════════════════════════════════════════════════════╝" 18 | 19 | echo " 20 | ╔═════════════════════════════════════════════════════════════╗ 21 | ║ Installing Docker Compose 🐳 ║ 22 | ╚═════════════════════════════════════════════════════════════╝" 23 | if test $(which docker-compose); then 24 | sudo apt-get remove docker-compose 25 | fi 26 | 27 | sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 28 | sudo chmod +x /usr/local/bin/docker-compose 29 | sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 30 | 31 | echo " 32 | ╔═════════════════════════════════════════════════════════════╗ 33 | ║ Downloading ⬇️ ║ 34 | ╚═════════════════════════════════════════════════════════════╝" 35 | git clone https://github.com/nurodev/jarvis.git 36 | cd ./jarvis/ 37 | 38 | echo " 39 | ╔═════════════════════════════════════════════════════════════╗ 40 | ║ Configuring .env 🤫 ║ 41 | ╚═════════════════════════════════════════════════════════════╝" 42 | cp ./example.env .env 43 | 44 | echo " 45 | ╔═════════════════════════════════════════════════════════════╗ 46 | ║ Starting 🚀 ║ 47 | ╚═════════════════════════════════════════════════════════════╝" 48 | docker-compose up -d 49 | 50 | echo " 51 | ╔═════════════════════════════════════════════════════════════╗ 52 | ║ Done! 🎉 ║ 53 | ╚═════════════════════════════════════════════════════════════╝" 54 | --------------------------------------------------------------------------------