Akses Aplikasi Self-Hosted di Rumah Dari Manapun

Tujuan artikel ini adalah untuk menunjukkan bagaimana saya dapat mengakses foto dan video saya di rumah dari mana saja, menggunakan VPN tunnel yang terhubung ke server Immich lokal saya.

Ada banyak cara untuk mengekspose HTTP service yang berada dibalik NAT supaya dapat diakses dari internet. Pada umumnya, teknik yang dilakukan adalah melakukan network tunnel menggunakan VPN dan HTTP reverse proxy. Cloudflare Tunnel adalah salah satu contoh yang menggunakan teknik ini.

Di artikel ini saya ingin berbagi pengalaman dan cara saya mengekspose HTTP service yang berada di jaringan lokal ke internet menggunakan WireGuard VPN tunnel dan Nginx sebagai HTTP reverse proxy. HTTP service yang akan saya expose adalah Immich. Bagi yang belum tahu, Immich adalah solusi manajemen foto dan video yang dapat dihosting sendiri; sebuah alternatif dari Google Photos.

Saya tidak akan membahas detail cara menginstall Immich karena proses instalasi Immich menggunakan Docker sangat mudah dilakukan. Saya akan lebih fokus ke konfigurasi Nginx dan VPN tunnel, serta topologi yang digunakan.

Prasyarat

Sebelum memulai ada beberapa kondisi yang perlu dipenuhi, yaitu:

  1. Sebuah nama domain atau subdomain yang menggunakan Cloudflare sebagai authoritative DNS server.
  2. Sebuah VPS dengan IP public (sudah terinstall WireGuard dan Nginx yang nantinya digunakan untuk reverse proxy ke jaringan lokal).
  3. Sebuah PC / VM / LXC di jaringan lokal untuk menjalankan Nginx, Docker dan Certbot.

Topologi

Sebelum memulai, saya ingin membagikan topologi jaringan yang saya gunakan saat artikel ini dibuat.

gambar topologi jaringan

Ijinkan saya menjelaskan topologi diatas dan memberikan tambahan informasi untuk mengikuti artikel ini:

  • Subdomain yang saya gunakan untuk Immich adalah i.arch.or.id.
  • IP publik VPS server yang saya gunakan adalah 154.26.xxx.xx.
  • IP VPS server untuk WireGuard tunnel adalah 10.88.88.51.
  • Jaringan LAN menggunakan segmen 192.168.2.0/24.
  • Immich terinstall di LXC yang berada di jaringan lokal dengan alamat IP 192.168.2.105.
  • LXC Immich terkoneksi ke VPS server dan menggunakan IP tunnel 10.88.88.105.
  • Di LXC Immich juga terinstall Nginx dan Certbot.

Tujuan akhir dari artikel ini adalah aplikasi Immich dapat diakses dari internet dan seluruh perangkat yang berada pada jaringan lokal dapat terkoneksi secara langsung ke server Immich tanpa harus memutar ke internet.

Jadi ketika saya berada di luar rumah, saya masih tetap bisa mengakses foto dan video saya yang berada di rumah melalui aplikasi Immich. Sedangkan saat saya berada dirumah, saya dapat secara leluasa melakukan sinkronisasi atau upload foto dan video lebih cepat karena terkoneksi langsung menggunakan jaringan LAN.

Konfigurasi

Cloudflare: DNS record & Edge Certificates

Anda perlu mendelegasikan authoritative DNS server ke Cloudflare kemudian tambahkan atau arahkan A/AAAA record untuk subdomain yang akan digunakan oleh immich ke IP public VPS Anda. Di artikel ini berarti saya mengarahkan A record i.arch.or.id ke IP 154.26.xxx.xx.

