diff --git a/pkg/server/views/time.go b/pkg/server/views/time.go
index 88c71169..e99d36c9 100644
--- a/pkg/server/views/time.go
+++ b/pkg/server/views/time.go
@@ -1,16 +1,19 @@
-/* Copyright 2025 Dnote Authors
+/* Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024, 2025 Dnote contributors
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This file is part of Dnote.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * Dnote is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Dnote is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Dnote. If not, see
.
*/
package views
diff --git a/pkg/server/views/view.go b/pkg/server/views/view.go
index 53315334..2b0e57a9 100644
--- a/pkg/server/views/view.go
+++ b/pkg/server/views/view.go
@@ -1,16 +1,19 @@
-/* Copyright 2025 Dnote Authors
+/* Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024, 2025 Dnote contributors
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This file is part of Dnote.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * Dnote is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Dnote is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Dnote. If not, see
.
*/
package views
@@ -105,13 +108,16 @@ func (v *View) Render(w http.ResponseWriter, r *http.Request, data *Data, status
}
vd.User = context.User(r.Context())
+ vd.Account = context.Account(r.Context())
// Put user data in Yield
if vd.Yield == nil {
vd.Yield = map[string]interface{}{}
}
- if vd.User != nil {
- vd.Yield["Email"] = vd.User.Email.String
+ if vd.Account != nil {
+ vd.Yield["Email"] = vd.Account.Email.String
+ vd.Yield["EmailVerified"] = vd.Account.EmailVerified
+ vd.Yield["EmailVerified"] = vd.Account.EmailVerified
}
vd.Yield["CurrentPath"] = r.URL.Path
vd.Yield["Standalone"] = buildinfo.Standalone
diff --git a/pkg/watcher/main.go b/pkg/watcher/main.go
index 7509fb90..a548aafe 100644
--- a/pkg/watcher/main.go
+++ b/pkg/watcher/main.go
@@ -1,16 +1,19 @@
-/* Copyright 2025 Dnote Authors
+/* Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024, 2025 Dnote contributors
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This file is part of Dnote.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * Dnote is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Dnote is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dnote. If not, see
.
*/
package main
diff --git a/scripts/cli/build.sh b/scripts/cli/build.sh
index d17cb477..467f1282 100755
--- a/scripts/cli/build.sh
+++ b/scripts/cli/build.sh
@@ -36,7 +36,7 @@ if [[ $1 == v* ]]; then
exit 1
fi
-goVersion=go-1.25.x
+goVersion=go-1.21.x
get_binary_name() {
platform=$1
@@ -57,7 +57,7 @@ build() {
# build binary
destDir="$outputDir/$platform-$arch"
- ldflags="-X main.apiEndpoint=https://localhost:3001/api -X main.versionTag=$version"
+ ldflags="-X main.apiEndpoint=https://api.getdnote.com -X main.versionTag=$version"
tags="fts5"
pushd "$projectDir"
@@ -92,13 +92,13 @@ build() {
popd
binaryName=$(get_binary_name "$platform")
- mv "$destDir/cli-"* "$destDir/$binaryName"
+ mv "$destDir/cli-${platform}-"* "$destDir/$binaryName"
# build tarball
tarballName="dnote_${version}_${platform}_${arch}.tar.gz"
tarballPath="$outputDir/$tarballName"
- cp "$projectDir/LICENSE" "$destDir"
+ cp "$projectDir/licenses/GPLv3.txt" "$destDir"
cp "$basedir/README.md" "$destDir"
tar -C "$destDir" -zcvf "$tarballPath" "."
rm -rf "$destDir"
@@ -113,20 +113,10 @@ if [ -z "$GOOS" ] && [ -z "$GOARCH" ]; then
# install the tool
go install src.techknowlogick.com/xgo@latest
- # Linux
build linux amd64
build linux arm64
- build linux arm
-
- # macOS
build darwin amd64
- build darwin arm64
-
- # Windows
build windows amd64
-
- # FreeBSD
- build freebsd amd64
else
build "$GOOS" "$GOARCH" true
fi
diff --git a/scripts/cli/dev.sh b/scripts/cli/dev.sh
index d4a23e76..ce173496 100755
--- a/scripts/cli/dev.sh
+++ b/scripts/cli/dev.sh
@@ -6,6 +6,6 @@ dir=$(dirname "${BASH_SOURCE[0]}")
sudo rm -rf "$(which dnote)" "$GOPATH/bin/cli"
# change tags to darwin if on macos
-go install -ldflags "-X main.apiEndpoint=http://127.0.0.1:3001/api" --tags "linux fts5" "$dir/../../pkg/cli"
+go install -ldflags "-X main.apiEndpoint=http://127.0.0.1:3000/api" --tags "linux fts5" "$dir/../../pkg/cli"
sudo ln -s "$GOPATH/bin/cli" /usr/local/bin/dnote
diff --git a/scripts/cli/release-homebrew.sh b/scripts/cli/release-homebrew.sh
new file mode 100755
index 00000000..7e9a7bd5
--- /dev/null
+++ b/scripts/cli/release-homebrew.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+set -eux
+
+currentDir=$(dirname "${BASH_SOURCE[0]}")
+cliHomebrewDir=${currentDir}/../../homebrew-dnote
+
+if [ ! -d "$cliHomebrewDir" ]; then
+ echo "homebrew-dnote not found locally. Cloning."
+ git clone git@github.com:dnote/homebrew-dnote.git "$cliHomebrewDir"
+fi
+
+version=$1
+tarball=$2
+
+echo "version: $version"
+echo "tarball: $tarball"
+
+sha=$(shasum -a 256 "$tarball" | cut -d ' ' -f 1)
+
+pushd "$cliHomebrewDir"
+
+echo "pulling latest dnote-homebrew repo"
+git checkout master
+git pull origin master
+
+cat > ./Formula/dnote.rb << EOF
+class Dnote < Formula
+ desc "A simple command line notebook for programmers"
+ homepage "https://www.getdnote.com"
+ url "https://github.com/dnote/dnote/releases/download/cli-v${version}/dnote_${version}_darwin_amd64.tar.gz"
+ version "${version}"
+ sha256 "${sha}"
+
+ def install
+ bin.install "dnote"
+ end
+
+ test do
+ system "#{bin}/dnote", "version"
+ end
+end
+EOF
+
+git add .
+git commit --author="Bot
" -m "Release ${version}"
+git push origin master
+
+popd
diff --git a/scripts/cli/test.sh b/scripts/cli/test.sh
index 42e0ad86..e66db37a 100755
--- a/scripts/cli/test.sh
+++ b/scripts/cli/test.sh
@@ -1,5 +1,6 @@
#!/usr/bin/env bash
-# test.sh runs tests for CLI packages
+# test.sh runs test files sequentially
+# https://stackoverflow.com/questions/23715302/go-how-to-run-tests-for-multiple-packages
set -eux
dir=$(dirname "${BASH_SOURCE[0]}")
@@ -7,5 +8,7 @@ pushd "$dir/../../pkg/cli"
# clear tmp dir in case not properly torn down
rm -rf "./tmp"
-go test ./... --tags "fts5"
+go test -a ./... \
+ -p 1\
+ --tags "fts5"
popd
diff --git a/scripts/e2e/test.sh b/scripts/e2e/test.sh
index 8713bb89..240d5c97 100755
--- a/scripts/e2e/test.sh
+++ b/scripts/e2e/test.sh
@@ -4,6 +4,10 @@ set -eux
dir=$(dirname "${BASH_SOURCE[0]}")
basePath=$(realpath "$dir/../../")
+set -a
+source "$basePath/pkg/server/.env.test"
+set +a
+
pushd "$basePath"/pkg/e2e
-go test --tags "fts5" ./... -v -timeout 5m
+go test --tags "fts5" ./... -p 1
popd
diff --git a/scripts/generate-changelog.sh b/scripts/generate-changelog.sh
deleted file mode 100755
index 8f24a8ec..00000000
--- a/scripts/generate-changelog.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-set -e
-
-# Usage: ./generate-changelog.sh
-# Example: ./generate-changelog.sh cli cli-v0.15.2 cli-v0.15.1
-
-COMPONENT=$1
-CURRENT_TAG=$2
-PREV_TAG=$3
-
-if [ -z "$COMPONENT" ] || [ -z "$CURRENT_TAG" ]; then
- echo "Usage: $0 [previous-tag]"
- echo "Example: $0 cli cli-v0.15.2 cli-v0.15.1"
- exit 1
-fi
-
-# Validate that tags match the component
-if [[ ! "$CURRENT_TAG" =~ ^${COMPONENT}- ]]; then
- echo "Error: Current tag '$CURRENT_TAG' doesn't match component '$COMPONENT'"
- echo "Expected tag to start with '${COMPONENT}-'"
- exit 1
-fi
-
-if [ -n "$PREV_TAG" ] && [[ ! "$PREV_TAG" =~ ^${COMPONENT}- ]]; then
- echo "Error: Previous tag '$PREV_TAG' doesn't match component '$COMPONENT'"
- echo "Expected tag to start with '${COMPONENT}-'"
- exit 1
-fi
-
-# Define paths for each component
-# Shared paths that apply to both components
-SHARED_PATHS="pkg/dirs/"
-
-if [ "$COMPONENT" == "cli" ]; then
- FILTER_PATHS="pkg/cli/ cmd/cli/ $SHARED_PATHS"
-elif [ "$COMPONENT" == "server" ]; then
- FILTER_PATHS="pkg/server/ host/ $SHARED_PATHS"
-else
- echo "Unknown component: $COMPONENT"
- echo "Valid components: cli, server"
- exit 1
-fi
-
-# Determine commit range
-if [ -z "$PREV_TAG" ]; then
- echo "Error: No previous tag specified"
- exit 1
-fi
-
-RANGE="$PREV_TAG..$CURRENT_TAG"
-
-# Get all commits that touched the relevant paths
-# Warnings go to stderr (visible in logs), commits go to stdout (captured for file)
-COMMITS=$(
- for path in $FILTER_PATHS; do
- git log --oneline --no-merges --pretty=format:"- %s%n" "$RANGE" -- "$path" 2>&2
- done | sort -u | grep -v "^$"
-)
-
-echo "## What's Changed"
-echo ""
-echo "$COMMITS"
diff --git a/scripts/license.sh b/scripts/license.sh
index 4f7788e4..d75b656b 100755
--- a/scripts/license.sh
+++ b/scripts/license.sh
@@ -1,46 +1,75 @@
#!/usr/bin/env bash
set -eux
-function has_license {
- # Check if file already has a copyright notice
- grep -q "Copyright.*Dnote Authors" "$1"
+function remove_notice {
+ sed -i -e '/\/\* Copyright/,/\*\//d' "$1"
+
+ # remove leading newline
+ sed -i '/./,$!d' "$1"
}
function add_notice {
ed "$1" <.
+ */"
+
+agpl="/* Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024, 2025 Dnote contributors
+ *
+ * This file is part of Dnote.
+ *
+ * Dnote is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dnote is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Dnote. If not, see .
*/"
dir=$(dirname "${BASH_SOURCE[0]}")
basedir="$dir/.."
pkgPath="$basedir/pkg"
+serverPath="$basedir/pkg/server"
-# Apply license to all source files
-allFiles=$(find "$pkgPath" -type f \( -name "*.go" -o -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.scss" -o -name "*.css" \) ! -path "**/vendor/*" ! -path "**/node_modules/*" ! -path "**/dist/*")
+gplFiles=$(find "$pkgPath" -type f \( -name "*.go" -o -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.scss" -o -name "*.css" \) ! -path "**/vendor/*" ! -path "**/node_modules/*" ! -path "$serverPath/*")
-for file in $allFiles; do
- if ! has_license "$file"; then
- add_notice "$file" "$license"
- fi
+for file in $gplFiles; do
+ remove_notice "$file"
+ add_notice "$file" "$gpl"
+done
+
+agplFiles=$(find "$serverPath" -type f \( -name "*.go" -o -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.scss" -o -name "*.css" \) ! -path "**/vendor/*" ! -path "**/node_modules/*" ! -path "**/dist/*")
+
+for file in $agplFiles; do
+ remove_notice "$file"
+ add_notice "$file" "$agpl"
done
diff --git a/scripts/release.sh b/scripts/release.sh
new file mode 100755
index 00000000..3cda5897
--- /dev/null
+++ b/scripts/release.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+#
+# release.sh releases the tarballs and checksum in the build directory
+# to GitHub and brew. A prerequisite is to build those files using build.sh.
+# use: ./scripts/release.sh cli v0.4.8 path/to/assets
+
+set -euxo pipefail
+
+project=$1
+version=$2
+assetPath=$3
+
+if [ "$project" != "cli" ] && [ "$project" != "server" ]; then
+ echo "unrecognized project '$project'"
+ exit 1
+fi
+if [ -z "$version" ]; then
+ echo "no version specified."
+ exit 1
+fi
+if [[ $version == v* ]]; then
+ echo "do not prefix version with v"
+ exit 1
+fi
+
+# 1. push tag
+version_tag="$project-v$version"
+
+echo "* tagging and pushing the tag"
+git tag -a "$version_tag" -m "Release $version_tag"
+git push --tags
+
+# 2. release on GitHub
+files=("$assetPath"/*)
+file_flags=()
+for file in "${files[@]}"; do
+ file_flags+=("$file")
+done
+
+# mark as prerelease if version is not in a form of major.minor.patch
+# e.g. 1.0.1-beta.1
+flags=()
+if [[ ! "$version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then
+ flags+=("--prerelease")
+fi
+
+echo "* creating release"
+set -x
+
+# Create release
+gh release create \
+ "$version_tag" \
+ "${file_flags[@]}" \
+ "${flags[@]}" \
+ --title="$version_tag"\
+ --notes="Please see the [CHANGELOG](https://github.com/dnote/dnote/blob/master/CHANGELOG.md)" \
+ --draft
diff --git a/scripts/server/build.sh b/scripts/server/build.sh
index 09bc16e3..a4e24df5 100755
--- a/scripts/server/build.sh
+++ b/scripts/server/build.sh
@@ -51,13 +51,13 @@ build() {
popd
- mv "$destDir/server-${platform}"* "$destDir/dnote-server"
+ mv "$destDir/server-${platform}-"* "$destDir/dnote-server"
# build tarball
tarballName="dnote_server_${version}_${platform}_${arch}.tar.gz"
tarballPath="$outputDir/$tarballName"
- cp "$projectDir/LICENSE" "$destDir"
+ cp "$projectDir/licenses/AGPLv3.txt" "$destDir"
cp "$basedir/README.md" "$destDir"
tar -C "$destDir" -zcvf "$tarballPath" "."
rm -rf "$destDir"
@@ -74,6 +74,3 @@ go install src.techknowlogick.com/xgo@latest
build linux amd64
build linux arm64
-build linux arm
-build linux 386
-build freebsd amd64
diff --git a/scripts/server/dev.sh b/scripts/server/dev.sh
index 3786f270..5eb93328 100755
--- a/scripts/server/dev.sh
+++ b/scripts/server/dev.sh
@@ -7,8 +7,11 @@ dir=$(dirname "${BASH_SOURCE[0]}")
basePath="$dir/../.."
serverPath="$basePath/pkg/server"
-# Set env
-DBPath=../../dev-server.db
+# load env
+set -a
+dotenvPath="$serverPath/.env.dev"
+source "$dotenvPath"
+set +a
# copy assets
mkdir -p "$basePath/pkg/server/static"
@@ -20,7 +23,7 @@ cp "$basePath"/pkg/server/assets/static/* "$basePath/pkg/server/static"
# run server
moduleName="github.com/dnote/dnote"
ldflags="-X '$moduleName/pkg/server/buildinfo.CSSFiles=main.css' -X '$moduleName/pkg/server/buildinfo.JSFiles=main.js' -X '$moduleName/pkg/server/buildinfo.Version=dev' -X '$moduleName/pkg/server/buildinfo.Standalone=true'"
-task="go run -ldflags \"$ldflags\" --tags fts5 main.go start -port 3001"
+task="go run -ldflags \"$ldflags\" --tags fts5 main.go start -port 3000"
(
cd "$basePath/pkg/watcher" && \
diff --git a/scripts/server/test-local.sh b/scripts/server/test-local.sh
index 504ef444..ce50d7d6 100755
--- a/scripts/server/test-local.sh
+++ b/scripts/server/test-local.sh
@@ -5,4 +5,8 @@ set -ex
dir=$(dirname "${BASH_SOURCE[0]}")
+set -a
+source "$dir/../../pkg/server/.env.test"
+set +a
+
"$dir/test.sh" "$1"
diff --git a/scripts/vagrant/bootstrap.sh b/scripts/vagrant/bootstrap.sh
new file mode 100755
index 00000000..b8299676
--- /dev/null
+++ b/scripts/vagrant/bootstrap.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -ex
+
+echo "export DNOTE=/go/src/github.com/dnote/dnote" >> /home/vagrant/.bash_profile
+echo "cd /go/src/github.com/dnote/dnote" >> /home/vagrant/.bash_profile
+
+# install dependencies
+(cd /go/src/github.com/dnote/dnote && make install)
+
+# set up database
+sudo -u postgres createdb dnote
+sudo -u postgres createdb dnote_test
+sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
+
+# allow connection from host and allow to connect without password
+sudo sed -i "/port*/a listen_addresses = '*'" /etc/postgresql/14/main/postgresql.conf
+sudo sed -i 's/host.*all.*.all.*md5/# &/' /etc/postgresql/14/main/pg_hba.conf
+sudo sed -i "$ a host all all all trust" /etc/postgresql/14/main/pg_hba.conf
+sudo service postgresql restart
diff --git a/scripts/vagrant/install_go.sh b/scripts/vagrant/install_go.sh
new file mode 100755
index 00000000..4dc0c1b0
--- /dev/null
+++ b/scripts/vagrant/install_go.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# shellcheck disable=SC1091
+set -eux
+
+VERSION=1.21
+OS=linux
+ARCH=amd64
+
+tarball=go$VERSION.$OS-$ARCH.tar.gz
+
+wget -q https://dl.google.com/go/"$tarball"
+sudo tar -C /usr/local -xzf "$tarball"
+sudo tar -xf "$tarball"
+
+sudo mkdir -p /go/src
+sudo mkdir -p /go/bin
+sudo mkdir -p /go/pkg
+sudo chown -R vagrant:vagrant /go
+
+GOPATH=/go
+echo "export GOPATH=$GOPATH" >> /home/vagrant/.bash_profile
+echo "export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin" >> /home/vagrant/.bash_profile
+source /home/vagrant/.bash_profile
+
+go version
+go env
diff --git a/scripts/vagrant/install_node.sh b/scripts/vagrant/install_node.sh
new file mode 100755
index 00000000..1233d449
--- /dev/null
+++ b/scripts/vagrant/install_node.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# shellcheck disable=SC1090,SC1091
+set -eux
+
+VERSION=12.16.2
+NVM_VERSION=v0.35.0
+
+# Install nvm
+wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/"$NVM_VERSION"/install.sh | bash
+cat >> /home/vagrant/.bash_profile<< EOF
+export NVM_DIR="\$([ -z "\${XDG_CONFIG_HOME-}" ] && printf %s "\${HOME}/.nvm" || printf %s "\${XDG_CONFIG_HOME}/nvm")"
+[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh" # This loads nvm
+EOF
+source /home/vagrant/.bash_profile
+
+# Install a node and alias
+nvm install --no-progress "$VERSION" 1>/dev/null
+nvm alias default "$VERSION"
+nvm use default
diff --git a/scripts/vagrant/install_postgres.sh b/scripts/vagrant/install_postgres.sh
new file mode 100755
index 00000000..f2738021
--- /dev/null
+++ b/scripts/vagrant/install_postgres.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -ex
+
+sudo apt-get -y install wget ca-certificates
+wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
+sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
+
+sudo apt-get update
+sudo apt-get install -y postgresql-14
diff --git a/scripts/vagrant/install_utils.sh b/scripts/vagrant/install_utils.sh
new file mode 100755
index 00000000..46322005
--- /dev/null
+++ b/scripts/vagrant/install_utils.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+set -eux
+
+sudo apt-get update
+sudo apt-get install -y htop git wget build-essential inotify-tools
+
+# Install Chrome
+wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add
+echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | sudo tee /etc/apt/sources.list.d/google-chrome.list
+sudo apt-get -y update
+sudo apt-get install -y google-chrome-stable
+
+# Install dart-sass
+dart_version=1.34.1
+dart_tarball="dart-sass-$dart_version-linux-x64.tar.gz"
+wget -q "https://github.com/sass/dart-sass/releases/download/$dart_version/$dart_tarball"
+tar -xvzf "$dart_tarball" -C /tmp/
+sudo install /tmp/dart-sass/sass /usr/bin