aboutsummaryrefslogtreecommitdiff
path: root/install.sh
blob: 8ed52ef5ae18af98a48a1e741a7bb7881bfe1887 (plain)
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
#!/usr/bin/env bash
set -euo pipefail

# Cerberus installer (development convenience)
# - Installs Python package with optional extras
# - Builds C core
# - Sets up Native Messaging for Firefox and Chrome (Linux)
#
# Options via env:
#  CERB_EXTRAS="ui-tui,ui-gui,automation-selenium"  (comma-separated)
#  CERB_SKIP_BUILD=1       # Skip cmake build
#  CERB_INSTALL_FF=1       # Install Firefox native host manifest
#  CERB_INSTALL_CHROME=1   # Install Chrome native host manifest
#  CERB_DATA_DIR=~/.cerberus

ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
EXTRAS="${CERB_EXTRAS:-}"
VYPROJ="${ROOT_DIR}/pyproject.toml"
VENV_DIR="${ROOT_DIR}/.venv"
PIP_CMD="python3 -m pip"

info() { echo -e "\033[1;34m[cerberus]\033[0m $*"; }
warn() { echo -e "\033[1;33m[cerberus]\033[0m $*"; }
err()  { echo -e "\033[1;31m[cerberus]\033[0m $*"; }

install_playwright_browsers() {
  # If Playwright is installed in venv, install the browser binaries
  if [[ -x "${VENV_DIR}/bin/playwright" ]]; then
    info "Installing Playwright browsers (chromium, firefox, webkit)"
    "${VENV_DIR}/bin/playwright" install || warn "Playwright browser install failed; you can run '${VENV_DIR}/bin/playwright install' later"
  else
    warn "Playwright CLI not found in venv; skipping browser install"
  fi
}

install_deps() {
  # Install required system packages if a known package manager is available
  if command -v apt-get >/dev/null 2>&1; then
    info "Installing system dependencies with apt (may prompt for sudo password)"
    if command -v sudo >/dev/null 2>&1; then
      sudo apt-get update -y || true
      sudo apt-get install -y cmake build-essential libssl-dev python3-venv || true
    else
      apt-get update -y || true
      apt-get install -y cmake build-essential libssl-dev python3-venv || true
    fi
  elif command -v dnf >/dev/null 2>&1; then
    warn "dnf detected. Please install: sudo dnf install cmake gcc gcc-c++ openssl-devel python3-virtualenv"
  elif command -v yum >/dev/null 2>&1; then
    warn "yum detected. Please install: sudo yum install cmake gcc gcc-c++ openssl-devel python3-virtualenv"
  elif command -v pacman >/dev/null 2>&1; then
    warn "pacman detected. Please install: sudo pacman -S cmake base-devel openssl python-virtualenv"
  elif command -v brew >/dev/null 2>&1; then
    warn "Homebrew detected. Please install: brew install cmake openssl@3 && ensure Python venv module is available"
  else
    warn "Unknown package manager. Please install cmake, a C toolchain, OpenSSL dev headers, and python3-venv manually."
  fi
}

ensure_venv() {
  if [[ "${CERB_USE_VENV:-1}" == "1" ]]; then
    if [[ ! -d "${VENV_DIR}" ]]; then
      info "Creating virtual environment at ${VENV_DIR}"
      if ! python3 -m venv "${VENV_DIR}" 2>/dev/null; then
        err "Failed to create virtualenv. Please install python3-venv (e.g., sudo apt install python3.13-venv) and re-run."
        exit 1
      fi
    fi
    PIP_CMD="${VENV_DIR}/bin/pip"
  fi
}

pip_install() {
  local user_flag=""
  if [[ "${CERB_PIP_USER:-}" == "1" ]]; then
    user_flag="--user"
    warn "Using --user install (CERB_PIP_USER=1)"
  fi
  if [[ -n "${EXTRAS}" ]]; then
    info "Installing Python package with extras: ${EXTRAS}"
    ${PIP_CMD} install ${user_flag} -e ".[${EXTRAS}]"
  else
    info "Installing Python package (base)"
    ${PIP_CMD} install ${user_flag} -e .
  fi
}

build_c_core() {
  if [[ "${CERB_SKIP_BUILD:-}" == "1" ]]; then
    warn "Skipping C core build (CERB_SKIP_BUILD=1)"
    return
  fi
  info "Building C core with CMake"
  mkdir -p build
  (cd build && cmake .. && make -j)
  if command -v sudo >/dev/null 2>&1; then
    warn "Attempting 'make install' (may prompt for sudo password)"
    (cd build && sudo make install) || warn "'make install' failed; continuing"
  else
    warn "sudo not available; skipping 'make install'"
  fi
}

setup_native_firefox() {
  local host_bin host_manifest target
  local vhost="${VENV_DIR}/bin/cerberus-native-host"
  if [[ -x "${vhost}" ]]; then
    host_bin="${vhost}"
  else
    host_bin="$(command -v cerberus-native-host || true)"
  fi
  if [[ -z "${host_bin}" ]]; then
    err "cerberus-native-host not found on PATH; ensure pip install succeeded"
    return 1
  fi
  host_manifest="${ROOT_DIR}/native/manifests/firefox_com.cerberus.pm.json"
  target="$HOME/.mozilla/native-messaging-hosts/com.cerberus.pm.json"
  mkdir -p "$(dirname "${target}")"
  cp "${host_manifest}" "${target}"
  # Replace path in manifest
  sed -i "s#/usr/local/bin/cerberus-native-host#${host_bin//\//\\/}#" "${target}"
  info "Installed Firefox native host manifest at ${target}"
}

setup_native_chrome() {
  local host_bin target dir
  host_bin="$(command -v cerberus-native-host || true)"
  if [[ -z "${host_bin}" ]]; then
    err "cerberus-native-host not found on PATH; ensure pip install succeeded"
    return 1
  fi
  dir="$HOME/.config/google-chrome/NativeMessagingHosts"
  target="${dir}/com.cerberus.pm.json"
  mkdir -p "${dir}"
  cat > "${target}" <<EOF
{
  "name": "com.cerberus.pm",
  "description": "Cerberus Password Manager Native Messaging Host (dev)",
  "path": "${host_bin}",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://REPLACE_WITH_EXTENSION_ID/"
  ]
}
EOF
  info "Installed Chrome native host manifest at ${target}"
  warn "Replace REPLACE_WITH_EXTENSION_ID with your unpacked extension ID in chrome://extensions"
}

main() {
  info "Starting Cerberus installation"
  install_deps
  ensure_venv
  pip_install
  install_playwright_browsers
  build_c_core

  if [[ "${CERB_INSTALL_FF:-}" == "1" ]]; then
    setup_native_firefox || true
  fi
  if [[ "${CERB_INSTALL_CHROME:-}" == "1" ]]; then
    setup_native_chrome || true
  fi

  info "Done. You can run: cerberus init, cerberus tui, cerberus gui"
}

main "$@"