Add Caddy authentication and Claude Matrix user setup
- Created caddyfile-docs-update.txt with Caddy basic auth configuration - Fixed documentation path from /home/klas/langmem-docs to /home/klas/langmem/docs - Added basic auth with credentials: langmem / langmem2025 - Created create-claude-matrix-user.md with user creation instructions - Added get-claude-token.py script for automated Matrix setup - Includes token retrieval, room joining, and configuration export Manual steps required: 1. Update /etc/caddy/Caddyfile with new docs.klas.chat config 2. Reload Caddy: sudo systemctl reload caddy 3. Create Claude Matrix user via admin panel 4. Run get-claude-token.py to complete setup 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
40
caddyfile-docs-update.txt
Normal file
40
caddyfile-docs-update.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Updated docs.klas.chat configuration with authentication
|
||||||
|
# Replace the existing docs.klas.chat block in /etc/caddy/Caddyfile with this:
|
||||||
|
|
||||||
|
docs.klas.chat {
|
||||||
|
tls /certs/klas.chat/fullchain.cer /certs/klas.chat/klas.chat.key
|
||||||
|
|
||||||
|
# Basic Authentication
|
||||||
|
basicauth * {
|
||||||
|
langmem $2a$14$.1fx02QwkkmfezhZMLE4Iu2N/ub5vwDSAtcH9lAa5z11ChjiYy1PG
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
header {
|
||||||
|
X-Frame-Options "DENY"
|
||||||
|
X-Content-Type-Options "nosniff"
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
|
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||||
|
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data: https:; font-src 'self' data:;"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file serving - UPDATED PATH
|
||||||
|
root * /home/klas/langmem/docs
|
||||||
|
file_server
|
||||||
|
|
||||||
|
# SPA routing fallback for clean URLs
|
||||||
|
try_files {path} {path}/ /index.html
|
||||||
|
|
||||||
|
# Enable compression
|
||||||
|
encode gzip
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
@static {
|
||||||
|
path *.css *.js *.png *.jpg *.jpeg *.gif *.svg *.ico *.woff *.woff2
|
||||||
|
}
|
||||||
|
|
||||||
|
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Credentials: langmem / langmem2025
|
||||||
47
create-claude-matrix-user.md
Normal file
47
create-claude-matrix-user.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Creating Claude Matrix User
|
||||||
|
|
||||||
|
Since Matrix registration is disabled, you'll need to create the Claude user manually using admin tools.
|
||||||
|
|
||||||
|
## Option 1: Synapse Admin Panel
|
||||||
|
|
||||||
|
1. **Access Synapse Admin**: https://synapse.klas.chat/admin
|
||||||
|
2. **Login with admin credentials**
|
||||||
|
3. **Go to Users section**
|
||||||
|
4. **Create new user:**
|
||||||
|
- **Username**: `claude`
|
||||||
|
- **Password**: `claude_assistant_2025`
|
||||||
|
- **Display Name**: `Claude Assistant`
|
||||||
|
- **Admin**: `No`
|
||||||
|
|
||||||
|
## Option 2: Command Line (if you have access to Synapse container)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Access synapse container
|
||||||
|
docker exec -it synapse /bin/bash
|
||||||
|
|
||||||
|
# Create user using register_new_matrix_user
|
||||||
|
register_new_matrix_user -u claude -p claude_assistant_2025 -c /data/homeserver.yaml https://matrix.klas.chat
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 3: Database Direct (if needed)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Connect to Matrix database and insert user manually
|
||||||
|
-- This requires knowledge of your Matrix database structure
|
||||||
|
```
|
||||||
|
|
||||||
|
## After Creating the User
|
||||||
|
|
||||||
|
1. **Get access token** for the claude user
|
||||||
|
2. **Join Home Assistant room** using the new account
|
||||||
|
3. **Update Claude's global configuration** with new credentials
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Once you've created the Claude user, I'll:
|
||||||
|
1. Get the access token
|
||||||
|
2. Join the Home Assistant room
|
||||||
|
3. Update my global Matrix configuration
|
||||||
|
4. Test sending messages as the Claude user
|
||||||
|
|
||||||
|
Let me know when the user is created!
|
||||||
156
get-claude-token.py
Executable file
156
get-claude-token.py
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Get access token for Claude Matrix user and join Home Assistant room
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import httpx
|
||||||
|
import json
|
||||||
|
|
||||||
|
MATRIX_HOMESERVER = "https://matrix.klas.chat"
|
||||||
|
CLAUDE_USERNAME = "claude"
|
||||||
|
CLAUDE_PASSWORD = "claude_assistant_2025"
|
||||||
|
HOME_ASSISTANT_ROOM_ID = "!xZkScMybPseErYMJDz:matrix.klas.chat"
|
||||||
|
|
||||||
|
async def login_and_get_token():
|
||||||
|
"""Login as Claude user and get access token"""
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
# Login request
|
||||||
|
response = await client.post(
|
||||||
|
f"{MATRIX_HOMESERVER}/_matrix/client/v3/login",
|
||||||
|
json={
|
||||||
|
"type": "m.login.password",
|
||||||
|
"user": CLAUDE_USERNAME,
|
||||||
|
"password": CLAUDE_PASSWORD
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
access_token = data["access_token"]
|
||||||
|
user_id = data["user_id"]
|
||||||
|
|
||||||
|
print(f"✅ Successfully logged in as {user_id}")
|
||||||
|
print(f"🔑 Access Token: {access_token}")
|
||||||
|
|
||||||
|
return access_token, user_id
|
||||||
|
else:
|
||||||
|
print(f"❌ Login failed: {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error during login: {e}")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
async def join_home_assistant_room(access_token):
|
||||||
|
"""Join the Home Assistant room"""
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
headers = {"Authorization": f"Bearer {access_token}"}
|
||||||
|
|
||||||
|
# Join room
|
||||||
|
response = await client.post(
|
||||||
|
f"{MATRIX_HOMESERVER}/_matrix/client/v3/join/{HOME_ASSISTANT_ROOM_ID}",
|
||||||
|
headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f"✅ Successfully joined Home Assistant room")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Failed to join room: {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error joining room: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def send_test_message(access_token):
|
||||||
|
"""Send a test message to verify everything works"""
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {access_token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
message = "🤖 Hello! Claude Assistant is now connected to Matrix and ready to send you updates about your projects."
|
||||||
|
|
||||||
|
response = await client.post(
|
||||||
|
f"{MATRIX_HOMESERVER}/_matrix/client/v3/rooms/{HOME_ASSISTANT_ROOM_ID}/send/m.room.message",
|
||||||
|
headers=headers,
|
||||||
|
json={
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": message
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f"✅ Test message sent successfully!")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Failed to send test message: {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error sending test message: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Main function"""
|
||||||
|
print("🤖 Setting up Claude Matrix Integration")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Step 1: Login and get token
|
||||||
|
print("\n1. Logging in as Claude user...")
|
||||||
|
access_token, user_id = await login_and_get_token()
|
||||||
|
|
||||||
|
if not access_token:
|
||||||
|
print("\n❌ Cannot proceed without access token.")
|
||||||
|
print("Make sure the Claude user has been created first!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Step 2: Join Home Assistant room
|
||||||
|
print("\n2. Joining Home Assistant room...")
|
||||||
|
joined = await join_home_assistant_room(access_token)
|
||||||
|
|
||||||
|
if not joined:
|
||||||
|
print("\n❌ Cannot proceed without joining the room.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Step 3: Send test message
|
||||||
|
print("\n3. Sending test message...")
|
||||||
|
message_sent = await send_test_message(access_token)
|
||||||
|
|
||||||
|
# Step 4: Output configuration for Claude
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("🎉 Claude Matrix Setup Complete!")
|
||||||
|
print("\n📋 Configuration for Claude's global config:")
|
||||||
|
print(f" Matrix Homeserver: {MATRIX_HOMESERVER}")
|
||||||
|
print(f" Claude User ID: {user_id}")
|
||||||
|
print(f" Claude Access Token: {access_token}")
|
||||||
|
print(f" Home Assistant Room: {HOME_ASSISTANT_ROOM_ID}")
|
||||||
|
|
||||||
|
# Save to file for easy copying
|
||||||
|
config = {
|
||||||
|
"matrix_homeserver": MATRIX_HOMESERVER,
|
||||||
|
"claude_user_id": user_id,
|
||||||
|
"claude_access_token": access_token,
|
||||||
|
"home_assistant_room_id": HOME_ASSISTANT_ROOM_ID,
|
||||||
|
"credentials": {
|
||||||
|
"username": CLAUDE_USERNAME,
|
||||||
|
"password": CLAUDE_PASSWORD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with open("/home/klas/langmem/claude-matrix-config.json", "w") as f:
|
||||||
|
json.dump(config, f, indent=2)
|
||||||
|
|
||||||
|
print(f"\n💾 Configuration saved to: /home/klas/langmem/claude-matrix-config.json")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
Reference in New Issue
Block a user