├── .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 | [](https://github.com/nurodev/jarvis/blob/master/LICENSE)
5 | [](https://github.com/NuroDev/jarvis/actions?query=workflow%3A%22%F0%9F%9A%80+Deploy%22)
6 | [](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 |
--------------------------------------------------------------------------------