README.md
1DragonFly pkg mirrorselect
2--------------------------
3
4**Mirrorselect** is an HTTP backend service that selects the
5[pkg(8)](https://man.dragonflybsd.org/?command=pkg§ion=8)
6mirrors according to their "distances" to the client.
7
8The "distance" of a mirror is determined by:
9
10* whether locate in the same country as the client
11* whether locate on the same continent as the client
12* great-circle distance between its coordinate and the client's
13
14The selected mirrors and their ordering are:
15
16* Prefer mirrors of the same **country** as the client.
17* If not, then prefer mirrors of the same **continent**.
18* If not, fallback to the *default* mirror.
19* If multiple mirrors in the same country/continent, order them by
20 *distance* to the client (calculated via latitude/longitude).
21* Append the *default* mirror to the last as fallback.
22* If cannot determine client's location, just return the *default* mirror.
23
24Features
25--------
26* Simple and small:
27 - simple config files
28 - few direct dependencies:
29 [gin-gonic/gin](https://github.com/gin-gonic/gin),
30 [oschwald/maxminddb-golang](https://github.com/oschwald/maxminddb-golang),
31 [spf13/viper](https://github.com/spf13/viper),
32 [jlaffaye/ftp](https://github.com/jlaffaye/ftp)
33* Stand-alone:
34 - use offline IP geolocation database
35 (open [MaxMind DB format](https://maxmind.github.io/MaxMind-DB/))
36 - support both [MaxMind](https://www.maxmind.com) and
37 [DB-IP](https://db-ip.com) dataset
38* Built-in mirror monitor:
39 - periodically check mirror status
40 - support HTTP, HTTPS and FTP
41 - use a hysteresis to smooth status flipping
42 - run a command when a mirror is down/up to publish events
43
44Implementation
45--------------
46This mirror selection implementation leverages pkg(8)'s **HTTP**
47mirror type of repository.
48Basically, the repository URL provides a sequence of lines beginning with
49`URL:` followed by any amount of white space and one URL for a repository
50mirror.
51Then, pkg(8) tries these mirrors in the order listed until a download
52succeeds.
53
54See also: [pkg-repository(5)](https://man.dragonflybsd.org/?command=pkg-repository§ion=5)
55
56For example, configure the pkg(8) repos as:
57```
58AUTO: {
59 url: https://pkg.dragonflybsd.org/pkg/${ABI}/LATEST
60 mirror_type: HTTP
61}
62```
63
64And upon client's request, the service returns, e.g.,:
65```
66URL: https://mirror.sjtu.edu.cn/dragonflybsd/dports/dragonfly:5.10:x86:64/LATEST
67URL: ...
68URL: https://mirror-master.dragonflybsd.org/dports/dragonfly:5.10:x86:64/LATEST
69```
70
71NOTE: The `${ABI}` is expanded by pkg(8) on the client side.
72
73Deployment
74----------
751. Prepare the mirror list file `mirrors.toml`, listing all available
76 pkg(8) mirrors and their locations.
772. Obtain one of the following **free** IP geolocation database
78 (choose **MMDB** binary format):
79 * [DB-IP Lite data](https://db-ip.com/db/download/ip-to-city-lite)
80 <br>
81 *Recommended*, more entries and higher precision, no sign-up required.
82 * [MaxMind GeoLite2 data](https://dev.maxmind.com/geoip/geoip2/geolite2/)
83 <br>
84 NOTE: sign-up required to download the database.
853. Create the main config file `mirrorselect.toml`.
864. Run **mirrorselect** as a **normal** user (e.g., `nobody`).
875. Publish this service via Nginx/Apache.
88
89### Nginx proxy example
90
91```nginx
92server {
93 listen 80 http2;
94 server_name pkg.dragonflybsd.org;
95
96 location / {
97 proxy_http_version 1.1;
98 proxy_set_header Host $host;
99 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
100 proxy_pass http://localhost:3130;
101 }
102}
103```
104
105### Apache proxy example
106
107```apache
108<VirtualHost *:80>
109 ServerName pkg.dragonflybsd.org
110
111 ProxyPreserveHost On
112 ProxyPass / http://localhost:3130/
113 ProxyPassReverse / http://localhost:3130/
114</VirtualHost>
115```
116
117### On DragonFly BSD
118
1191. Install the `www/mirrorselect` package:
120
121 pkg install mirrorselect
122
1232. Enable and start the `mirrorselect` service:
124
125 rcenable mirrorselect
126 rcstart mirrorselect
127
1283. Configure Nginx/Apache to export the service.
129
130Services
131--------
132* `/`
133 <br>
134 For testing, just reply a `pong`, same as the `/ping` below.
135* `/ping`
136 <br>
137 For testing, just reply a `pong`.
138* `/ip`
139 <br>
140 Show the client's IP as well as its location information,
141 queried from the geolocation database.
142* `/mirrors`
143 <br>
144 Return a JSON object containing the information and status of all mirrors.
145* `/pkg/:abi/*path`
146 <br>
147 Return the selected mirrors based on the client's location.
148 <br>
149 NOTE: The `:abi/*path` part would be returned as-is.
150
151License
152-------
153The 3-Clause BSD License
154
155Copyright (c) 2021 The DragonFly Project.
156