shared cache for flutter pub packages.
This commit is contained in:
+190
@@ -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.
|
||||
@@ -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>.
|
||||
Reference in New Issue
Block a user