Ada beberapa setting default dari Cloudflare yang perlu dirubah supaya LXC dapat melakukan request sertifikat SSL menggunakan certbot, yaitu:

  1. Mengubah mode enkripsi ke Full. Caranya masuk ke manajemen domain -> SSL/TLS -> Overview. Pada bagian “SSL/TLS encryption” ubah encryption mode ke Full. Hal ini perlu dilakukan supaya Cloudflare mau menerima “self-signed certificate” dari origin server.
  2. Mendisable “Always Use HTTPS” dan “Automatic HTTPS Rewrites”. Caranya masuk ke manajemen domain -> Edge Certificates. Pastikan “Always Use HTTPS” dan “Automatic HTTPS Rewrites” tidak aktif. Hal ini perlu dilakukan supaya verifikasi SSL request dari LXC ke Let’s Encrypt server berjalan dengan lancar.

VPS: WireGuard & Nginx

Anda perlu mensetting dan menjalankan WireGuard di VPS server yang nantinya digunakan untuk berkomunikasi dengan LXC server yang berada di jaringan lokal. Jika Anda belum pernah melakukan konfigurasi WireGuard, Anda dapat membaca artikel saya sebelumnya tentang cara setup WireGuard VPN server secara manual atau menggunakan WireGuard-UI.

Kurang lebih, konfigurasi WireGuard di VPS server saya sebagai berikut:

1[Interface]
2PrivateKey = SomeRandomStringThatShouldBePrivate
3Address = 10.88.88.51/22
4ListenPort = 51822
5
6# Immich LXC server
7[Peer]
8PublicKey = SomeRandomStringThatPublicMayKnow
9AllowedIPs = 10.88.88.105/32

Kemudian konfigurasi Nginx di VPS server sebagai reverse proxy ke LXC server, kurang lebih konfigurasi Nginx saya sebagai berikut:

 1upstream immich_app {
 2    server 10.88.88.105:443;
 3}
 4
 5server {
 6    listen 80;
 7    listen 443 ssl;
 8    server_name i.arch.or.id;
 9
10    # Self-signed certificates
11    ssl_certificate /etc/nginx/certs/fullchain.pem;
12    ssl_certificate_key /etc/nginx/certs/privkey.pem;
13
14    # Acme challenge handler
15    location /.well-known/acme-challenge/ {
16        allow all;
17        proxy_set_header Host $host;
18        proxy_set_header X-Real-IP $remote_addr;
19        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
20        proxy_set_header X-Forwarded-Proto https;
21
22        # This avoid SSL_do_handshake() failed on HTTPS upstream
23        proxy_ssl_name $host;
24        proxy_ssl_server_name on;
25        proxy_ssl_verify off;
26
27        proxy_pass https://immich_app;
28    }
29
30    keepalive_timeout    70;
31    sendfile             on;
32    client_max_body_size 100m;
33
34    location / {
35        proxy_set_header Host $host;
36        proxy_set_header X-Real-IP $remote_addr;
37        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
38        proxy_set_header X-Forwarded-Proto https;
39
40        # This avoid SSL_do_handshake() failed on HTTPS upstream
41        proxy_ssl_name $host;
42        proxy_ssl_server_name on;
43        proxy_ssl_verify off;
44
45        # enable websockets: http://nginx.org/en/docs/http/websocket.html
46        proxy_http_version 1.1;
47        proxy_set_header   Upgrade    $http_upgrade;
48        proxy_set_header   Connection "upgrade";
49        proxy_redirect     off;
50
51        proxy_pass https://immich_app;
52    }
53}

Bisa dilihat bahwa Nginx di VPS server menggunakan Self-signed certificates. Hal ini tidak menjadi masalah karena kita sudah mengkonfigurasi Cloudflare SSL/TLS encryption mode ke Full.

Dengan konfigurasi diatas, HTTP request dari internet akan melewati Cloudflare dan menggunakan sertifikat SSL yang valid dari Cloudflare. Request dilanjutkan ke VPS server dan kemudian diteruskan ke LXC server melalui WireGuard VPN tunnel.

Lokal LXC: WireGuard, Immich (Docker), Nginx, Certbot

Install WireGuard dan buat konfigurasi supaya bisa terhubung ke WireGuard server di VPS. Berikut ini contoh konfigurasi WireGuard di LXC server saya:

 1[Interface]
 2PrivateKey = SomeRandomStringThatShouldBePrivateII
 3Address = 10.88.88.105/22
 4
 5# VPS server
 6[Peer]
 7PublicKey = SomeRandomStringThatPublicMayKnowII
 8AllowedIPs = 10.88.88.51/32
 9Endpoint = 154.26.xxx.xxx:51822
