-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathbuild.sh
More file actions
executable file
·366 lines (317 loc) · 9 KB
/
build.sh
File metadata and controls
executable file
·366 lines (317 loc) · 9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
#!/bin/bash
SCRIPT_DIR=$(
cd $(dirname $0)
pwd
)
ACTION=$1
META_DIR=$SCRIPT_DIR
DSTACK_DIR=$SCRIPT_DIR/dstack
CERTS_DIR=$(pwd)/certs
IMAGES_DIR=$(pwd)/images
RUN_DIR=$(pwd)/run
RUST_BUILD_DIR=$(pwd)/rust-target
CERBOT_WORKDIR=$RUN_DIR/certbot
KMS_UPGRADE_REGISTRY_DIR=$RUN_DIR/kms/upgrade_registry
KMS_CERT_LOG_DIR=$RUN_DIR/kms/cert_log/
GATEWAY_CERT=${GATEWAY_CERT:-$CERTS_DIR/live/cert.pem}
GATEWAY_KEY=${GATEWAY_KEY:-$CERTS_DIR/live/key.pem}
CONFIG_FILE=./build-config.sh
check_config() {
local template_file=$1
local config_file=$2
# extract all variables in template file
local variables=$(grep -oE '^\s*[A-Z_]+=' $template_file | sort)
# check if each variable is set in config file
local var missing=0
for var in $variables; do
if ! grep -qE "^\s*$var" $config_file; then
echo "Variable $var is not set in $config_file"
missing=1
fi
done
if [ $missing -ne 0 ]; then
return 1
fi
return 0
}
require_config() {
# Base port for RPC services
BASE_PORT=$(($RANDOM % 1000 * 10 + 10000))
CID_POOL_START=$(($RANDOM % 1000 * 1000 + 20000))
SUBNET_INDEX=$(($RANDOM % 240 + 10))
cat <<EOF >build-config.sh.tpl
# DNS domain of kms rpc and dstack-gateway rpc
# *.1022.dstack.org resolves to 10.0.2.2 which is the IP of the host system
# from CVMs point of view
KMS_DOMAIN=kms.1022.dstack.org
GATEWAY_DOMAIN=gateway.1022.dstack.org
# CIDs allocated to VMs start from this number of type unsigned int32
VMM_CID_POOL_START=$CID_POOL_START
# CID pool size
VMM_CID_POOL_SIZE=1000
VMM_RPC_LISTEN_PORT=$BASE_PORT
# Whether port mapping from host to CVM is allowed
VMM_PORT_MAPPING_ENABLED=true
# Host API configuration, type of uint32
VMM_VSOCK_LISTEN_PORT=$BASE_PORT
# Whether to enable GPU support
VMM_ENABLE_GPU=false
KMS_RPC_LISTEN_PORT=$(($BASE_PORT + 1))
GATEWAY_RPC_LISTEN_PORT=$(($BASE_PORT + 2))
GATEWAY_WG_INTERFACE=dgw-$USER
GATEWAY_WG_LISTEN_PORT=$(($BASE_PORT + 3))
GATEWAY_WG_IP=10.$SUBNET_INDEX.3.1
GATEWAY_SERVE_PORT=$(($BASE_PORT + 4))
GATEWAY_CERT=$CERBOT_WORKDIR/live/cert.pem
GATEWAY_KEY=$CERBOT_WORKDIR/live/key.pem
BIND_PUBLIC_IP=0.0.0.0
GATEWAY_PUBLIC_DOMAIN=<your domain for zt-https>
# for certbot
CERTBOT_ENABLED=false
CF_API_TOKEN=
ACME_URL=https://acme-staging-v02.api.letsencrypt.org/directory
EOF
if [ -f $CONFIG_FILE ]; then
source $CONFIG_FILE
# check if any variable in build-config.sh.tpl is not set in build-config.sh.
# This might occur if the build-config.sh is generated from and old repo.
check_config build-config.sh.tpl $CONFIG_FILE
if [ $? -ne 0 ]; then
exit 1
fi
rm -f build-config.sh.tpl
if [ -z "$GATEWAY_SERVE_PORT" ]; then
GATEWAY_SERVE_PORT=${GATEWAY_LISTEN_PORT1}
fi
AGENT_PORT=8090
else
mv build-config.sh.tpl $CONFIG_FILE
echo "Config file $CONFIG_FILE created, please edit it to configure the build"
exit 1
fi
}
# Step 1: build binaries
build_host() {
echo "Building binaries"
(cd $DSTACK_DIR && cargo build --release --target-dir ${RUST_BUILD_DIR})
for bin in dstack-gateway dstack-kms dstack-vmm supervisor; do
cp "${RUST_BUILD_DIR}/release/${bin}" ".${bin}.new"
mv -f ".${bin}.new" "./${bin}"
done
}
# Step 2: build guest images
build_guest() {
echo "Building guest images"
if [ -z "$BBPATH" ]; then
source $SCRIPT_DIR/dev-setup $1
fi
make -C $META_DIR dist DIST_DIR=$IMAGES_DIR BB_BUILD_DIR=${BBPATH}
}
# Step 4: generate config files
build_cfg() {
echo "Building config files"
if [ -f "gateway.toml" ]; then
echo "Reading existing WireGuard key from gateway.toml"
GATEWAY_WG_KEY=$(awk '
/^\s*private_key\s*=/ {
# Remove leading whitespace and "private_key ="
gsub(/^\s*private_key\s*=\s*/, "")
# Remove quotes (both single and double)
gsub(/^["'"'"']|["'"'"']$/, "")
# Remove trailing whitespace and comments
gsub(/\s*(#.*)?$/, "")
if (length($0) > 0) {
print $0
exit
}
}
' gateway.toml)
if [ -z "$GATEWAY_WG_KEY" ]; then
echo "Error: Could not read WireGuard key from existing gateway.toml"
exit 1
fi
else
echo "Generating new WireGuard key"
GATEWAY_WG_KEY=$(wg genkey)
fi
GATEWAY_WG_PUBKEY=$(echo $GATEWAY_WG_KEY | wg pubkey)
# kms
cat <<EOF >kms.toml
log_level = "info"
[rpc]
address = "127.0.0.1"
port = $KMS_RPC_LISTEN_PORT
[rpc.tls]
key = "$CERTS_DIR/rpc.key"
certs = "$CERTS_DIR/rpc.crt"
[rpc.tls.mutual]
ca_certs = "$CERTS_DIR/tmp-ca.crt"
mandatory = false
[core]
cert_dir = "$CERTS_DIR"
[core.gpu]
enabled = $VMM_ENABLE_GPU
[core.auth_api]
type = "dev"
[core.onboard]
quote_enabled = false
address = "127.0.0.1"
port = $KMS_RPC_LISTEN_PORT
auto_bootstrap_domain = "$KMS_DOMAIN"
[core.image]
verify = false
EOF
# dstack-gateway
cat <<EOF >gateway.toml
log_level = "info"
address = "127.0.0.1"
port = $GATEWAY_RPC_LISTEN_PORT
[tls]
key = "$CERTS_DIR/gateway-rpc.key"
certs = "$CERTS_DIR/gateway-rpc.cert"
[tls.mutual]
ca_certs = "$CERTS_DIR/gateway-ca.cert"
mandatory = false
[core]
kms_url = "https://localhost:$KMS_RPC_LISTEN_PORT"
rpc_domain = "$GATEWAY_DOMAIN"
run_in_dstack = false
[core.sync]
enabled = false
[core.certbot]
enabled = $CERTBOT_ENABLED
# Path to the working directory
workdir = "$CERBOT_WORKDIR"
# ACME server URL
acme_url = "$ACME_URL"
# Cloudflare API token
cf_api_token = "$CF_API_TOKEN"
# Auto set CAA record
auto_set_caa = true
# Domain to issue certificates for
domain = "*.$GATEWAY_PUBLIC_DOMAIN"
# Check renewal interval
renew_interval = "30m"
# Number of days before expiration to trigger renewal
renew_days_before = "10d"
# Renew timeout
renew_timeout = "10m"
[core.wg]
private_key = "$GATEWAY_WG_KEY"
public_key = "$GATEWAY_WG_PUBKEY"
listen_port = $GATEWAY_WG_LISTEN_PORT
ip = "$GATEWAY_WG_IP/24"
reserved_net = ["$GATEWAY_WG_IP/31"]
client_ip_range = "$GATEWAY_WG_IP/24"
config_path = "$RUN_DIR/wg.conf"
interface = "$GATEWAY_WG_INTERFACE"
endpoint = "10.0.2.2:$GATEWAY_WG_LISTEN_PORT"
[core.proxy]
cert_chain = "$GATEWAY_CERT"
cert_key = "$GATEWAY_KEY"
base_domain = "$GATEWAY_PUBLIC_DOMAIN"
listen_addr = "$BIND_PUBLIC_IP"
listen_port = $GATEWAY_SERVE_PORT
agent_port = $AGENT_PORT
app_address_ns_prefix = "_tapp-address"
EOF
# dstack-vmm config
cat <<EOF >vmm.toml
log_level = "info"
address = "127.0.0.1"
port = $VMM_RPC_LISTEN_PORT
image_path = "$IMAGES_DIR"
run_path = "$RUN_DIR/vm"
kms_url = "https://localhost:$KMS_RPC_LISTEN_PORT"
[cvm]
kms_urls = ["https://$KMS_DOMAIN:$KMS_RPC_LISTEN_PORT"]
gateway_urls = ["https://$GATEWAY_DOMAIN:$GATEWAY_RPC_LISTEN_PORT"]
cid_start = $VMM_CID_POOL_START
cid_pool_size = $VMM_CID_POOL_SIZE
[cvm.port_mapping]
enabled = $VMM_PORT_MAPPING_ENABLED
address = "127.0.0.1"
range = [
{ protocol = "tcp", from = 1, to = 20000 },
{ protocol = "udp", from = 1, to = 20000 },
]
[gateway]
base_domain = "$GATEWAY_PUBLIC_DOMAIN"
port = $GATEWAY_SERVE_PORT
agent_port = $AGENT_PORT
[host_api]
port = $VMM_VSOCK_LISTEN_PORT
EOF
mkdir -p $RUN_DIR
mkdir -p $CERBOT_WORKDIR/backup/preinstalled
}
download_image() {
local VERSION=""
local IS_DEV=""
# Parse arguments to support both formats
if [[ "$1" == "-dev" ]]; then
IS_DEV=1
VERSION=$2
else
VERSION=$1
fi
echo "Downloading image $VERSION${IS_DEV:+ (dev)}"
TAG=v$VERSION
if [ x"$IS_DEV" = x"1" ]; then
BASENAME=dstack-dev-$VERSION
else
BASENAME=dstack-$VERSION
fi
URL=https://github.com/Dstack-TEE/meta-dstack/releases/download/$TAG/$BASENAME.tar.gz
if [ -d $IMAGES_DIR/$BASENAME ]; then
echo "Image already exists"
else
mkdir -p $IMAGES_DIR/$BASENAME.tmp
curl -L $URL -o $IMAGES_DIR/$BASENAME.tar.gz
tar -xvf $IMAGES_DIR/$BASENAME.tar.gz -C $IMAGES_DIR/$BASENAME.tmp
rm -f $IMAGES_DIR/$BASENAME.tar.gz
if [ -d $IMAGES_DIR/$BASENAME.tmp/$BASENAME ]; then
mv $IMAGES_DIR/$BASENAME.tmp/$BASENAME $IMAGES_DIR/$BASENAME
rm -rf $IMAGES_DIR/$BASENAME.tmp
else
mv $IMAGES_DIR/$BASENAME.tmp $IMAGES_DIR/$BASENAME
fi
fi
}
case $ACTION in
host)
build_host
;;
guest)
build_guest $2
;;
cfg)
require_config
build_cfg
;;
dl)
download_image $2 $3
;;
hostcfg)
require_config
build_host
build_cfg
;;
all)
require_config
build_host
build_guest
build_cfg
;;
*)
echo "Invalid action: $ACTION"
echo "Valid actions are:"
echo " host - Build host binaries only"
echo " guest - Build guest images only"
echo " cfg - Generate configuration files only"
echo " dl - Download a specific image"
echo " hostcfg - Build host binaries and generate configuration files"
echo " all - Build everything (host, guest, and configuration)"
exit 1
;;
esac