shared cache for flutter pub packages.

This commit is contained in:
Thomas SharedInbox
2026-05-16 00:12:12 +02:00
parent 7fa19dd39a
commit c21d198a25
2 changed files with 298 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
# Development Environment Setup
This document explains how to set up a development environment for SharedInbox.
## ⚠️ Security Recommendation: Use a Dedicated Linux User
For enhanced security, especially when working with autonomous coding agents (like Gemini CLI in YOLO mode), we **strongly recommend** using a dedicated Linux user for this project. This isolates the project environment and prevents any potential accidental damage to your main system.
### 1. Create a Dedicated User
Set the user name variable (default is `si` for SharedInbox):
```bash
export DEV_USER=si
```
Create the user and add them to the `sudo` group:
```bash
sudo adduser --disabled-password newuser $DEV_USER
```
Set up SSH public key login (replace with your actual public key):
```bash
sudo mkdir -p /home/$DEV_USER/.ssh
sudo chmod 700 /home/$DEV_USER/.ssh
echo "ssh-ed25519 AAAA... your-key-comment" | sudo tee /home/$DEV_USER/.ssh/authorized_keys
sudo chmod 600 /home/$DEV_USER/.ssh/authorized_keys
sudo chown -R $DEV_USER:$DEV_USER /home/$DEV_USER/.ssh
```
### 2. Switch to the Dedicated User
```bash
ssh $DEV_USER@localhost
```
### Create ssh-keypair
```bash
ssh-keygen
```
### 3. Clone the Repository
Clone the project into your new user's home directory:
```bash^
git clone ssh://git@codeberg.org/guettli/sharedinbox.git
# Move git directory into $HOME
# This user only works on the git repo. Avoid "cd sharedinbox" after each login...
mv sharedinbox/* .
mv sharedinbox/.??* .
rmdir sharedinbox/
```
### 3b. Configure Git Identity
The new user needs a Git identity for commits and some scripts:
```bash
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
```
### 4. Install System Dependencies
This project uses **Nix** with flakes to manage its toolchain (Flutter, Dart, Stalwart, etc.).
```
mkdir -p .config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
nix profile add nixpkgs#direnv
nix profile add nixpkgs#nix-direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
source ~/.bashrc
.config/direnv/direnv.toml
```
[global]
hide_env_diff = true
#log_filter = "^$"
[whitelist]
prefix = [ "/home/DEV_USER-CHANGE_THAT" ]
```
### 4b. Additional Permissions (GUI & Android)
1. **GUI Access**: To run the Linux app (`task run`) from the `si` user, you must allow it to access your X server. Run this **from your main user terminal**:
```bash
xhost +local:$DEV_USER
```
2. **Android Emulator (KVM)**: If you plan to use the Android emulator, add the user to the `kvm` group:
```bash
sudo usermod -aG kvm $DEV_USER
```
### 5. Project Setup
Once you are in the project directory and have the dependencies installed:
1. **Initialize Environment**:
```bash
cp .env.example .env
```
2. **Allow direnv**:
```bash
direnv allow
```
*This will trigger Nix to download and set up the environment (Flutter, Android SDK, etc.). It might take some time on the first run.*
3. **Install Flutter (via FVM)**:
Nix provides FVM, which manages the pinned Flutter version.
```bash
fvm install
```
4. **Initial Setup**:
Run the comprehensive setup command which handles `pub get`, code generation, and git hooks:
```bash
task setup
```
### 6. Verify the Setup
Run the full check suite to ensure everything is working correctly:
```bash
task check
```
### 7. Running the App
To run the app on your Linux desktop:
```bash
task run
```
---
## Working with VS Code
To maintain isolation, it is recommended to run VS Code "remotely" on the dedicated development user.
### Preferred Method: VS Code Remote - SSH
The most robust way to work with a separate user is using the **VS Code Remote - SSH** extension. This allows you to run the VS Code Server as the `si` user while using your main user's GUI.
1. **Install the Extension**: Install "Remote - SSH" from the VS Code Marketplace.
2. **Enable SSH for the Dev User**:
From your main user, copy your SSH public key to the dev user:
```bash
# As your main user:
sudo mkdir -p /home/$DEV_USER/.ssh
sudo cp ~/.ssh/id_rsa.pub /home/$DEV_USER/.ssh/authorized_keys
sudo chown -R $DEV_USER:$DEV_USER /home/$DEV_USER/.ssh
sudo chmod 700 /home/$DEV_USER/.ssh
sudo chmod 600 /home/$DEV_USER/.ssh/authorized_keys
```
3. **Connect**:
In VS Code, open the Command Palette (`Ctrl+Shift+P`) and select `Remote-SSH: Connect to Host...`.
Enter: `si@localhost` (or `$DEV_USER@localhost`).
4. **Install Extensions in the Remote**:
Once connected, you will need to install the following extensions *on the remote user*:
* **Dart** / **Flutter**
* **direnv**: (by mkhl) Highly recommended to automatically load the Nix environment inside VS Code.
* **Nix IDE**: For syntax highlighting.
### Why SSH?
Using SSH to `localhost` is preferred over complex X11/Wayland permission hacks. It provides a clean boundary for the VS Code process and any integrated terminal or coding agents, ensuring they cannot access your personal files in `/home/$YOUR_USER`.
> **Note on Security:** While these instructions add the user to the `sudo` group for convenience during setup, you can remove it later with `sudo gpasswd -d $DEV_USER sudo` to further restrict the user and any coding agents.
---
## Daily Workflow
Refer to the [README.md](./README.md#daily-workflow) for common development tasks and commands.
+108
View File
@@ -0,0 +1,108 @@
# Shared Flutter & Dart Pub Cache Configuration
This guide provides the instructions to configure a centralized, robust `pub-cache` for a Linux
environment acting as both a local development workstation and a Dagger CI runner.
The `pub-cache` is the local directory where Dart and Flutter store downloaded packages
(dependencies) fetched from `pub.dev` or other package repositories. By default, it resides in
`~/.pub-cache` (or `~/.local/share/pub-cache` on some Linux setups) for each individual user. When
multiple users or CI runners operate on the same machine, they end up downloading the same packages
redundantly, wasting disk space and network bandwidth.
This setup aggressively prevents permission drift between local user accounts and CI service
accounts. It also strictly forbids `pub global activate` via OS-level directory permissions to
guarantee a 100% collision-free environment, effectively forcing
roject-level dependency
management.
---
## Prerequisites
- Root (`sudo`) access to the Linux host machine.
- The `acl` package installed (standard on most modern distributions like Ubuntu).
## Step 1: Create the Dedicated Group and Directory
Establish a shared user group for all human developers and CI service accounts, and provision the
central cache directory.
```bash
# Create the shared group
sudo groupadd flutter-devs
# Add your local user to the group
sudo usermod -aG flutter-devs $USER
# Add the CI runner service account to the group (e.g., 'dagger' or 'gitlab-runner')
# sudo usermod -aG flutter-devs <ci-service-user>
# Create the centralized cache directory in /opt
sudo mkdir -p /opt/pub-cache
sudo chown root:flutter-devs /opt/pub-cache
Step 2: Enforce Strict Group Permissions (ACLs)
Standard Linux permissions result in the creator of a file owning it exclusively. To prevent permission drift when Dagger or the local user pulls dependencies, apply Access Control Lists (ACLs). This forces all newly created subdirectories and files to inherit read, write, and execute permissions for the flutter-devs group.
Bash
# Set the SetGID bit so new files inherit the 'flutter-devs' group
sudo chmod 2775 /opt/pub-cache
# Apply default ACLs to enforce rwx for the group on all future files/folders
sudo setfacl -d -m g:flutter-devs:rwx /opt/pub-cache
# Apply the same ACLs to the directory itself immediately
sudo setfacl -m g:flutter-devs:rwx /opt/pub-cache
Step 3: Export the Environment Variable
You must instruct Dart and Flutter to utilize this central location instead of the default ~/.pub-cache.
A. Global Host Setup
For system-wide application, drop an environment script into /etc/profile.d/.
Bash
echo 'export PUB_CACHE=/opt/pub-cache' | sudo tee /etc/profile.d/flutter-pub-cache.sh
echo 'export PATH="$PATH:$PUB_CACHE/bin"' | sudo tee -a /etc/profile.d/flutter-pub-cache.sh
(Note: Users will need to log out and log back in, or source the profile, for this to take effect).
B. Dagger Pipeline Integration (Go SDK)
When writing your Dagger pipeline controller, mount the host directory directly into the container so the CI runner uses the identical cache pool:
Go
// In your Dagger CI logic, mount the shared host cache into the container
WithMountedDirectory("/root/.pub-cache", dag.Host().Directory("/opt/pub-cache")).
WithEnvVariable("PUB_CACHE", "/root/.pub-cache")
Step 4: The 100% Strict Lockdown for Global Activations
Running dart pub global activate <package> in a shared cache causes severe conflicts by overwriting global executables. To guarantee this never happens, we revoke write access to the specific global activation subdirectories.
By implementing this OS-level constraint, any attempt to globally activate a package—regardless of multiline bash scripts, variables, or clever aliases—will be unconditionally rejected by the Linux kernel with a Permission denied error. Standard pub get commands for project dependencies will continue working without issue.
Bash
# Ensure the target subdirectories exist
sudo mkdir -p /opt/pub-cache/bin
sudo mkdir -p /opt/pub-cache/global_packages
# Change ownership of exclusively these two directories to root
sudo chown root:root /opt/pub-cache/bin
sudo chown root:root /opt/pub-cache/global_packages
# Remove write permissions for everyone else
sudo chmod 755 /opt/pub-cache/bin
sudo chmod 755 /opt/pub-cache/global_packages
Developer Workflow Impact
Because global activations are now entirely disabled on this host, developers and CI scripts must manage CLI tools locally.
If a tool like melos, slidy, or coverage is required:
Add it to the dev_dependencies of your pubspec.yaml.
Invoke it project-locally using dart run <package_name>.