Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab7099220a | ||
|
|
e6663657b0 |
@@ -54,10 +54,27 @@ If the app shows "No Archives Found" and logs `EACCES: permission denied`:
|
|||||||
chmod -R 755 /path/to/archives
|
chmod -R 755 /path/to/archives
|
||||||
```
|
```
|
||||||
2. **SELinux (Fedora/RHEL/CentOS)**: Use the `:z` flag in your volume mount as shown above.
|
2. **SELinux (Fedora/RHEL/CentOS)**: Use the `:z` flag in your volume mount as shown above.
|
||||||
3. **User Mapping**: You can force the container to run as your host user:
|
3. **User Mapping**: The container runs as the non-root `node` user (UID 1000).
|
||||||
|
If your archives are readable only by another account, run as that user
|
||||||
|
instead — the container needs to *list* the archive directory, so `--x`
|
||||||
|
(traverse-only) permissions are not enough:
|
||||||
```bash
|
```bash
|
||||||
docker run --user $(id -u):$(id -g) ...
|
docker run --user $(stat -c '%u:%g' /path/to/archives) ...
|
||||||
```
|
```
|
||||||
|
In Compose:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
instaarchive:
|
||||||
|
user: "1234:1234" # a UID that can read your archives
|
||||||
|
```
|
||||||
|
|
||||||
|
### Archive Index
|
||||||
|
|
||||||
|
On first start the server walks the archive root once and caches the result,
|
||||||
|
keyed by directory mtime. This matters on network storage: for a 110k-file
|
||||||
|
archive root, listing went from ~52s per request to ~0.1s. Mount a volume at
|
||||||
|
`/cache` (or set `CACHE_DIR`) so the index survives restarts, otherwise it is
|
||||||
|
rebuilt on every start.
|
||||||
|
|
||||||
## Supported Archive Structure
|
## Supported Archive Structure
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "instaarchive-viewer",
|
"name": "instaarchive-viewer",
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "instaarchive-viewer",
|
"name": "instaarchive-viewer",
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"@vitejs/plugin-react": "^5.0.4",
|
"@vitejs/plugin-react": "^5.0.4",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "instaarchive-viewer",
|
"name": "instaarchive-viewer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port=3000 --host=0.0.0.0",
|
"dev": "vite --port=3000 --host=0.0.0.0",
|
||||||
|
|||||||
@@ -16,7 +16,23 @@ const PORT = process.env.PORT || 3001;
|
|||||||
const ARCHIVES_DIR = path.resolve(process.env.ARCHIVES_DIR || path.join(__dirname, '_sample-archives'));
|
const ARCHIVES_DIR = path.resolve(process.env.ARCHIVES_DIR || path.join(__dirname, '_sample-archives'));
|
||||||
|
|
||||||
console.log(`[Server] Initializing...`);
|
console.log(`[Server] Initializing...`);
|
||||||
console.log(`[Server] Running as user: ${os.userInfo().username} (UID: ${os.userInfo().uid}, GID: ${os.userInfo().gid})`);
|
/**
|
||||||
|
* Describe the running user without assuming it exists in /etc/passwd.
|
||||||
|
*
|
||||||
|
* `os.userInfo()` throws ENOENT for a UID with no passwd entry, which is
|
||||||
|
* exactly what happens when the container is started with `--user 1234:1234`
|
||||||
|
* (as the deployment docs suggest) — previously crashing the server at boot.
|
||||||
|
*/
|
||||||
|
const describeUser = () => {
|
||||||
|
try {
|
||||||
|
const info = os.userInfo();
|
||||||
|
return `${info.username} (UID: ${info.uid}, GID: ${info.gid})`;
|
||||||
|
} catch {
|
||||||
|
return `UID: ${typeof process.getuid === 'function' ? process.getuid() : '?'}, GID: ${typeof process.getgid === 'function' ? process.getgid() : '?'} (no passwd entry)`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`[Server] Running as user: ${describeUser()}`);
|
||||||
console.log(`[Server] Environment ARCHIVES_DIR: ${process.env.ARCHIVES_DIR}`);
|
console.log(`[Server] Environment ARCHIVES_DIR: ${process.env.ARCHIVES_DIR}`);
|
||||||
console.log(`[Server] Resolved ARCHIVES_DIR: ${ARCHIVES_DIR}`);
|
console.log(`[Server] Resolved ARCHIVES_DIR: ${ARCHIVES_DIR}`);
|
||||||
|
|
||||||
@@ -114,7 +130,7 @@ app.get('/api/archives', (req, res) => {
|
|||||||
res.json(archives);
|
res.json(archives);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code === 'EACCES') {
|
if (err.code === 'EACCES') {
|
||||||
console.error(`[API] Permission Denied! The server (UID ${os.userInfo().uid}) cannot read ${ARCHIVES_DIR}.`);
|
console.error(`[API] Permission Denied! The server (${describeUser()}) cannot read ${ARCHIVES_DIR}.`);
|
||||||
console.error(`[API] Hint: If using Linux/Docker, check folder permissions (chmod 755) or SELinux context (append :z to your volume mount).`);
|
console.error(`[API] Hint: If using Linux/Docker, check folder permissions (chmod 755) or SELinux context (append :z to your volume mount).`);
|
||||||
} else {
|
} else {
|
||||||
console.error('[API] Error listing archives:', err);
|
console.error('[API] Error listing archives:', err);
|
||||||
|
|||||||
Reference in New Issue
Block a user