summaryrefslogtreecommitdiffstats
path: root/deployment/install.sh
blob: 18652b9135449666ad7c17e3d72f17e006af70dc (plain) (blame)
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
#!/bin/bash
set -euo pipefail

abort() {
    printf "\033[31m%s\033[0m\n" "$@" >&2
    exit 1
}

log() {
    printf "%s\n" "$@"
}

ensure_visudo() {
    if ! command -v visudo >/dev/null 2>&1; then
        log "visudo was not found"
        log "Please install visudo for your distro"
        abort "sudo must be installed"
    fi
}

ensure_curl() {
    if ! command -v curl >/dev/null 2>&1; then
        log "curl was not found"
        log "Please install curl for your distro"
        abort "curl must be installed"
    fi
}

ensure_acl() {
    if ! command -v setfacl >/dev/null 2>&1; then
        log "ACL tools not found"
        log "Please install acl for your distro"
        abort "setfacl must be installed"
    fi
}

ensure_wg() {
    if ! command -v wg >/dev/null 2>&1; then
        log "Wireguard tools not found"
        log "Please install wireguard for your distro"
        abort "wg/wg-quick must be installed"
    fi
    WIREGUARD_PATH="$(which wg)"
    WIREGUARD_QUICK_PATH="$(which wg-quick)"
}

ensure_systemd() {
    if ! systemctl --version >/dev/null 2>&1; then
        abort "systemd is required but not available"
    fi
}

ensure_sudo() {
    if [ "$EUID" -ne 0 ]; then
        abort "Must be run as sudo"
    fi
}

get_arch() {
    ARCH=$(uname -m)
    case $ARCH in
        x86_64) ARCH="amd64" ;;
        aarch64) ARCH="arm64" ;;
        armv7l) ARCH="arm" ;;
        *) abort "Unsupported architecture: $ARCH" ;;
    esac
    log "Architecture: $ARCH"
}

get_version() {
    if [ "$VERSION" = "latest" ]; then
        RELEASE_URL="https://api.github.com/repos/a14m/wg-portal/releases/latest"
        VERSION=$(curl -s "$RELEASE_URL" | grep '"tag_name":' | cut -d '"' -f 4)
        log "Latest version: $VERSION"
    fi
}

validate_version() {
    if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && [ "$VERSION" != "latest" ]; then
        abort "Invalid version format: $VERSION (valid format example v1.0.0)"
    fi
}

create_tmp() {
    TMP_DIR=$(mktemp -d)
    trap 'rm -rf $TMP_DIR' EXIT
}

download_binary() {
    log "Downloading wg-portal binary"
    DOWNLOAD_URL="https://github.com/a14m/wg-portal/releases/download/$VERSION/wg-portal-linux-${ARCH}"
    if ! timeout 120 curl -s -L -o "$TMP_DIR/wg-portal" "$DOWNLOAD_URL"; then
        log "Failed to download $DOWNLOAD_URL"
        abort "Failed to download wg-portal binary"
    fi
    log "Downloaded $TMP_DIR/wg-portal"
}

download_systemd_service() {
    log "Downloading wg-portal.service"
    DOWNLOAD_SERVICE_URL="https://git.sr.ht/~a14m/wg-portal/blob/$VERSION/deployment/wg-portal.service"
    if ! timeout 30 curl -s -L -o "$TMP_DIR/wg-portal.service" "$DOWNLOAD_SERVICE_URL"; then
        log "Failed to download $DOWNLOAD_SERVICE_URL"
        abort "Failed to download wg-portal.service"
    fi
    log "Downloaded $TMP_DIR/wg-portal.service"
}

create_system_user() {
  if ! id -u wg-portal >/dev/null 2>&1; then
      log "Creating wg-portal system user and group..."
      useradd --system --no-create-home --shell /usr/sbin/nologin wg-portal
  else
      log "User wg-portal already exists"
  fi
}

create_etc_directory() {
    log "Creating /etc/wg-portal directory..."
    mkdir -p /etc/wg-portal
    chown root:wg-portal /etc/wg-portal
    chmod 750 /etc/wg-portal
}

configure_access_control() {
    log "Configure ACL for /etc/wireguard"
    setfacl -R -m g:wg-portal:r /etc/wireguard

    log "Setting up wg-portal user/group sudo permissions"
    cat > "$TMP_DIR/wg-portal-sudoers" << EOF
%wg-portal ALL=(ALL) NOPASSWD: ${WIREGUARD_QUICK_PATH} up *, ${WIREGUARD_QUICK_PATH} down *
%wg-portal ALL=(ALL) NOPASSWD: ${WIREGUARD_PATH} show
EOF
    # Validate before installing
    if visudo -c -f "$TMP_DIR/wg-portal-sudoers"; then
        mv "$TMP_DIR/wg-portal-sudoers" /etc/sudoers.d/wg-portal
        chmod 440 /etc/sudoers.d/wg-portal
    else
        abort "Invalid sudoers configuration"
    fi
}

install_binary() {
    log "Installing wg-portal binary to /etc/wg-portal"
    chmod +x "$TMP_DIR/wg-portal"
    mv "$TMP_DIR/wg-portal" /etc/wg-portal
}

install_systemd_service() {
    log "Installing wg-portal systemd service..."
    mv "$TMP_DIR/wg-portal.service" /etc/systemd/system/wg-portal.service
    systemctl daemon-reload
    systemctl enable wg-portal
    log "Service installed and enabled"
}

show_completion_message() {
  log ""
  log "wg-portal installed successfully!"
  log ""
  log "Configuration:"
  log "  - Configuration file: /etc/wg-portal/config"
  log ""
  log "Service Information:"
  log "  - Binary installed: /etc/wg-portal/wg-portal"
  log "  - Service: wg-portal.service (enabled)"
  log "  - User: wg-portal (system user)"
  log ""
  log "Useful Commands:"
  log "  - Check status: systemctl status wg-portal"
  log "  - View logs: journalctl -u wg-portal -f"
  log "  - Restart: systemctl restart wg-portal"
  log "  - Stop: systemctl stop wg-portal"
  log ""
  log "Next steps:"
  log "  - Configure: /etc/wg-portal/config"
  log "  - Start Service: systemctl start wg-portal"
}


# Configuration
VERSION=${1:-latest}
# Main
ensure_visudo
ensure_curl
ensure_acl
ensure_wg
ensure_systemd
ensure_sudo
get_arch
get_version
validate_version
create_tmp
download_binary
download_systemd_service
create_system_user
create_etc_directory
configure_access_control
install_binary
install_systemd_service
show_completion_message