Skip to content

Commit c301b7f

Browse files
committed
Add Docker Compose configuration and Go module files for ClamAV API
0 parents  commit c301b7f

File tree

9 files changed

+1539
-0
lines changed

9 files changed

+1539
-0
lines changed

.example.env

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
NODE_ENV=production
2+
APP_PORT=3000
3+
APP_FORM_KEY=FILES
4+
APP_MAX_FILE_SIZE=26214400
5+
APP_MAX_FILES_NUMBER=4
6+
CLAMD_IP=127.0.0.1
7+
CLAMD_PORT=3310
8+
CLAMD_TIMEOUT=60000
9+
APP_MORGAN_LOG_FORMAT=combined
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
tags: [ 'v*' ]
7+
pull_request:
8+
branches: [ "main" ]
9+
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: ${{ github.repository }}
13+
14+
jobs:
15+
build-and-push:
16+
name: Build and Push
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
id-token: write
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Install cosign
28+
if: github.event_name != 'pull_request'
29+
uses: sigstore/cosign-installer@v3.1.1
30+
with:
31+
cosign-release: 'v2.2.0'
32+
33+
- name: Set up Docker Buildx
34+
uses: docker/setup-buildx-action@v3
35+
36+
- name: Log in to the Container registry
37+
uses: docker/login-action@v3
38+
with:
39+
registry: ${{ env.REGISTRY }}
40+
username: ${{ github.actor }}
41+
password: ${{ secrets.GITHUB_TOKEN }}
42+
43+
- name: Extract Docker metadata
44+
id: meta
45+
uses: docker/metadata-action@v5
46+
with:
47+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
48+
tags: |
49+
type=schedule
50+
type=ref,event=branch
51+
type=ref,event=pr
52+
type=semver,pattern={{version}}
53+
type=semver,pattern={{major}}.{{minor}}
54+
type=semver,pattern={{major}}
55+
type=sha
56+
57+
- name: Build and push Docker image
58+
id: build-and-push
59+
uses: docker/build-push-action@v5
60+
with:
61+
context: .
62+
push: ${{ github.event_name != 'pull_request' }}
63+
tags: ${{ steps.meta.outputs.tags }}
64+
labels: ${{ steps.meta.outputs.labels }}
65+
cache-from: type=gha
66+
cache-to: type=gha,mode=max
67+
68+
- name: Sign the published Docker image
69+
if: ${{ github.event_name != 'pull_request' }}
70+
env:
71+
TAGS: ${{ steps.meta.outputs.tags }}
72+
DIGEST: ${{ steps.build-and-push.outputs.digest }}
73+
run: |
74+
echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}

Dockerfile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Build stage
2+
FROM golang:1.24-bookworm AS builder
3+
4+
LABEL maintainer="Sai Sanjay"
5+
6+
WORKDIR /app
7+
8+
# Copy go mod files
9+
COPY go.mod go.sum ./
10+
11+
# Download dependencies
12+
RUN go mod download
13+
14+
# Copy source code
15+
COPY . .
16+
17+
# Build the application
18+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/clamav
19+
20+
# Final stage
21+
FROM alpine:3.19
22+
23+
# Add retry logic and better error handling for package installation
24+
RUN set -eux; \
25+
# Update package index
26+
apk update; \
27+
# Install packages with retry logic
28+
for i in 1 2 3; do \
29+
apk --no-cache add ca-certificates tzdata wget && break || \
30+
(echo "Attempt $i failed, retrying..." && sleep $((i * 2))); \
31+
done; \
32+
# Verify installation
33+
which wget || (echo "wget installation failed" && exit 1)
34+
35+
WORKDIR /root/
36+
37+
# Copy the binary from builder stage
38+
COPY --from=builder /app/main .
39+
40+
# Copy .env file if it exists
41+
COPY --from=builder /app/.env* ./
42+
43+
# Create non-root user
44+
RUN addgroup -g 1001 -S appuser && \
45+
adduser -S -D -H -u 1001 -h /root -s /sbin/nologin -G appuser appuser
46+
47+
# Change ownership
48+
RUN chown -R appuser:appuser /root
49+
50+
USER appuser
51+
52+
EXPOSE 3000
53+
54+
CMD ["./main"]

