9 Commits

Author SHA1 Message Date
f2d42751fd Added systemd unit
All checks were successful
Build and Publish Deb Package / build-deb (push) Successful in 33s
Publish Server Image / build-and-push-image (push) Successful in 9m16s
2026-03-13 16:42:44 +00:00
bc34b6bc41 Added systemd unit
All checks were successful
Build and Publish Deb Package / build-deb (push) Successful in 2m17s
Publish Server Image / build-and-push-image (push) Successful in 4m35s
2026-03-13 16:31:58 +00:00
3ee7235b51 Fixed deb CI
Some checks failed
Build and Publish Deb Package / build-deb (push) Successful in 1m19s
Publish Server Image / build-and-push-image (push) Has been cancelled
2026-03-13 16:18:08 +00:00
1f85d9c435 Fixed deb CI
Some checks failed
Build and Publish Deb Package / build-deb (push) Failing after 1m58s
Publish Server Image / build-and-push-image (push) Has been cancelled
2026-03-13 16:12:53 +00:00
773e9c1ee7 Added deb build
Some checks failed
Build and Publish Deb Package / build-deb (push) Failing after 9m5s
Publish Server Image / build-and-push-image (push) Has been cancelled
2026-03-13 15:54:08 +00:00
0242376a65 Added deb build
Some checks failed
Build and Publish Deb Package / build-deb (push) Has been cancelled
Publish Server Image / build-and-push-image (push) Has been cancelled
2026-03-13 15:52:17 +00:00
Ultradesu
64f292c7b1 Added win client plan 2026-03-11 14:28:10 +00:00
ab
73b6d7483e Update README.md 2026-03-11 14:17:07 +00:00
Ultradesu
64b59ba72d fix macos clinet unmounting 2026-03-11 10:42:19 +00:00
9 changed files with 208 additions and 13 deletions

63
.github/workflows/deb-publish.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Build and Publish Deb Package
on:
push:
tags:
- 'v*.*.*'
jobs:
build-deb:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Enable universe and install dependencies
run: |
sudo add-apt-repository universe -y
sudo apt-get update
sudo apt-get install -y fuse3 libfuse3-dev pkg-config protobuf-compiler cmake
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Install cargo-deb
run: cargo install cargo-deb --locked
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Build deb package
run: |
cargo deb -p furumi-mount-linux \
--deb-version ${{ steps.version.outputs.version }}
- name: Locate deb file
id: deb
run: |
DEB=$(ls target/debian/furumi-mount-linux_*.deb | head -1)
echo "path=$DEB" >> "$GITHUB_OUTPUT"
echo "name=$(basename $DEB)" >> "$GITHUB_OUTPUT"
- name: Publish to Gitea APT registry
run: |
TARGET_URL="${{ secrets.PKG_REGISTRY_URL }}/api/packages/${{ secrets.PKG_OWNER }}/debian/pool/noble/main/upload"
echo "Uploading to: $TARGET_URL"
curl --fail-with-body \
--user "${{ secrets.PKG_USER }}:${{ secrets.PKG_TOKEN }}" \
--upload-file "${{ steps.deb.outputs.path }}" \
"$TARGET_URL"

8
Cargo.lock generated
View File

