WSL Proxy Setup
This is just a quick little instructional for setting up apt-cacher-ng and Nexus Repository 3 on a WSL2 Debian distro.
Proxy Creation
Install the distro from the app store and run once to create a default user. Then execute the following on the distro (cut and paste into a shell script, terminal, or whatever it is you like to do).
sudo apt update
sudo apt -y --no-install-recommends install curl gnupg software-properties-common
URL=https://github.com/DamionGans/ubuntu-wsl2-systemd-script/archive/master.tar.gz
curl -kL ${URL} --output - | tar zxvf -
cd ./ubuntu-wsl2-systemd-script-master/
bash ./ubuntu-wsl2-systemd-script.sh
URL=https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public
curl -kL ${URL} --output - | sudo apt-key add -
sudo add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
sudo apt update
sudo apt -y install apt-cacher-ng adoptopenjdk-8-hotspot-jre
sudo cp /lib/systemd/system/apt-cacher-ng.service /etc/systemd/system/apt-cacher-ng.service
sudo sed -i '/^ExecStart=/ s/$/ DontCache=".*localhost.*"/' /etc/systemd/system/apt-cacher-ng.service
cd /opt
URL=https://download.sonatype.com/nexus/3/latest-unix.tar.gz
curl -kL ${URL} --output - | sudo tar zxf -
sudo mv /opt/nexus-* /opt/nexus
NEXUS_DATA=/opt/sonatype-work/nexus3
sudo useradd -r -m -c "nexus role account" -d ${NEXUS_DATA} -s /bin/false nexus
sudo chown -R nexus:nexus ${NEXUS_DATA}
cd ~
cat > ~/nexus.service << EOF
[Unit]
Description=nexus service
After=network.target
[Service]
Type=forking
LimitNOFILE=65536
ExecStart=/opt/nexus/bin/nexus start
ExecStop=/opt/nexus/bin/nexus stop
User=nexus
Restart=on-abort
TimeoutSec=600
[Install]
WantedBy=multi-user.target
EOF
sudo mv ~/nexus.service /etc/systemd/system/
sudo chmod 0644 /etc/systemd/system/nexus.service
sudo systemctl enable nexus
Exit and restart the distro.
That was the primary setup, now we'll create the nexus repositories for the CRAN binaries and RStudio Package Manager binaries.
Repository Creation
Start the Debian distro again.
# Wait for Nexus startup to complete.
sed "/^Started Sonatype Nexus.*$/ q" <(tail -f /opt/sonatype-work/nexus3/log/nexus.log)
REPO_JSON_PATH="/tmp/repo.json"
cat > ${REPO_JSON_PATH} << \EOF
{
"name": "focal-cran-4.0-proxy",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"cleanup": null,
"proxy": {
"remoteUrl": "https://cloud.r-project.org/bin/linux/ubuntu",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true,
"connection": {
"retries": 0,
"userAgentSuffix": "string",
"timeout": 60,
"enableCircularRedirects": false,
"enableCookies": false
}
},
"routingRule": "string",
"apt": {
"distribution": "focal-cran40",
"flat": false
}
}
EOF
curl "http://localhost:8081/service/rest/beta/repositories/apt/proxy" \
-vvv --user admin:$(cat /opt/sonatype-work/nexus3/admin.password) \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d @${REPO_JSON_PATH}
REPO_JSON_PATH="/tmp/repo.json"
cat > ${REPO_JSON_PATH} << \EOF
{
"name": "focal-rspm-4.0-binary",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"cleanup": null,
"proxy": {
"remoteUrl": "https://packagemanager.rstudio.com/all/__linux__/focal/latest",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true,
"connection": {
"retries": 0,
"userAgentSuffix": "R/4.0.2 R (4.0.2 x86_64-pc-linux-gnu x86_64 linux-gnu)",
"timeout": 20,
"enableCircularRedirects": false,
"enableCookies": true
}
},
"routingRule": "string"
}
EOF
curl "http://localhost:8081/service/rest/beta/repositories/r/proxy" \
-vvv --user admin:$(cat /opt/sonatype-work/nexus3/admin.password) \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d @${REPO_JSON_PATH}
That's it. You can now exit the distro and the services will continue running and they will start with the distro when it is started thanks to systemd.
Client Apt Setup.
Using an Ubuntu distro from the app store that has an sudoer user...
# Apt proxy setup.
cat > ~/wsl-apt-proxy << \EOF
#!/bin/bash
# Executed as part of apt.conf.d/00-wsl-apt-proxy
WSL_HOST_IP=localhost
exec 9<>/dev/tcp/${WSL_HOST_IP}/3142
STATUS=$?
exec 9>&-
if [ "X$STATUS" = "X0" ]; then
echo "http://${WSL_HOST_IP}:3142"
else
echo "DIRECT"
fi
EOF
sudo chown root:root wsl-apt-proxy
sudo mv ~/wsl-apt-proxy /usr/sbin/
sudo chmod +x /usr/sbin/wsl-apt-proxy
echo 'Acquire::http::Proxy-Auto-Detect "/usr/sbin/wsl-apt-proxy";' | sudo tee /etc/apt/apt.conf.d/00-wsl-apt-proxy
sudo apt-add-repository "deb http://localhost:8081/repository/focal-cran-4.0-proxy focal-cran40/"
R-Client Config
there isn't much to do here... Just use whatever method you prefer to ensure you're setting your repo to fetch from nexus.
options(repos = c(nexus = "http://localhost:8081/repository/focal-rspm-4.0-binary/"))
Testing it out.
In a different terminal (or tab) start a session that will monitor the logs.
wsl -d Debian -- tail -f /var/log/apt-cacher-ng/apt-cacher.log /var/log/apt-cacher-ng/apt-cacher.err /opt/sonatype-work/nexus3/log/request.log
Ubuntu client usage testing.
sudo apt update
sudo apt -y upgrade
sudo apt -y install r-base
# An install.packages call that will cache the packages.
mkdir -p ~/R-cache-test
R --quiet -e 'options(repos = c(nexus = "http://localhost:8081/repository/focal-rspm-4.0-binary/"));
sw.start <- Sys.time(); install.packages("usethis", lib="~/R-cache-test", quiet=TRUE); sw.end <- Sys.time(); sw.end - sw.start'
# An install.packages call that will use the cached packages.
rm -Rf ~/R-cache-test/*
R --quiet -e 'options(repos = c(nexus = "http://localhost:8081/repository/focal-rspm-4.0-binary/"));
sw.start <- Sys.time(); install.packages("usethis", lib="~/R-cache-test", quiet=TRUE); sw.end <- Sys.time(); sw.end - sw.start'
At this point you should have seen the log monitor show that apt-cacher-ng and nexus are both working.
You should, also, have noted improved install times.
Explore the control interface and documentation for nexus to setup other proxies.