10PersistentKeepalive = 15

Kemudian, install Immich dengan mengikuti proses instalasi Immich menggunakan Docker dari situs resminya. Secara default, Immich akan menggunakan TCP port 2283.

Buat konfigurasi Nginx virtual host untuk Immich. Nginx di LXC ini akan berfungsi sebagai reverse proxy dan menghandle Acme challenge sehingga server LXC memiliki sertifikat yang valid. Berikut ini adalah contoh konfigurasi Nginx virtual host untuk Immich di server LXC lokal:

 1upstream immich_app {
 2    server 127.0.0.1:2283;
 3}
 4
 5server {
 6    listen 80;
 7    server_name i.arch.or.id;
 8    root /srv/http/default;
 9
10    location /.well-known/acme-challenge/ {
11        allow all;
12    }
13    location / { return 301 https://$host$request_uri; }
14}
15
16server {
17    listen 443 ssl;
18    server_name i.arch.or.id;
19    ssl_certificate /etc/nginx/certs/fullchain.pem;
20    ssl_certificate_key /etc/nginx/certs/privkey.pem;
21
22    # allow large file uploads
23    client_max_body_size 50000M;
24
25    location / {
26        # Set headers
27        proxy_set_header Host              $http_host;
28        proxy_set_header X-Real-IP         $remote_addr;
29        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
30        proxy_set_header X-Forwarded-Proto $scheme;
31
32        # enable websockets: http://nginx.org/en/docs/http/websocket.html
33        proxy_http_version 1.1;
34        proxy_set_header   Upgrade    $http_upgrade;
35        proxy_set_header   Connection "upgrade";
36        proxy_redirect     off;
37
38        proxy_pass http://immich_app;
39    }
40}

Dari konfigurasi Nginx diatas, perlu diperhatikan bahwa untuk konfigurasi awal saya masih menggunakan Self-signed certificate. Langkah selanjutnya adalah melakukan request sertifikat SSL menggunakan Certbot.

Catatan: Sebelum melakukan request serifikat SSL, pastikan koneksi antara VPS server dan LXC melalui WireGuard tunnel berjalan dengan baik. Begitu pula dengan konfigurasi Nginx baik di VPS server dan LXC server.

Install certbot Nginx plugin. Di Ubuntu, Anda bisa menginstall cerbot Nginx plugin menggunakan sudo apt install python3-certbot-nginx. Setelah Certbot Nginx plugin terinstall, lakukan request sertifikat SSL dari XLC server:

1sudo certbot --nginx -d i.arch.or.id

Ubah i.arch.or.id ke (sub)domain milik Anda.

LAN: Lokal DNS resolver

Langkah terakhir adalah mengkonfigurasi perangkat-perangkat di jaringan LAN supaya subdomain i.arch.or.id mengarah ke IP lokal server LXC (192.169.2.105). Cara paling efektif adalah menggunakan lokal DNS resolver yang bisa digunakan oleh seluruh perangkat di jaringan LAN. Untuk konfigurasi DNS resolver akan sangat bervariasi tergantung seperti apa jaringan LAN masing-masing.

Untuk jaringan LAN saya, saya mempunyai dua buah DNS resolver. DNS resolver pertama berada di Router MikroTik, dan resolver kedua menggunakan AdGuard Home yang berjalan di Linux Container. AdGuard home disini saya gunakan juga sebagai DHCP server untuk jaringan lokal saya.

Berikut capture konfigurasi DNS resolver di MikroTik router dan AdGuard Home saya:

Dengan konfigurasi tersebut, seluruh perangkat yang ada di jaringan lokal menggunakan DHCP akan langsung akan menggunakan IP 192.168.2.105 ketika mencoba mengakses subdomain i.arch.or.id.

limitasi

  • Karena maksimum upload di Cloudflare hanya 100MB per request (untuk free version), maka proses sinkronisasi Immich dari internet kemungkinan besar banyak yang gagal, terutama saat sinkronisasi video.