不少人的Redis从安装到现在,一直是“裸奔”状态——没有密码、没有认证,任何一个能访问到6379端口的人都能执行FLUSHALL把数据刷干净。我自己就见过好几起因Redis未授权访问导致的事故:轻则缓存被清空,重则服务器被植入挖矿程序、CPU飙到100%。设置密码这件事看着简单,但放到配置文件、Docker容器、命令行三种不同场景下,细节和坑完全不一样。今天这篇就围绕这三种场景,把原理、步骤、坑点一次性说透,适合刚接触Redis的新手,也适合已经踩过坑的运维老手。
1. 内容整体设计与思路拆解
1.1 Redis的requirepass认证机制是怎么工作的
先花半分钟把Redis的认证机制讲清楚。Redis默认情况下是不需要任何认证的,任何一个客户端连上来就能执行写命令、删除命令、甚至触发持久化和主从切换。它早期设计上默认相信“能连上Redis的人都是自己人”,所以配置文件中requirepass这一项默认是注释掉的,等于完全敞开大门。
当你把requirepass设置成某个密码之后,Redis会进入“需要认证”的模式。此时客户端连接成功,但还没有任何操作权限,必须先发送AUTH <密码>这条命令完成身份校验,才能执行后续的GET、SET、INFO等指令。如果没认证就操作,Redis会直接返回NOAUTH Authentication required.错误。认证成功后客户端也不能因此绕过密码,因为Redis是单连接校验的,换一个连接就得重新认证,不存在什么“认证一次全局放行”的机制。
这个流程背后就是一个简单但实用的鉴权模型:密码是全局的、统一的,通过在redis.conf里的一行配置,或者在运行时的一条命令,就能控制整台Redis实例的访问权。理解了这个机制,你再去看三种设置场景,其实就是“用什么方式把密码这个配置项塞给Redis”的区别,完全没有黑魔法。后面几章我都会围绕这个核心配置项展开,只是操作入口不同。
1.2 没有密码的Redis有多危险
我见过太多“Redis怎么又要密码了”的抱怨,也见过太多因为懒得上密码而付出真金白银代价的项目。不需要把问题说得玄乎,就举几个真实发生的场景:
- 公网裸连:一个项目把Redis的6379端口直接映射到公网IP上,以为是临时测试,结果一周后数据和配置全没了,被用来做挖矿的矿机。
- 内网横向渗透:攻击者通过其他漏洞进入内网后,用默认配置扫描全网所有开放6379的机器,很多机器连密码都没设,直接写入
crontab拉取恶意脚本。 - 开发环境带着问题上线:开发时图方便不设密码,上线时忘记同步配置,生产Redis对所有内网机器“开放”,任何一条
FLUSHALL都是灾难。
你可能会说:“我的Redis只监听本机,别人访问不到。”这话有一定道理,但一次配置错误、一次端口映射、一次容器网络配置不当,就能让“别人”变成“任何人”。Redis本身高性能、无客户端数量限制,这恰恰也是它被恶意盯上的原因——作为中间跳板非常顺手。所以给Redis设密码不是“过度安全”,而是底线操作,别等数据出问题才回头补课。
1.3 三种设置场景的选择逻辑
既然目标是同一个requirepass,为什么还要分三种场景?因为Redis现在部署方式实在太不一样了。同一套命令在物理机上是安全的,在容器里可能压根不生效;同一个配置文件挂在宿主机上是ok的,在容器的镜像里就可能被启动参数覆盖掉。根据我的经验,你可以按下面这个思路选:
| 场景 | 适合谁 | 原理 | 最大坑点 |
|---|---|---|---|
| 配置文件方式 | 传统部署、生产环境物理机/云服务器 | 启动时读取redis.conf中的requirepass | 配置路径不对导致静默失效 |
| Docker容器方式 | 容器化部署、本地开发、微服务 | 通过镜像默认配置或挂载配置文件传入 | Docker启动命令和配置文件的优先级问题 |
| 命令行方式 | 临时调试、快速验证、紧急处置 | 运行时用CONFIG SET直接改配置项 | 重启后配置丢失、密码进shell历史 |
选择的核心原则就一句话:配置文件和容器方式适合长期稳定使用,命令行方式适合“我先用一下”的临时场景。但命令行方式里有个CONFIG REWRITE能把临时配置写回磁盘,这块后面我会专门讲,别急着下结论。下来逐章展开每一种场景的操作细节。
2. 配置文件方式设置Redis密码
2.1 先找准redis.conf的位置
配置文件方式的第一步不是改配置,而是找到你的Redis到底读了哪个配置文件。这一步看着简单,实际翻车率极高——很多人改了半天的文件,Redis压根就没读它。
判断当前Redis实例使用的是哪个配置文件,最直接的方法是看启动脚本或启动命令。系统自带或包管理器装的Redis,默认配置文件通常在/etc/redis/redis.conf;编译安装的Redis,路径往往是安装目录下的redis.conf,比如/usr/local/redis/redis.conf。如果你完全不知道在哪,可以连上Redis执行CONFIG GET dir看一眼工作目录,但更靠谱的是找到启动时用的那个明确的“-c /xxx/redis.conf”参数。
还要提醒一句:新版Redis 7.x默认关闭了默认网卡监听,只监听127.0.0.1,如果项目需要被其他机器访问,配置文件里还得同时解决bind和protected-mode的问题。密码是访问控制的第一个环节,但千万别设了密码后把端口全部对外暴露,成为新一轮攻击入口。
2.2 修改配置文件的正确步骤
推荐用三步走的方式,看着简单但最稳妥:
- 用文本编辑器打开
redis.conf,搜索requirepass,找到这一行。
vim /etc/redis/redis.conf- 把行尾的注释符去掉,并设置密码。默认那一行通常是:
# requirepass foobared改成:
requirepass your-strong-password密码本身建议用至少16位的随机字符串,不要用123456、redis这种一看就懂的弱口令。如果担心配置文件被其他用户读到,改完后顺手把文件权限设置得严一点:
chmod 600 /etc/redis/redis.conf但注意:Redis启动时的用户要有读权限,权限收太死可能导致启动失败,这个要按实际用户来权衡。
- 重启Redis让配置生效。这里有个重要原则:不要直接
kill -9杀进程,推荐用优雅关闭:
redis-cli -a your-strong-password shutdown如果密码还没生效,就不需要-a参数;如果已经生效,就带上密码再执行shutdown。Redis收到shutdown命令后会做一次安全保存(如果开启了持久化),然后退出。之后再启动:
redis-server /etc/redis/redis.conf启动完马上验证一下:直接执行一条命令试试。
redis-cli ping此时应该返回NOAUTH Authentication required.,表示密码已经生效。然后再执行:
redis-cli -a your-strong-password ping返回PONG,说明认证成功。
2.3 配置文件方式最容易踩的3个坑
第一个坑就是我前面提到的“改了文件但没生效”。常见原因有:启动脚本里带了其他配置路径,把配置文件-c参数指向了另一个文件;或者系统服务方式启动时使用了/etc/redis/redis.conf,但你自己手动测试用的却是另一个实例。排查办法很简单:启动后执行CONFIG GET requirepass,看拿到的是不是自己设置的密码,如果不是,说明启动时就没走这个配置。
第二个坑是重启手段太粗暴。kill -9强制杀进程,如果Redis正在执行持久化或者处理主从数据,可能导致RDB文件损坏或数据丢失。所以我始终建议用redis-cli shutdown优雅退出,尤其是在生产环境。
第三个坑是被忽略的权限问题。有些团队把redis.conf丢在代码仓库里,密码明文上传到Git,这就等于把钥匙挂在门把手上。配置文件必须放服务器本地、控制访问权限,密码不要出现在提交记录里。如果已经出现泄漏,直接改密码并清理所有相关历史记录。
3. Docker容器方式设置Redis密码
3.1 方式一:启动命令直接带requirepass
Docker下第一种方式最简单,把密码作为redis-server的启动参数传进去。官方镜像启动默认命令就是redis-server,你可以在镜像名后面追加参数:
docker run -d --name redis-test \ -p 6379:6379 \ redis:7 \ redis-server --requirepass "your-strong-password"这条命令实际上等于在容器内执行redis-server --requirepass "your-strong-password"。原理是在启动Redis时,命令行参数的优先级高于配置文件,所以无论如何都会生效。
这里有个细节很多人没意识到:Docker官方镜像的redis.conf里实际上是加载了一份默认配置的,但镜像入口脚本会在启动时把额外参数追加到redis-server后面。所以你完全不需要自己准备配置文件,用这个方式最省事。
验证方式可以进容器里操作:
docker exec -it redis-test redis-cli进入交互模式后执行ping,会看到NOAUTH Authentication required.。然后:
AUTH your-strong-password返回OK,再执行ping就返回PONG了。如果不想进交互模式,也可以直接用一条命令验证:
docker exec -it redis-test redis-cli -a your-strong-password ping注意:这里密码会出现在docker exec的命令行参数里,开发环境还好,生产环境建议用后面两种更规范的方式。
3.2 方式二:挂载配置文件到容器
如果你希望把Redis的配置全部管理起来,或者要和代码仓库里的配置保持同步,那就用挂载配置文件的方式。操作上分两步:先在宿主机准备好一个redis.conf,再把文件挂载到容器内Redis读取的位置。
宿主机准备配置,假设路径是/etc/redis/redis.conf,内容里包含:
requirepass your-strong-password然后启动容器时挂载:
docker run -d --name redis-test \ -p 6379:6379 \ -v /etc/redis/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7 \ redis-server /usr/local/etc/redis/redis.conf这里的关键是:镜像内默认配置文件的路径不固定,官方镜像通常用/usr/local/etc/redis/redis.conf作为推荐挂载点。你挂载到这个路径,然后用redis-server参数显式指定该配置文件,Redis就会以它为准启动。
挂载方式最大的好处是:配置文件是你自己的,可追踪、可审计、可走配置管理流程。比如配合docker-compose.yml,可以在YAML里直接写挂载:
services: redis: image: redis:7 container_name: redis-test ports: - "6379:6379" volumes: - /etc/redis/redis.conf:/usr/local/etc/redis/redis.conf command: ["redis-server", "/usr/local/etc/redis/redis.conf"]这种方式在微服务架构里尤其常见,配置跟着部署清单走,不会出现“容器起来了但密码不知道是谁设的”这种混乱。
3.3 方式三:用docker-compose环境变量传递密码
第三种方式在编排场景中很有用:通过docker-compose.yml里的command或者environment把密码传递进去。需要注意,Redis官方镜像本身不会自动读取某个固定环境变量来设置requirepass,所以environment这块不能直接生效,还是要靠command拼接。
实际可用的写法是这样的:
services: redis: image: redis:7 container_name: redis-test ports: - "6379:6379" command: ["sh", "-c", "redis-server --requirepass $REDIS_PASSWORD"] environment: REDIS_PASSWORD: "your-strong-password"这里用环境变量REDIS_PASSWORD把密码注入容器,再通过sh -c展开成启动参数。好处是密码不直接写死在YAML的command里,运维可以直接在CI/CD或者部署平台上注入环境变量,密钥管理更干净。
这个思路对“配置与代码分离”是个很好的示范。密码属于敏感信息,如果直接写在docker-compose.yml里,git提交后所有拉到代码的人都能看到,这在多人协作的项目里非常危险。用环境变量或者Secret管理工具,密码就不在代码库中暴露了。
3.4 Docker场景的验证与连接
容器化场景下我说的验证套路要熟练掌握。首先看容器日志:
docker logs redis-test能看到Ready to accept connections之类的启动日志,说明服务起来了。然后进容器验证密码:
docker exec -it redis-test redis-cli -a your-strong-password ping返回PONG就没问题了。宿主机侧联容器试一下:
redis-cli -h 127.0.0.1 -p 6379 -a your-strong-password ping如果你在别的机器上访问,注意网络和防火墙问题。这里有个常见的坑:容器映射了6379:6379,宿主机防火墙开着也没法连接。别急着怀疑密码问题,先用nc或ping确认端口通不通,再查认证。遇到端口不通却报密码错误的场景,九成都是网络层被拦截了。
4. 命令行方式设置Redis密码
4.1 用CONFIG SET临时生效
命令行方式最大的应用场景就是:线上Redis已经跑着,我不能随便重启,需要立刻给实例加密码。这时候用运行时配置命令是最佳选择。
先连上Redis,执行:
redis-cli然后执行:
CONFIG SET requirepass your-strong-password返回OK,密码立即生效。从这一刻开始,当前连接是被保留的——这很关键,因为当前连接已经通过了认证,不会被自己踢掉,但其他所有新连接都需要密码了。你新开一个终端再执行redis-cli ping,就会收到NOAUTH Authentication required.。
这个方式的优点是完全不需要重启,对在线服务零干扰,特别适合应急处理和临时做主从切换前的本地保护。缺点也很明显:它只保存在内存中,重启后就会丢。所以如果你想永久设置,还需要配合下一步。
4.2 用CONFIG REWRITE把配置写回文件
要让临时设置的密码在重启后也生效,就必须把运行时配置持久化到配置文件。Redis提供了CONFIG REWRITE命令,可以直接把当前内存中生效的配置写回到启动时加载的配置文件里。
执行方式很简单,只要一行:
CONFIG REWRITE返回OK,说明配置已经被写盘了。这个命令的机制很像编辑配置文件后保存:Redis会把启动时加载的配置文件和当前运行配置做合并,凡是内存中有变化且配置文件支持的项,都会自动更新。
但要记住两个条件:第一,Redis启动时必须有加载配置文件(redis-server /path/redis.conf),如果启动时根本没指定配置文件,CONFIG REWRITE会报错,告诉你The server is running without a config file。第二,这个命令只对Redis自己的配置项有效,不会把命令行参数强制写入文件。所以最稳妥的组合是:用CONFIG SET改完配置后,再执行一次CONFIG REWRITE,确保重启也不丢。
在Docker场景中,如果容器是直接通过redis-server --requirepass xxx启动的,没有挂载配置文件,那你执行CONFIG REWRITE大概率会失败,因为容器内没有可写的配置文件路径。这也是为什么不建议在容器里依赖命令行持久化的原因,老老实实把配置文件和密码写到挂载卷里才是正解。
4.3 命令行验证Redis密码
命令行设置完密码之后,验证是必须的一步。最简单的方法:
redis-cli -a your-strong-password ping返回PONG,认证通过。如果密码错误,Redis会返回WRONGPASS invalid username-password pair or user is disabled.,这表示密码不对,不是网络不通。
再聊聊交互式的AUTH命令。在交互模式下执行:
redis-cli如果Redis已经有密码,先执行AUTH再操作:
AUTH your-strong-password返回OK,接下来所有命令都正常执行。这里有个老生常谈的提醒:-a参数非常方便,但它会在shell历史记录里留下密码。你敲命令的终端如果记录了历史,别人翻一下.bash_history就能看到密码。所以我更推荐用交互式的AUTH,或者至少在敏感环境下使用-a时给命令前加个空格(比如redis-cli -a xxx ping),虽然这取决于shell的ignoreboth历史配置,实际效果不一定可靠。
4.4 命令行设置密码的安全雷区
命令行方式最大的雷区就是密码泄露。举几个常见场景:
- shell历史记录:
redis-cli -a yourpassword ping直接进history,任何人拿到history文件就能看到。 - 进程列表:如果命令中包含密码,在
ps aux或容器docker inspect里也可能被看到。CONFIG SET requirepass本身不会暴露密码,因为参数在Redis内部,不入进程命令行;但redis-cli -a的密码一定在命令行里。 - 自动化脚本中硬编码:很多自动化脚本把密码写成变量,一旦脚本被上传到公共仓库,密码就公开了。
- 日志记录:某些执行过程会把命令原样打在日志里,同样等于变相泄露。
我的习惯是:凡是涉及命令行密码的操作,绝不写在需要留档的脚本里;凡是.bash_history可能被他人看到的环境,一律用交互模式或配置环境变量。密码设置完了,最好顺手rm -rf ~/.bash_history(当然这只对当前用户本次会话有效,核心是别再干这种危险动作),或者在操作完成后让运维同事立刻改一次密码。
5. 常见问题与排查技巧实录
5.1 密码设置了但重启就失效
这个问题用户问得最多。出现这个现象的原因基本就三个:你没有把设置持久化、配置文件路径发错了、或者启动参数反向覆盖了配置文件。
第一个原因好排查,你回想一下:如果用的是CONFIG SET方式,重启后丢掉太正常了,需要执行CONFIG REWRITE。如果用的是配置文件方式,那就看第二个原因。
第二个原因:文件路径问题。启动时加载的是/etc/redis/redis.conf,但你改的是/usr/local/redis/redis.conf,两码事。排查方法很简单,启动后执行:
redis-cli CONFIG GET requirepass如果拿到的值不是你设置的密码,就是路径错了。找到正确路径,改对文件,再优雅重启一次。
第三个原因比较隐蔽:有些启动脚本会在redis-server /path/redis.conf后面又加一层参数。比如脚本是redis-server /etc/redis/redis.conf --requirepass tmp,那以命令行参数为准,配置文件里的密码直接被覆盖。遇到这种情况,仔细看启动命令和系统服务的Unit文件,把正确的参数规则统一起来。
5.2 应用/Lettuce连接报NOAUTH Authentication required
设置密码后最常见的连锁反应是:代码里的连接池、Lettuce、Jedis、RedisTemplate全部报NOAUTH Authentication required.。这个错误其实在明示:服务端要求认证,但客户端没带密码。
正确做法是找到项目的Redis连接配置,把密码加进去。以Spring Data Redis为例,spring.redis.password补上;以Jedis为例,new Jedis(host, port, 0, false, password)或者用池化配置里的setPassword;以Python的redis-py为例,Redis(host=..., port=..., password=...)。
排查的时候有个小技巧:先用redis-cli手动连接一遍,确认密码本身是对的,然后再去核对项目配置。我曾经遇到过一种误导情况:项目里配置文件改了密码,但代码走的是缓存中间层,中间层还是旧连接池,一直复用旧连接,Redis密码改了之后中间层还在用旧连接,出现了NOAUTH错误,重启应用才解决。所以改完Redis密码,记得把依赖它的所有连接重建一遍,最简单粗暴的方式就是重启应用,别看只是改了个配置,连接池的旧连接不会自动重新认证。
5.3 主从复制环境下认证失败
主从架构是Redis高可用最常见的形式,而密码在这种场景下最容易出的错是:主库设了密码,从库同步时报MASTER <-> REPLICA sync started: Non AES message digest或ERR Client sent AUTH, but no password is set。
根本原因是从库在连接主库做同步时,也需要带着密码去认证,而认证信息就是从库上的masterauth配置项。你只给主库设了requirepass,没给从库配masterauth,从库自然无法同步。
解决办法是从库配置文件里加:
masterauth your-strong-password如果是在主从切换的场景,建议所有节点(包括主库自己)都配置上masterauth,因为主从切换后原主库可能会变成新主库的从库,那时它也需要用masterauth来认证连接。很多高可用方案切换失败,就是栽在这个细节上:平时主库不需要masterauth,一切正常,一旦发生切换,原主库变成从库后拿不到新主的同步数据。
在Docker部署Redis主从时也同样处理,从库容器的启动参数里加上--masterauth。不要觉得这是小问题,我见过半夜线上主库宕机,从库一直无法切主,就是因为masterauth没配,高可用方案直接失效。
5.4 关于密码安全的几条追加建议
密码只是第一道门,我给几个实操层面的额外建议。
密码强度:不要用短密码或可读单词。我说个直白的例子:一台公网Redis如果只设了六位数字密码,暴力破解脚本不用多久就能撞开。实测经验是至少16位、大小写+数字+符号混排。
不要把密码写入代码仓库:无论
application.yml、Dockerfile、docker-compose.yml还是脚本,都不要把明文密码提交进去。配置中心和密钥管理系统就是干这个用的,哪怕规模小,至少用环境变量兜底。网络层限制比密码更重要:密码挡不住所有访问,更好的方式是让Redis只监听可信的内网或本机地址,用
bind和防火墙规则封死外部访问。密码用于认证合法用户,网络层负责隔离非法访问,两者叠加才是正解。从requirepass升级到ACL:Redis 6开始引入了ACL(Access Control List),可以为不同用户分配不同权限和密码,而不是一把全局钥匙。比如应用A只能读写某个库,应用B只有只读权限。这个机制比全局
requirepass精细得多,适合多应用共享Redis实例的场景。如果你从0搭建新环境,我强烈建议直接规划ACL账号体系,而不是继续依赖单一的全局密码。
最后再分享一个实际运营中的小技巧
我个人运维Redis比较久的一个体会是:CONFIG SET和CONFIG REWRITE这种玩法虽然好用,但生产环境一定要谨慎操作,尤其不要在高峰期乱改配置。密码变更属于高敏感变更,最好走运维变更流程,预留演练时间。另外,改完密码后一定要把涉及到的所有客户端连接、监控探针、自动化脚本全部检查一遍,很多时候Redis这头看着改好了,那头定时任务却还在用旧密码重试,日志里刷一堆认证错误,排查起来反而更费神。