README.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# ClamAV REST API - Go Implementation
2+
3+
This is a Go/Gin-based implementation of the original Node.js ClamAV REST API. It provides the same functionality with improved performance and lower memory usage.
4+
5+
## Features
6+
7+
- **File Scanning**: Upload files for virus scanning via REST API
8+
- **Version Information**: Get ClamAV version information
9+
- **Database Signatures**: Check local and remote virus database versions
10+
- **Multiple File Support**: Scan multiple files in a single request
11+
- **Docker Support**: Ready-to-use Docker containers
12+
- **CORS Enabled**: Cross-origin resource sharing support
13+
14+
## API Endpoints
15+
16+
- `POST /api/v1/scan` - Scan uploaded files
17+
- `GET /api/v1/version` - Get ClamAV version
18+
- `GET /api/v1/dbsignatures` - Get database signature information
19+
20+
## Quick Start
21+
22+
### Prerequisites
23+
24+
- Go 1.21 or higher
25+
- Running ClamAV daemon (clamd)
26+
27+
### Running with Docker Compose (Recommended)
28+
29+
```bash
30+
# Clone and build
31+
git clone <your-repo>
32+
cd clamav-rest-api-go
33+
docker-compose up -d
34+
```
35+
36+
### Running Locally
37+
38+
```bash
39+
# Install dependencies
40+
go mod tidy
41+
42+
# Copy environment file
43+
cp .env.example .env
44+
45+
# Edit .env file with your settings
46+
# Start the server
47+
go run main.go
48+
```
49+
50+
### Building
51+
52+
```bash
53+
# Build binary
54+
go build -o clamav-rest-api
55+
56+
# Run binary
57+
./clamav-rest-api
58+
```
59+
60+
## Configuration
61+
62+
Configure via environment variables or `.env` file:
63+
64+
- `APP_PORT` - Server port (default: 3000)
65+
- `APP_FORM_KEY` - Form field name for file uploads (default: FILES)
66+
- `APP_MAX_FILE_SIZE` - Maximum file size in bytes (default: 26214400)
67+
- `APP_MAX_FILES_NUMBER` - Maximum number of files per request (default: 4)
68+
- `CLAMD_IP` - ClamAV daemon IP address (default: 127.0.0.1)
69+
- `CLAMD_PORT` - ClamAV daemon port (default: 3310)
70+
- `CLAMD_TIMEOUT` - Connection timeout in milliseconds (default: 60000)
71+
- `NODE_ENV` - Environment mode (default: development)
72+
73+
## Usage Examples
74+
75+
### cURL Example
76+
77+
```bash
78+
curl -X POST http://localhost:3000/api/v1/scan \
79+
-F "FILES=@test1.txt" \
80+
-F "FILES=@test2.txt"
81+
```
82+
83+
### Response Format
84+
85+
```json
86+
{
87+
"success": true,
88+
"data": {
89+
"result": [
90+
{
91+
"name": "test1.txt",
92+
"is_infected": false,
93+
"viruses": []
94+
},
95+
{
96+
"name": "test2.txt",
97+
"is_infected": true,
98+
"viruses": ["Win.Test.EICAR_HDB-1"]
99+
}
100+
]
101+
}
102+
}
103+
```
104+
105+
### Version Check
106+
107+
```bash
108+
curl http://localhost:3000/api/v1/version
109+
```
110+
111+
### Database Signatures
112+
113+
```bash
114+
curl http://localhost:3000/api/v1/dbsignatures
115+
```
116+
117+
## Differences from Node.js Version
118+
119+
1. **Performance**: Significantly faster startup and lower memory usage
120+
2. **Concurrency**: Better handling of concurrent requests
121+
3. **Dependencies**: Fewer external dependencies
122+
4. **Binary**: Compiles to a single binary for easy deployment
123+
5. **Error Handling**: More robust error handling and logging
124+
125+
## Docker Images
126+
127+
### Building Your Own Image
128+
129+
```bash
130+
docker build -t clamav-rest-api-go .
131+
```
132+
133+
### Running with Docker
134+
135+
```bash
136+
docker run -d -p 8080:3000 \
137+
-e APP_PORT=3000 \
138+
-e CLAMD_IP=your-clamav-host \
139+
-e APP_FORM_KEY=FILES \
140+
clamav-rest-api-go
141+
```
142+
143+
## Testing
144+
145+
### Test File Creation
146+
147+
```bash
148+
# Create a test file
149+
echo "Hello World" > test.txt
150+
151+
# Create EICAR test virus file (harmless test file)
152+
echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > eicar.txt
153+
```
154+
155+
### Manual Testing
156+
157+
```bash
158+
# Test clean file
159+
curl -X POST http://localhost:3000/api/v1/scan -F "FILES=@test.txt"
160+
161+
# Test virus file (should be detected)
162+
curl -X POST http://localhost:3000/api/v1/scan -F "FILES=@eicar.txt"
163+
```
164+
165+
## Health Checks
166+
167+
The application includes health check endpoints for monitoring:
168+
169+
```bash
170+
# Check if service is running
171+
curl http://localhost:3000/api/v1/version
172+
```
173+
174+
## Logging
175+
176+
The application uses Gin's built-in logging. In production mode, logs are minimized for better performance.
177+
178+
## Security Considerations
179+
180+
- File size limits are enforced
181+
- Maximum number of files per request is limited
182+
- Input validation on all endpoints
183+
- No file persistence (files are scanned in memory)
184+
- Non-root user in Docker container
185+
186+
## Performance Notes
187+
188+
- Uses connection pooling for ClamAV connections
189+
- Efficient memory usage with streaming
190+
- Concurrent file processing
191+
- Optimized Docker image with multi-stage builds
192+
193+
## Troubleshooting
194+
195+
### Common Issues
196+
197+
1. **Cannot connect to ClamAV**: Ensure ClamAV daemon is running and accessible
198+
2. **File size errors**: Check `APP_MAX_FILE_SIZE` setting
199+
3. **Too many files**: Check `APP_MAX_FILES_NUMBER` setting
200+
4. **Port conflicts**: Change `APP_PORT` if port 3000 is in use
201+
202+
### Debug Mode
203+
204+
Set `NODE_ENV=development` for verbose logging.
205+
206+
## License
207+
208+
MIT License

0 commit comments

Comments
 (0)