@@ -585,7 +585,7 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "furumi-client-core"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"anyhow",
"async-trait",
@@ -607,7 +607,7 @@ dependencies = [
[[package]]
name = "furumi-common"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"prost",
"protobuf-src",
@@ -617,7 +617,7 @@ dependencies = [
[[package]]
name = "furumi-mount-linux"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"anyhow",
"clap",
@@ -634,7 +634,7 @@ dependencies = [
[[package]]
name = "furumi-mount-macos"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"anyhow",
"async-trait",

View File

@@ -27,13 +27,7 @@ cargo build --release --workspace
--token mysecrettoken \
--tls-cert-out /tmp/furumi-ca.pem
# Client (Linux) — automatically uses TLS, trusts server certificate
./target/release/furumi-mount-linux \
--server server-ip:50051 \
--token mysecrettoken \
--mount /mnt/remote
# Client (macOS)
# Client
./target/release/furumi-mount-macos \
--server server-ip:50051 \
--token mysecrettoken \
@@ -44,6 +38,12 @@ ls /mnt/remote
mpv /mnt/remote/video.mkv
```
### Linux FUSE3
Linux client uses FUSE. Install with:
```
sudo add-apt-repository universe
sudo apt install libfuse3-dev
```
## Encryption
TLS is enabled by default. The server auto-generates a self-signed certificate on each start — no manual cert management required. The client automatically trusts the server's certificate for encryption.

View File

@@ -15,3 +15,16 @@ tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
tokio = { version = "1.50.0", features = ["full"] }
tokio-stream = "0.1.18"
ctrlc = "3.5.2"
[package.metadata.deb]
maintainer = "Furumi"
copyright = "Furumi contributors"
extended-description = "Furumi-ng: mount remote filesystem via encrypted gRPC + FUSE"
depends = "fuse3"
section = "utils"
priority = "optional"
maintainer-scripts = "debian/"
assets = [
{ source = "target/release/furumi-mount-linux", dest = "usr/bin/furumi-mount-linux", mode = "755" },
{ source = "debian/furumi-mount.service", dest = "usr/lib/systemd/user/furumi-mount.service", mode = "644" },
]

View File

@@ -0,0 +1,15 @@
[Unit]
Description=Furumi remote filesystem mount
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=%h/.config/furumi/config
ExecStart=/usr/bin/furumi-mount-linux
ExecStopPost=fusermount3 -uz ${FURUMI_MOUNT}
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target

View File

@@ -0,0 +1,36 @@
#!/bin/bash
set -e
if [ "$1" = "configure" ]; then
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
REAL_USER="$SUDO_USER"
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
CONFIG_DIR="$REAL_HOME/.config/furumi"
CONFIG_FILE="$CONFIG_DIR/config"
if [ ! -f "$CONFIG_FILE" ]; then
mkdir -p "$CONFIG_DIR"
cat > "$CONFIG_FILE" << 'EOF'
# Furumi mount configuration
# Edit the values below, then enable and start the service:
#
# systemctl --user enable --now furumi-mount.service
#
# To apply changes after editing this file:
#
# systemctl --user restart furumi-mount.service
FURUMI_SERVER=your-server:50051
FURUMI_TOKEN=your-token-here
FURUMI_MOUNT=/path/to/mountpoint
EOF
chown -R "$REAL_USER:$REAL_USER" "$CONFIG_DIR"
echo ""
echo "furumi-mount: config created at $CONFIG_FILE"
echo "furumi-mount: edit the file, then run:"
echo " systemctl --user enable --now furumi-mount.service"
echo ""
fi
fi
fi

View File

@@ -57,7 +57,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
};
let client = rt.block_on(async {
FurumiClient::connect(&full_addr, &args.token).await
let c = FurumiClient::connect(&full_addr, &args.token).await?;
// Ping the server to verify connection and authentication token
if let Err(e) = c.get_attr("/").await {
return Err(format!("Failed to authenticate or connect to server: {}", e).into());
}
Ok::<_, Box<dyn std::error::Error>>(c)
})?;
let fuse_fs = fs::FurumiFuse::new(client, rt.handle().clone());

View File

@@ -116,7 +116,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
// Unmount
let _ = Command::new("umount").arg(mount_point_umount.to_string_lossy().as_ref()).status();
let _ = Command::new("diskutil")
.arg("unmount")
.arg("force")
.arg(mount_point_umount.to_string_lossy().as_ref())
.status();
handle.abort();
println!("Unmounted successfully.");
});

View File

@@ -0,0 +1,56 @@
# Implementation Plan for `furumi-mount-windows` Client
## Architectural Decision
- **VFS Driver:** `WinFSP` (Windows File System Proxy).
- **Justification:** Excellent performance, perfect compatibility with the FUSE model, widely used in similar projects (e.g., rclone, sshfs-win).
- **Installation:** A unified installer (bundle) will be created (for example, using Inno Setup or WiX Toolkit), which will:
- Check if WinFSP is already installed.
- Automatically install the official `winfsp.msi` silently (using `/qn` flags) if the driver is missing.
- Install the `furumi-mount-windows.exe` client itself.
---
## Implementation Details
### 1. Application Scaffold
- Create a new binary crate `furumi-mount-windows` within the workspace.
- Add dependencies: `winfsp` (or `wfd`), `tokio`, `clap`, `tracing`, and an internal dependency on `furumi-client-core`.
### 2. Entry Point (CLI)
- In `main.rs`, configure parsing for command-line arguments and environment variables (`--server`, `--token`, `--mount`), similar to `furumi-mount-macos`.
- Initialize the gRPC connection to the server via `furumi-client-core`.
- Configure directory mounting:
- As a network drive (e.g., `Z:`).
- Or as a transparent folder within an existing NTFS filesystem (depending on driver support/flags).
### 3. VFS Implementation
- Create an `fs.rs` module.
- Implement the trait or callback structure required by WinFSP (e.g., the `WinFspFileSystem` structure).
- Action mapping:
- `GetFileInfo` / `GetSecurityByName` → gRPC `GetAttr` call.
- `ReadDirectory` → Streaming gRPC `ReadDir` call.
- `ReadFile``ReadFile` gRPC call (with support for stream chunking).
- **Crucial Part:** Translating Unix file attributes (from gRPC) into Windows File Attributes to ensure the system permits high-performance continuous stream reading (especially for media).
### 4. Installer Creation
- Write a configuration script for a Windows installer builder (e.g., `windows/setup.iss` for Inno Setup).
- Neatly bundle both `winfsp-x.y.z.msi` and `furumi-mount-windows.exe` together.
- Add Custom Actions / Logic to:
- Check the Windows Registry for an existing WinFSP installation.
- Trigger the `winfsp.msi` installation conditionally.
### 5. CI/CD Integration
- Update the GitHub Actions workflow (`docker-publish.yml` or create a dedicated release workflow).
- Add the target toolchain: `x86_64-pc-windows-msvc`.
- Add a step to compile: `cargo build --release --bin furumi-mount-windows`.
- Add a step to build the installer (e.g., `iscc setup.iss` or via `cargo-wix`).
- Output the final `setup.exe` as a GitHub Release artifact alongside other binaries.
### 6. Testing Strategy
- Write unit tests in Rust covering attribute translation and path mapping (mapping slashes `/` to backslashes `\`).
- Manual System Testing:
- Start `furumi-server` locally.
- Run the installer on a clean Windows machine (VM without pre-installed WinFSP).
- Verify that the drive mounts correctly and seamlessly.
- Launch media playback (e.g., via VLC/mpv) to ensure streaming stability over the VFS connection.