diff --git a/caddyfile-docs-update.txt b/caddyfile-docs-update.txt new file mode 100644 index 0000000..505f6ea --- /dev/null +++ b/caddyfile-docs-update.txt @@ -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 \ No newline at end of file diff --git a/create-claude-matrix-user.md b/create-claude-matrix-user.md new file mode 100644 index 0000000..f86792e --- /dev/null +++ b/create-claude-matrix-user.md @@ -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! \ No newline at end of file diff --git a/get-claude-token.py b/get-claude-token.py new file mode 100755 index 0000000..6f825ae --- /dev/null +++ b/get-claude-token.py @@ -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()) \ No newline at end of file